Well-known developer, Keith Packard has recently announced the launch of “picolibc” through his blog. Picolibc is a C Library for embedded systems which is suitable for small micro-controllers, and this standard C library API’s allows to run even in low memory (RAM) devices. This is an upgraded version of “newlib-nano” with few interesting changes which includes replacement of “stdio” lib with ATMEL-specific printf code adopted from avrlibc. As part of this library, Keith also launched picocrt, which is responsible for initializing memory and invoking various constructors before calling its own C program, the main function.
Features
- picolibc is a revised version of newlibc, without full-fledged stdio lib and uses lightweight stdio lib from avrlibc, which is more suitable to low memory embedded devices.
- Meson build-system eases the build process of picolibc source tree for various target platform and hardware.
- Updated the math test suite to use Glibc as a reference
- The library is BSD licensed, and non-BSD components were removed from the source tree.
- picocrt- picolibc startup code that initializes an embedded system without having to write your own code. This can be enabled by using -specs=picolibc.specs at compile time
- Uses built-in Thread-local storage (TLS) which offers several benefits :
- Source code is simpler as thread-local variables are
accessed directly by name. - Thread local storage contains only values used by the
application. - Generated code is smaller and faster.
- Source code is simpler as thread-local variables are
Getting Start with picolibc
Picolibc uses the meson build system to compile the source tree for various hardware platforms on a Linux host using GCC. Apart from the default parameters, this library allows to build with multiple attributes for enabling and disabling various functionalities by using the attribute line” -D=”.
Even though Picolibc is running on small stdio library from avrlibc, user having the option to enable old newlibc’s stdio lib by using the attribute (newlib-tinystdio=false). By default, it will be newlib-tinystdio=true, means it will get compiled with small avrlibc based stdio.
Before starting to build picolibc, you have to make sure that meson build system is part of your build environment, please refer to meson setup instructions.
As meson standard, all build configurations for cross-compilation build is part of separate configuration files, which is part of the source tree. Below the sample config file for various build environments.
Config file for RISC-V (cross-riscv32-unknown-elf.txt)
1 2 3 4 5 6 7 8 9 10 11 12 |
[binaries] c = 'riscv64-unknown-elf-gcc' ar = 'riscv64-unknown-elf-ar' as = 'riscv64-unknown-elf-as' ld = 'riscv64-unknown-elf-ld' strip = 'riscv64-unknown-elf-strip' [host_machine] system = 'unknown' cpu_family = 'riscv' cpu = 'riscv' endian = 'little' |
Compiling picolibc source tree using meson
The source tree itself provides scripts to configure, for various targets, includes riscv, arm, x86, etc. Below the sample compile script for the target arm.
1 2 3 4 5 6 7 8 |
#!/bin/sh ARCH=arm-none-eabi DIR=`dirname $0` meson "$DIR" \ -Dincludedir=picolibc/$ARCH/include \ -Dlibdir=picolibc/$ARCH/lib \ --cross-file "$DIR"/cross-$ARCH.txt \ "$@" |
And once you are ready with the meson and desired cross-compiler gcc lib environment, follow the steps to build picolibc with a specific target (for arm). My test build environment was ubuntu 18.04.
Installing meson
1 2 |
$ sudo apt-get install python3 python3-pip python3-setuptools python3-wheels ninja-build $ pip install --user meson |
Install Cross Compiler GCC (for arm)
1 |
$ sudo apt-get install gcc-arm-none-eabi |
Compile & Build picolibc
1 2 3 4 5 |
$ mkdir build_picolibc_arm $ cd build_picolibc_arm $ ~/picolibc/do-arm-configure (define your binary file path, which will be part of the picolibc source tree) $ ninja $ sudo ninja install |
Once it’s built successfully, you can verify by running the sample test case applications for printf and scanf in the “test” directory which is part of the build folder.
Picolibc code compilation process
Picolibc uses the GCC.spec file to compile source code. This will set the system header file path and the linker to point Picolibc. Below the example to compile a single file and generate a .o file:
1 |
$ gcc -specs=picolibc.specs -c test.c |
Picocrt (picolibc.specs)— startup code
Picocrt is part of picolib named as crt0.o, been enabled by
default when using -specs=picolibc.specs. Picocrt enables the initialization steps, which includes –
- Architecture-specific runtime initialization.
- Data initialization. Refer code snippet of picocrt, which handles data initialization –
1 |
memcpy(__data_start, __data_source, (uintptr_t) __data_size); |
-
-
- __data_start points to the RAM location where the .data segment
starts. - __data_source points to the Flash location where the .data segment
initialization values are stored. - __data_size is an absolute symbol noting the size of the
initialized data segment
- __data_start points to the RAM location where the .data segment
-
- BSS initialization. . Refer code snippet of picocrt, which handles data initialization –
1 |
memset(__bss_start, '\0', (uintptr_t) __bss_size); |
-
-
- __bss_start points to the RAM location where the .bss segment
starts. - __bss_size is an absolute symbol noting the size of the cleared
data segment
- __bss_start points to the RAM location where the .bss segment
-
- The __libc_init_array and __libc_fini_array functions in Picolibc are called by Picocrt during application startup and shutdown (__libc_init_array() (AppStart) —> main() —> –libc_fini_array() (App Stop) )
References
An Entrepreneur, an Opensource Enthusiast and Researcher in the domain of Embedded Systems, Wireless and IoT – Has over 16+ years of experience in managing and contributing enterprise Research Projects, in Embedded Systems, Software Technologies, Product Conceptualizations and development, Telecommunication, Media and Entertainment and Consumer Electronics.
Support CNX Software! Donate via cryptocurrencies, become a Patron on Patreon, or purchase goods on Amazon or Aliexpress
I hope this triggers a bit of a revival in these libraries (newlib, lwip etc). Everyone seems to use them, no one seems to maintain them.
I think the main problem is the industry. I am originally from the web. Compared the web world, embedded is a lot of closed source. There is also a missing mind-set for open source contributions. This is slowly coming. Probably with new people joining the industry. Projects like Arduino, RIOT OS or Platform IO give me some hope. Just takes some time.
Embedded is broken because vendors behave like gollum with their “IP” even though a good chunk of it isn’t theirs. I think so much of the market moving from in-house cores to ARM has made it even worse. They can’t publish stuff knowing that it’s only useful on their chips so they do stupid stuff like adding fixes for GCC in their own private builds behind an NDA-wall. At $DAYJOB I’ve been waiting on fixes in a library that is shipped as a binary for about 6 months now. I reverse engineered the library and told them where the issue… Read more »
PicoLibC 1.1 released: https://keithp.com/blogs/picolibc-1.1/
Mostly addition of a simple ‘hello world’ demo app
Hedzup! Jonathan McDowell has just contributed xtensa-lx106 additions to Keith’s project:-
https://esp8266hints.wordpress.com/2019/12/23/picolibc-adds-hooks-for-esp8266-esp32-builds/