Picolibc Hello World Example
It's hard to get started building applications for embedded RISC-V and ARM systems. You need to at least:
Find and install the toolchain
Install a C library
Configure the compiler for the right processor
Configure the compiler to select the right headers and libraries
Figure out the memory map for the target device
Configure the linker to place objects in the right addresses
I've added a simple 'hello-world' example to picolibc that shows how to build something that runs under qemu so that people can test the toolchain and C library and see what values will be needed from their hardware design.
The Source Code
Getting text output from the application is a huge step in embedded
system development. This example uses the “semihosting” support
built-in to picolibc to simplify that process. It also explicitly
calls exit
so that qemu will stop when the demo has finished.
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
printf("hello, world\n");
exit(0);
}
The Command Line
The hello-world documentation
takes the user through the steps of building the compiler command line, first using the picolibc.specs
file to
specify header and library paths:
gcc --specs=picolibc.specs
Next adding the semihosting library with the --semihost option (this is an option defined in picolibc.specs which places -lsemihost after -lc):
gcc --specs=picolibc.specs --semihost
Now we specify the target processor (switching to the target compiler here as these options are target-specific):
riscv64-unknown-elf-gcc --specs=picolibc.specs --semihost -march=rv32imac -mabi=ilp32
or
arm-none-eabi-gcc --specs=picolibc.specs --semihost -mcpu=cortex-m3
The next step specifies the memory layout for our emulated hardware, either the 'spike' emulation for RISC-V:
riscv64-unknown-elf-gcc --specs=picolibc.specs --semihost -march=rv32imac -mabi=ilp32 -Thello-world-riscv.ld
with hello-world-riscv.ld containing:
__flash = 0x80000000;
__flash_size = 0x00080000;
__ram = 0x80080000;
__ram_size = 0x40000;
__stack_size = 1k;
INCLUDE picolibc.ld
or the mps2-an385 for ARM:
arm-none-eabi-gcc --specs=picolibc.specs --semihost -mcpu=cortex-m3 -Thello-world-arm.ld
with hello-world-arm.ld containing:
__flash = 0x00000000;
__flash_size = 0x00004000;
__ram = 0x20000000;
__ram_size = 0x00010000;
__stack_size = 1k;
INCLUDE picolibc.ld
Finally, we add the source file name and target elf output:
riscv64-unknown-elf-gcc --specs=picolibc.specs --semihost
-march=rv32imac -mabi=ilp32 -Thello-world-riscv.ld -o
hello-world-riscv.elf hello-world.c
arm-none-eabi-gcc --specs=picolibc.specs --semihost
-mcpu=cortex-m3 -Thello-world-arm.ld -o hello-world-arm.elf
hello-world.c
Summary
Picolibc tries to make things a bit simpler by offering built-in compiler and linker scripts along with default startup code to try and make building your first embedded application easier.