Newlib minimal runnable example
https://sourceware.org/newlib/
With Newlib, you implement your own system calls for your baremetal platform.
Here I provide a highly automated and documented example that shows Newlib built with crosstool-NG running in QEMU aarch64.
For example, on the above example, we have an example program exit.c
:
#include <stdio.h>
#include <stdlib.h>
void main(void) {
exit(0);
}
and in a separate C file common.c
, we implement the exit
with ARM semihosting:
void _exit(int status) {
__asm__ __volatile__ ("mov r0, #0x18; ldr r1, =#0x20026; svc 0x00123456");
}
The other typical syscalls that you will implement are:
write
to output results to the host. This can be done either with:
- more semihosting
- an UART hardware
brk
for malloc
.
Easy on baremetal, since we don't have to care about paging!
TODO I wonder if it is realistic to reach preemptive scheduling syscalls execution without going into a full blown RTOS like Zephyr or FreeRTOS.
The cool thing about Newlib, is that it implements all the non-OS specific things like string.h
for you, and lets you implement just the OS stubs.
Also, you don't have to implement all the stubs, but only the ones you will need. E.g., if your program only need exit
, then you don't have to provide a print
. Newlib achieves this by giving dummy do-nothing implementations of all syscalls as weak symbols.
The Newlib source tree does already have some implementations, including an ARM semihosting implementation under newlib/libc/sys/arm
, but for the most part you have to implement your own. It does however provide a solid base for the task.
The easiest way to setup Newlib is by building your own compiler with crosstool-NG, you just have to tell it that you want to use Newlib as the C library. My setup handles that automatically for you with this script, which uses the newlib configs present at crosstool_ng_config
.
C++ should also work in theory, but my initial attempt was unsucessful.