-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathpicolibc_interface.c
More file actions
164 lines (139 loc) · 4.5 KB
/
picolibc_interface.c
File metadata and controls
164 lines (139 loc) · 4.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <machine/time.h>
#include <time.h>
#include <sys/time.h>
#include <sys/times.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();
#else
return -1;
#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;
}
__weak clock_t times(struct tms *tms) {
#if CLOCKS_PER_SEC >= 1000000
tms->tms_utime = (clock_t)(to_us_since_boot(get_absolute_time()) * (CLOCKS_PER_SEC / 1000000));
#else
tms->tms_utime = (clock_t)(to_us_since_boot(get_absolute_time()) / (1000000 / CLOCKS_PER_SEC));
#endif
tms->tms_stime = 0;
tms->tms_cutime = 0;
tms->tms_cstime = 0;
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
// 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)();
}
}
#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 char __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"
// );
//}