Adding RP2350 SDK and target framework (#13988)
[betaflight.git] / lib / main / pico-sdk / rp2_common / pico_clib_interface / newlib_interface.c
blob8925e546409438526fa0d4c5e8d3ed0bcc31df9b
1 /*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
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"
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
30 #if PICO_ENTER_USB_BOOT_ON_EXIT
31 #include "pico/bootrom.h"
32 #endif
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
42 reset_usb_boot(0,0);
43 #else
44 while (1) {
45 __breakpoint();
47 #endif
50 __weak void *_sbrk(int incr) {
51 extern char end; /* Set by linker. */
52 static char *heap_end;
53 char *prev_heap_end;
55 if (heap_end == 0)
56 heap_end = &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) {
64 // errno = ENOMEM;
65 return (char *) -1;
67 next_heap_end = &__StackLimit;
68 #else
69 return (char *) -1;
70 #endif
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) {
80 if (tv) {
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);
85 return 0;
88 __weak int settimeofday(__unused const struct timeval *tv, __unused const struct timezone *tz) {
89 if (tv) {
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;
93 return 0;
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));
99 #else
100 tms->tms_utime = (clock_t)(to_us_since_boot(get_absolute_time()) / (1000000 / CLOCKS_PER_SEC));
101 #endif
102 tms->tms_stime = 0;
103 tms->tms_cutime = 0;
104 tms->tms_cstime = 0;
105 return 0;
108 __weak pid_t _getpid(void) {
109 return 0;
112 __weak int _kill(__unused pid_t pid, __unused int sig) {
113 return -1;
116 int __attribute__((weak)) _read(int handle, char *buffer, int length) {
117 #if LIB_PICO_STDIO
118 if (handle == STDIO_HANDLE_STDIN) {
119 return stdio_get_until(buffer, length, at_the_end_of_time);
121 #endif
122 return -1;
125 int __attribute__((weak)) _write(int handle, char *buffer, int length) {
126 #if LIB_PICO_STDIO
127 if (handle == STDIO_HANDLE_STDOUT || handle == STDIO_HANDLE_STDERR) {
128 stdio_put_string(buffer, length, false, true);
129 return length;
131 #endif
132 return -1;
135 int __attribute__((weak)) _open(__unused const char *fn, __unused int oflag, ...) {
136 return -1;
139 int __attribute__((weak)) _close(__unused int fd) {
140 return -1;
143 off_t __attribute__((weak)) _lseek(__unused int fd, __unused off_t pos, __unused int whence) {
144 return -1;
147 int __attribute__((weak)) _fstat(__unused int fd, __unused struct stat *buf) {
148 return -1;
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) {
157 _exit(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: " : "",
166 func ? func : "");
168 _exit(1);
170 GCC_Pragma("GCC diagnostic pop")
172 void runtime_init(void) {
173 #ifndef NDEBUG
174 if (__get_current_exception()) {
175 // crap; started in exception handler
176 __breakpoint();
178 #endif
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);
184 #endif
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) {
197 (*p)();