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