blob: b10bb418d6d1fe1ce58dd3b65c06f6477fae4f47 [file] [log] [blame]
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include "pico.h"
#if LIB_PICO_STDIO
#include "pico/stdio.h"
#endif
#if PICO_ENTER_USB_BOOT_ON_EXIT
#include "pico/bootrom.h"
#endif
#include "pico/time.h"
#include "pico/runtime_init.h"
#if LIB_PICO_PRINTF_PICO
#include "pico/printf.h"
#else
#define weak_raw_printf printf
#define weak_raw_vprintf vprintf
#endif
static int picolibc_putc(char c, __unused FILE *file) {
#if LIB_PICO_STDIO
stdio_putchar(c);
#endif
return c;
}
static int picolibc_getc(__unused FILE *file) {
#if LIB_PICO_STDIO
return stdio_getchar();
#endif
}
static int picolibc_flush(__unused FILE *file) {
#if LIB_PICO_STDIO
stdio_flush();
#endif
return 0;
}
static FILE __stdio = FDEV_SETUP_STREAM(picolibc_putc,
picolibc_getc,
picolibc_flush,
_FDEV_SETUP_RW);
FILE *const stdin = &__stdio; __strong_reference(stdin, stdout); __strong_reference(stdin, stderr);
void __weak __assert_func(const char *file, int line, const char *func, const char *failedexpr) {
weak_raw_printf("assertion \"%s\" failed: file \"%s\", line %d%s%s\n",
failedexpr, file, line, func ? ", function: " : "",
func ? func : "");
_exit(1);
}
void __attribute__((noreturn)) __weak _exit(__unused int status) {
#if PICO_ENTER_USB_BOOT_ON_EXIT
reset_usb_boot(0,0);
#else
while (1) {
__breakpoint();
}
#endif
}
static int64_t epoch_time_us_since_boot;
__weak int gettimeofday (struct timeval *__restrict tv, __unused void *__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;
}
__weak 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;
}
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
// piolibc __libc_init_array does __preint_array and __init_array
extern void __libc_init_array(void);
__libc_init_array();
}
#if !PICO_RUNTIME_NO_INIT_PER_CORE_TLS_SETUP
__weak void runtime_init_pre_core_tls_setup(void) {
// for now we just set the same global area on both cores
// note: that this is superfluous with the stock picolibc it seems, since it is itself
// using a version of __aeabi_read_tp that returns the same pointer on both cores
extern void __tls_base;
extern void _set_tls(void *tls);
_set_tls(&__tls_base);
}
#endif
#if !PICO_RUNTIME_SKIP_INIT_PER_CORE_TLS_SETUP
PICO_RUNTIME_INIT_FUNC_PER_CORE(runtime_init_pre_core_tls_setup, PICO_RUNTIME_INIT_PER_CORE_TLS_SETUP);
#endif
//// naked as it must preserve everything except r0 and lr
//uint32_t __attribute__((naked)) WRAPPER_FUNC(__aeabi_read_tp)() {
// // note for now we are just returning a shared instance on both cores
// pico_default_asm_volatile(
// "ldr r0, =__tls_base\n"
// "bx lr\n"
// );
//}