2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
4 * SPDX-License-Identifier: BSD-3-Clause
11 #include <sys/times.h>
14 #if PICO_ENTER_USB_BOOT_ON_EXIT
15 #include "pico/bootrom.h"
17 #include "pico/time.h"
18 #include "pico/runtime_init.h"
20 #if LIB_PICO_PRINTF_PICO
21 #include "pico/printf.h"
23 #define weak_raw_printf printf
24 #define weak_raw_vprintf vprintf
27 #include "pico/stdio.h"
30 #if PICO_ENTER_USB_BOOT_ON_EXIT
31 #include "pico/bootrom.h"
34 extern char __StackLimit
; /* Set by linker. */
36 #define STDIO_HANDLE_STDIN 0
37 #define STDIO_HANDLE_STDOUT 1
38 #define STDIO_HANDLE_STDERR 2
40 void __attribute__((noreturn
)) __weak
_exit(__unused
int status
) {
41 #if PICO_ENTER_USB_BOOT_ON_EXIT
50 __weak
void *_sbrk(int incr
) {
51 extern char end
; /* Set by linker. */
52 static char *heap_end
;
58 prev_heap_end
= heap_end
;
59 char *next_heap_end
= heap_end
+ incr
;
61 if (__builtin_expect(next_heap_end
> (&__StackLimit
), false)) {
62 #if PICO_USE_OPTIMISTIC_SBRK
63 if (heap_end
== &__StackLimit
) {
67 next_heap_end
= &__StackLimit
;
73 heap_end
= next_heap_end
;
74 return (void *) prev_heap_end
;
77 static int64_t epoch_time_us_since_boot
;
79 __weak
int _gettimeofday (struct timeval
*__restrict tv
, __unused
void *__restrict tz
) {
81 int64_t us_since_epoch
= ((int64_t)to_us_since_boot(get_absolute_time())) - epoch_time_us_since_boot
;
82 tv
->tv_sec
= (time_t)(us_since_epoch
/ 1000000);
83 tv
->tv_usec
= (suseconds_t
)(us_since_epoch
% 1000000);
88 __weak
int settimeofday(__unused
const struct timeval
*tv
, __unused
const struct timezone
*tz
) {
90 int64_t us_since_epoch
= tv
->tv_sec
* 1000000 + tv
->tv_usec
;
91 epoch_time_us_since_boot
= (int64_t)to_us_since_boot(get_absolute_time()) - us_since_epoch
;
96 __weak
int _times(struct tms
*tms
) {
97 #if CLOCKS_PER_SEC >= 1000000
98 tms
->tms_utime
= (clock_t)(to_us_since_boot(get_absolute_time()) * (CLOCKS_PER_SEC
/ 1000000));
100 tms
->tms_utime
= (clock_t)(to_us_since_boot(get_absolute_time()) / (1000000 / CLOCKS_PER_SEC
));
108 __weak pid_t
_getpid(void) {
112 __weak
int _kill(__unused pid_t pid
, __unused
int sig
) {
116 int __attribute__((weak
)) _read(int handle
, char *buffer
, int length
) {
118 if (handle
== STDIO_HANDLE_STDIN
) {
119 return stdio_get_until(buffer
, length
, at_the_end_of_time
);
125 int __attribute__((weak
)) _write(int handle
, char *buffer
, int length
) {
127 if (handle
== STDIO_HANDLE_STDOUT
|| handle
== STDIO_HANDLE_STDERR
) {
128 stdio_put_string(buffer
, length
, false, true);
135 int __attribute__((weak
)) _open(__unused
const char *fn
, __unused
int oflag
, ...) {
139 int __attribute__((weak
)) _close(__unused
int fd
) {
143 off_t
__attribute__((weak
)) _lseek(__unused
int fd
, __unused off_t pos
, __unused
int whence
) {
147 int __attribute__((weak
)) _fstat(__unused
int fd
, __unused
struct stat
*buf
) {
151 int __attribute__((weak
)) _isatty(int fd
) {
152 return fd
== STDIO_HANDLE_STDIN
|| fd
== STDIO_HANDLE_STDOUT
|| fd
== STDIO_HANDLE_STDERR
;
155 // exit is not useful... no desire to pull in __call_exitprocs
156 void exit(int status
) {
160 // incorrect warning from GCC 6
161 GCC_Pragma("GCC diagnostic push")
162 GCC_Pragma("GCC diagnostic ignored \"-Wsuggest-attribute=format\"")
163 void __weak
__assert_func(const char *file
, int line
, const char *func
, const char *failedexpr
) {
164 weak_raw_printf("assertion \"%s\" failed: file \"%s\", line %d%s%s\n",
165 failedexpr
, file
, line
, func
? ", function: " : "",
170 GCC_Pragma("GCC diagnostic pop")
172 void runtime_init(void) {
174 if (__get_current_exception()) {
175 // crap; started in exception handler
180 #if !PICO_RUNTIME_SKIP_INIT_PER_CORE_INSTALL_STACK_GUARD
181 // install core0 stack guard
182 extern char __StackBottom
;
183 runtime_init_per_core_install_stack_guard(&__StackBottom
);
186 // todo maybe we want to do this in the future, but it does stuff like register_tm_clones
187 // which we didn't do in previous SDKs
188 //extern void __libc_init_array(void);
189 //__libc_init_array();
191 // ... so instead just do the __preinit_array
192 runtime_run_initializers();
193 // ... and the __init_array
194 extern void (*__init_array_start
)(void);
195 extern void (*__init_array_end
)(void);
196 for (void (**p
)(void) = &__init_array_start
; p
< &__init_array_end
; ++p
) {