1# Using Picolibc in Embedded Systems
2
3Picolibc is designed to be used in deeply embedded systems, those
4running either no operating system or a small RTOS. It is designed to
5be linked statically along with any operating system and application
6code.
7
8### Prerequisites
9
10It is expected that the toolchain used for compilation of applicatons
11against Picolibc provides the follwoing headers in its default search
12paths:
13
14 * float.h
15 * iso646.h
16 * stdalign.h
17 * stdarg.h
18 * stdbool.h
19 * stddef.h
20 * tgmath.h
21
22Vanilla GCC & Clang/LLVM toolchains take care of that so most of
23the users have everything in place. But some third-party toolchains
24may expect these headers to be provided by the C library. Unfortunately
25it is not possible as these headers have compiler-specific parts and
26so whatever version could be imported in the Picolibc, it won't work
27nicely with certain compilers. Moreover even different versions of the
28same compiler may not work well with the same version of one of the
29headers mentioned above.
30
31## Compiling with Picolibc
32
33To compile source code to use Picolibc, you can use the GCC .specs
34file delivered with Picolibc. This will set the system header file
35path and the linker library path to point at Picolibc. For example, to
36compile a single file and generate a .o file:
37
38	$ gcc --specs=picolibc.specs -c foo.c
39
40When installed directly into the system, picolibc.specs is placed in
41the gcc directory so that it will be found using just the base name of
42the file. If installed in a separate location, you will need to
43provide an absolute pathname to the picolibc.specs file:
44
45	$ gcc --specs=/usr/local/picolibc/picolibc.specs -c foo.c
46
47When building for an embedded system, you'll probably need to use a
48longer name for the compiler, something like `riscv-unknown-elf-gcc`
49or `arm-none-eabi-gcc`.
50
51## Picolibc startup
52
53Initializing an embedded system usually requires a combination of
54hardware, run-time, library and application setup. You may want to
55perform all of these in your own code, or you be able to use the
56Picolibc startup code. Either works fine, using the Picolibc code
57means writing less of your own.
58
59### Picocrt — Picolibc startup code
60
61Picocrt is the crt0.o code provided by Picolibc. This is enabled by
62default when using -specs=picolibc.specs:
63
64	$ gcc -specs=picolibc.specs -o foo.elf foo.c
65
66Picocrt goes through a sequence of initialization steps, many of which
67you can plug your own code into:
68
69 1) Architecture-specific runtime initialization. For instance, RISC-V
70    needs the `gp` register initialized for quick access to global
71    variables while ARM with hardware floating point needs to have the
72    FPSCR register set up to match C semantics for rounding.
73
74 2) Data initialization. Here's the code inside Picocrt:\
75    \
76    `memcpy(__data_start, __data_source, (uintptr_t) __data_size);`\
77    \
78    For this to work, the linker script must assign correct values to
79    each of these symbols:
80
81    * __data_start points to the RAM location where the .data segment
82      starts.
83    * __data_source points to the Flash location where the .data segment
84      initialization values are stored.
85    * __data_size is an absolute symbol noting the size of the
86      initialized data segment
87
88 3) BSS initialization. Here's the code inside Picocrt:\
89    \
90    `memset(__bss_start, '\0', (uintptr_t) __bss_size);`\
91    \
92    Assign these symbols in the linker script as follows:
93
94    * __bss_start points to the RAM location where the .bss segment
95      starts.
96    * __bss_size is an absolute symbol noting the size of the cleared
97      data segment
98
99 4) Optionally call constructors:
100
101    * The default and hosted crt0 variants call
102      [initializers/constructors](init.md) using `__libc_init_array()`
103
104    * The minimal crt0 variant doesn't call any constructors
105
106 5) Call `main()`
107
108 6) After main returns:
109
110    * The default and minimal crt0 variants run an infinite
111      loop if main returns.
112
113    * The hosted crt0 variant calls `exit`, passing it the value
114      returned from main.
115
116## Linking
117
118Picolibc provides two sample linker scripts: `picolibc.ld` for C
119applications and `picolibcpp.ld` for C++ applications. These are
120designed to be useful for fairly simple applications running on
121embedded hardware which need read-only code and data stored in flash
122and read-write data allocated in RAM and initialized by picolibc at
123boot time. You can read more about this on the [linking](linking.md)
124page.
125
126## Semihosting
127
128“Semihosting” is a mechanism used when the application is run under a
129debugger or emulation environment that provides access to some
130functionality of the OS running the debugger or emulator. Picolibc
131has semihosting support for console I/O and the exit() call.
132
133One common use for semihosting is to generate debug messages before
134any of the target hardware has been set up.
135
136Picolibc distributes the semihosting implementation as a separate
137library, `libsemihost.a`. Because it provides interfaces that are used
138by libc itself, it must be included in the linker command line *after*
139libc. You can do this by using the GCC --oslib=semihost
140command line flag defined by picolibc.specs:
141
142	$ gcc --specs=picolibc.specs --oslib=semihost -o program.elf program.o
143
144You can also list libc and libsemihost in the correct order
145explicitly:
146
147	$ gcc --specs=picolibc.specs -o program.elf program.o -lc -lsemihost
148
149## Crt0 variants
150
151The default `crt0` version provided by Picolibc calls any constructors
152before it calls main and then goes into an infinite loop after main
153returns to avoid requiring an `_exit` function.
154
155In an environment which provides a useful `_exit` implementation, applications
156may want to use the `crt0-hosted` variant that calls `exit` when main
157returns, resulting in a clean return to the hosting environment (this
158conforms to a hosted execution environment as per the C
159specification). Select this using the `--crt0=hosted` flag:
160
161	$ gcc --specs=picolibc.specs --crt0=hosted -o program.elf program.o
162
163In a smaller environment which is not using any constructors (or any
164Picolibc code which requires constructors) may want to use the
165`crt0-minimal` variant that removes the call to
166`__libc_init_array()`. This variant also runs an infinite loop in case
167main returns. Select this using the `--crt0=minimal` flag:
168
169	$ gcc --specs=picolibc.specs --crt0=minimal -o program.elf program.o
170