|
| 1 | +/* |
| 2 | + Copyright (c) 2020 Raspberry Pi (Trading) Ltd. |
| 3 | +
|
| 4 | + SPDX-License-Identifier: BSD-3-Clause |
| 5 | +*/ |
| 6 | + |
| 7 | +#include <stdio.h> |
| 8 | +#include <stdarg.h> |
| 9 | +#include <sys/stat.h> |
| 10 | +#include <sys/time.h> |
| 11 | +#include <sys/times.h> |
| 12 | +#include <time.h> |
| 13 | +#include <unistd.h> |
| 14 | +#if PICO_ENTER_USB_BOOT_ON_EXIT |
| 15 | +#include "pico/bootrom.h" |
| 16 | +#endif |
| 17 | +#include "pico/time.h" |
| 18 | +#include "pico/runtime_init.h" |
| 19 | + |
| 20 | +#if LIB_PICO_PRINTF_PICO |
| 21 | +#include "pico/printf.h" |
| 22 | +#else |
| 23 | +#define weak_raw_printf printf |
| 24 | +#define weak_raw_vprintf vprintf |
| 25 | +#endif |
| 26 | +#if LIB_PICO_STDIO |
| 27 | +#include "pico/stdio.h" |
| 28 | +#endif |
| 29 | + |
| 30 | +#if PICO_ENTER_USB_BOOT_ON_EXIT |
| 31 | +#include "pico/bootrom.h" |
| 32 | +#endif |
| 33 | + |
| 34 | +extern char __StackLimit; /* Set by linker. */ |
| 35 | + |
| 36 | +#define STDIO_HANDLE_STDIN 0 |
| 37 | +#define STDIO_HANDLE_STDOUT 1 |
| 38 | +#define STDIO_HANDLE_STDERR 2 |
| 39 | + |
| 40 | +void __attribute__((noreturn)) __weak _exit(__unused int status) { |
| 41 | +#if PICO_ENTER_USB_BOOT_ON_EXIT |
| 42 | + reset_usb_boot(0, 0); |
| 43 | +#else |
| 44 | + while (1) { |
| 45 | + __breakpoint(); |
| 46 | + } |
| 47 | +#endif |
| 48 | +} |
| 49 | + |
| 50 | +__weak void *_sbrk(int incr) { |
| 51 | + extern char end; /* Set by linker. */ |
| 52 | + static char *heap_end; |
| 53 | + char *prev_heap_end; |
| 54 | + |
| 55 | + if (heap_end == 0) { |
| 56 | + heap_end = &end; |
| 57 | + } |
| 58 | + |
| 59 | + prev_heap_end = heap_end; |
| 60 | + char *next_heap_end = heap_end + incr; |
| 61 | + |
| 62 | + if (__builtin_expect(next_heap_end > (&__StackLimit), false)) { |
| 63 | +#if PICO_USE_OPTIMISTIC_SBRK |
| 64 | + if (heap_end == &__StackLimit) { |
| 65 | + // errno = ENOMEM; |
| 66 | + return (char *) -1; |
| 67 | + } |
| 68 | + next_heap_end = &__StackLimit; |
| 69 | +#else |
| 70 | + return (char *) -1; |
| 71 | +#endif |
| 72 | + } |
| 73 | + |
| 74 | + heap_end = next_heap_end; |
| 75 | + return (void *) prev_heap_end; |
| 76 | +} |
| 77 | +#if 0 |
| 78 | +static int64_t epoch_time_us_since_boot; |
| 79 | + |
| 80 | +__weak int _gettimeofday(struct timeval *__restrict tv, __unused void *__restrict tz) { |
| 81 | + if (tv) { |
| 82 | + int64_t us_since_epoch = ((int64_t)to_us_since_boot(get_absolute_time())) - epoch_time_us_since_boot; |
| 83 | + tv->tv_sec = (time_t)(us_since_epoch / 1000000); |
| 84 | + tv->tv_usec = (suseconds_t)(us_since_epoch % 1000000); |
| 85 | + } |
| 86 | + return 0; |
| 87 | +} |
| 88 | + |
| 89 | +__weak int settimeofday(__unused const struct timeval *tv, __unused const struct timezone *tz) { |
| 90 | + if (tv) { |
| 91 | + int64_t us_since_epoch = tv->tv_sec * 1000000 + tv->tv_usec; |
| 92 | + epoch_time_us_since_boot = (int64_t)to_us_since_boot(get_absolute_time()) - us_since_epoch; |
| 93 | + } |
| 94 | + return 0; |
| 95 | +} |
| 96 | + |
| 97 | +__weak int _times(struct tms *tms) { |
| 98 | +#if CLOCKS_PER_SEC >= 1000000 |
| 99 | + tms->tms_utime = (clock_t)(to_us_since_boot(get_absolute_time()) * (CLOCKS_PER_SEC / 1000000)); |
| 100 | +#else |
| 101 | + tms->tms_utime = (clock_t)(to_us_since_boot(get_absolute_time()) / (1000000 / CLOCKS_PER_SEC)); |
| 102 | +#endif |
| 103 | + tms->tms_stime = 0; |
| 104 | + tms->tms_cutime = 0; |
| 105 | + tms->tms_cstime = 0; |
| 106 | + return 0; |
| 107 | +} |
| 108 | + |
| 109 | +__weak pid_t _getpid(void) { |
| 110 | + return 0; |
| 111 | +} |
| 112 | + |
| 113 | +__weak int _kill(__unused pid_t pid, __unused int sig) { |
| 114 | + return -1; |
| 115 | +} |
| 116 | + |
| 117 | +int __attribute__((weak)) _read(int handle, char *buffer, int length) { |
| 118 | +#if LIB_PICO_STDIO |
| 119 | + if (handle == STDIO_HANDLE_STDIN) { |
| 120 | + return stdio_get_until(buffer, length, at_the_end_of_time); |
| 121 | + } |
| 122 | +#endif |
| 123 | + return -1; |
| 124 | +} |
| 125 | + |
| 126 | +int __attribute__((weak)) _write(int handle, char *buffer, int length) { |
| 127 | +#if LIB_PICO_STDIO |
| 128 | + if (handle == STDIO_HANDLE_STDOUT || handle == STDIO_HANDLE_STDERR) { |
| 129 | + stdio_put_string(buffer, length, false, true); |
| 130 | + return length; |
| 131 | + } |
| 132 | +#endif |
| 133 | + return -1; |
| 134 | +} |
| 135 | + |
| 136 | +int __attribute__((weak)) _open(__unused const char *fn, __unused int oflag, ...) { |
| 137 | + return -1; |
| 138 | +} |
| 139 | + |
| 140 | +int __attribute__((weak)) _close(__unused int fd) { |
| 141 | + return -1; |
| 142 | +} |
| 143 | + |
| 144 | +off_t __attribute__((weak)) _lseek(__unused int fd, __unused off_t pos, __unused int whence) { |
| 145 | + return -1; |
| 146 | +} |
| 147 | + |
| 148 | +int __attribute__((weak)) _fstat(__unused int fd, __unused struct stat *buf) { |
| 149 | + return -1; |
| 150 | +} |
| 151 | + |
| 152 | +int __attribute__((weak)) _isatty(int fd) { |
| 153 | + return fd == STDIO_HANDLE_STDIN || fd == STDIO_HANDLE_STDOUT || fd == STDIO_HANDLE_STDERR; |
| 154 | +} |
| 155 | + |
| 156 | +// exit is not useful... no desire to pull in __call_exitprocs |
| 157 | +void exit(int status) { |
| 158 | + _exit(status); |
| 159 | +} |
| 160 | + |
| 161 | +// incorrect warning from GCC 6 |
| 162 | +GCC_Pragma("GCC diagnostic push") |
| 163 | +GCC_Pragma("GCC diagnostic ignored \"-Wsuggest-attribute=format\"") |
| 164 | +void __weak __assert_func(const char *file, int line, const char *func, const char *failedexpr) { |
| 165 | + weak_raw_printf("assertion \"%s\" failed: file \"%s\", line %d%s%s\n", |
| 166 | + failedexpr, file, line, func ? ", function: " : "", |
| 167 | + func ? func : ""); |
| 168 | + |
| 169 | + _exit(1); |
| 170 | +} |
| 171 | +GCC_Pragma("GCC diagnostic pop") |
| 172 | +#endif |
| 173 | +void runtime_init(void) { |
| 174 | +#ifndef NDEBUG |
| 175 | + if (__get_current_exception()) { |
| 176 | + // crap; started in exception handler |
| 177 | + __breakpoint(); |
| 178 | + } |
| 179 | +#endif |
| 180 | + |
| 181 | +#if !PICO_RUNTIME_SKIP_INIT_PER_CORE_INSTALL_STACK_GUARD |
| 182 | + // install core0 stack guard |
| 183 | + extern char __StackBottom; |
| 184 | + runtime_init_per_core_install_stack_guard(&__StackBottom); |
| 185 | +#endif |
| 186 | + |
| 187 | + // todo maybe we want to do this in the future, but it does stuff like register_tm_clones |
| 188 | + // which we didn't do in previous SDKs |
| 189 | + //extern void __libc_init_array(void); |
| 190 | + //__libc_init_array(); |
| 191 | + |
| 192 | + // ... so instead just do the __preinit_array |
| 193 | + runtime_run_initializers(); |
| 194 | + // ... and the __init_array |
| 195 | + extern void (*__init_array_start)(void); |
| 196 | + extern void (*__init_array_end)(void); |
| 197 | + for (void (**p)(void) = &__init_array_start; p < &__init_array_end; ++p) { |
| 198 | + (*p)(); |
| 199 | + } |
| 200 | +} |
0 commit comments