/* * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "pico/runtime_init.h" #include "pico/stdio.h" #include "pico/time.h" #if PICO_ENTER_USB_BOOT_ON_EXIT #include "pico/bootrom.h" #endif // These functions are defined by POSIX and not C standard. static int64_t epoch_time_us_since_boot; int gettimeofday(struct timeval *__restrict tv, __unused struct timezone *__restrict tz) { if (tv) { int64_t us_since_epoch = ((int64_t)to_us_since_boot(get_absolute_time())) - epoch_time_us_since_boot; tv->tv_sec = (time_t)(us_since_epoch / 1000000); tv->tv_usec = (suseconds_t)(us_since_epoch % 1000000); } return 0; } int settimeofday(__unused const struct timeval *tv, __unused const struct timezone *tz) { if (tv) { int64_t us_since_epoch = tv->tv_sec * 1000000 + tv->tv_usec; epoch_time_us_since_boot = (int64_t)to_us_since_boot(get_absolute_time()) - us_since_epoch; } return 0; } // TODO: This should be a thread-local variable. int errno; int *__llvm_libc_errno(void) { return &errno; } struct __llvm_libc_stdio_cookie {}; struct __llvm_libc_stdio_cookie __llvm_libc_stdin_cookie; struct __llvm_libc_stdio_cookie __llvm_libc_stdout_cookie; struct __llvm_libc_stdio_cookie __llvm_libc_stderr_cookie; ssize_t __llvm_libc_stdio_read(__unused void *cookie, char *buf, size_t size) { for (size_t i = 0; i < size; i++) { buf[i] = getchar_timeout_us(0); } return size; } ssize_t __llvm_libc_stdio_write(__unused void *cookie, const char *buf, size_t size) { // TODO: We would ideally use `stdio_put_string` from pico_stdio. for (size_t i = 0; i < size; i++) { putchar_raw(buf[i]); } return size; } void __cxa_finalize(__unused void *dso) {} void __attribute__((noreturn)) __llvm_libc_exit(__unused int status) { #if PICO_ENTER_USB_BOOT_ON_EXIT reset_usb_boot(0,0); #else while (1) { __breakpoint(); } #endif } void _exit(int) __attribute__((noreturn, alias("__llvm_libc_exit"))); void runtime_init(void) { #ifndef NDEBUG if (__get_current_exception()) { // crap; started in exception handler __breakpoint(); } #endif #if !PICO_RUNTIME_SKIP_INIT_PER_CORE_INSTALL_STACK_GUARD // install core0 stack guard extern char __StackBottom; runtime_init_per_core_install_stack_guard(&__StackBottom); #endif // todo maybe we want to do this in the future, but it does stuff like register_tm_clones // which we didn't do in previous SDKs //extern void __libc_init_array(void); //__libc_init_array(); // ... so instead just do the __preinit_array runtime_run_initializers(); // ... and the __init_array extern void (*__init_array_start)(void); extern void (*__init_array_end)(void); for (void (**p)(void) = &__init_array_start; p < &__init_array_end; ++p) { (*p)(); } }