• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..--

.gitignoreD11-Mar-202411 22

MakefileD11-Mar-20243.5 KiB9844

README.mdD11-Mar-20245 KiB161116

aarch64-cpp.ldD11-Mar-2024150 86

aarch64.ldD11-Mar-2024148 86

arm-cpp.ldD11-Mar-2024150 86

arm.ldD11-Mar-2024148 86

hello-world.cD11-Mar-20241.7 KiB458

hello-worldpp.cppD11-Mar-20241.8 KiB4710

printf.cD11-Mar-20241.8 KiB4911

riscv-cpp.ldD11-Mar-2024133 86

riscv.ldD11-Mar-2024131 86

run-aarch64D11-Mar-20241.8 KiB5411

run-aarch64++D11-Mar-20242.1 KiB649

run-armD11-Mar-20241.8 KiB5511

run-riscvD11-Mar-20241.9 KiB5411

run-riscv++D11-Mar-20242.2 KiB659

test-fileD11-Mar-202422 21

README.md

1# Hello World
2
3Building embedded applications is tricky in part because of the huge
4number of configuration settings necessary to get something that
5works. This example shows how to use the installed version of
6picolibc, and uses 'make' instead of 'meson' to try and make the
7operations as clear as possible. Here's our fine program:
8
9	#include <stdio.h>
10
11	int
12	main(void)
13	{
14		printf("hello, world\n");
15		return 0;
16	}
17
18## Selecting picolibc headers and C library
19
20Picolibc provides a GCC '.specs' file _(generated from
21picolibc.specs.in)_ which sets the search path for
22header files and picolibc libraries.
23
24	gcc -specs=picolibc.specs
25
26## Semihosting
27
28Our example program wants to display a string to stdout; because there
29aren't drivers for the serial ports emulated by qemu provided, the
30example uses Picolibc's semihosting support (`--oslib=semihost`) to
31direct stdout to the QEMU console:
32
33	gcc -specs=picolibc.specs --oslib=semihost
34
35## Target processor
36
37For ARM, QEMU emulates a "mps2-an385" board which has a Cortex-M3
38processor:
39
40	arm-none-eabi-gcc -specs=picolibc.specs --oslib=semihost -mcpu=cortex-m3
41
4264-bit ARM (aarch64) processors are pretty much the same, so the
43default target code will run fine on a cortex-a57 processor as
44supported by QEMU:
45
46	aarch64-linux-gnu-gcc -specs=picolibc.specs --oslib-semihost
47
48For RISC-V, QEMU lets you specify which CPU core you want, so we'll
49use something that looks like a SiFive E31 chip. That's a 32-bit
50processor with the 'imac' options (integer, multiply, atomics,
51compressed) and uses the 'ilp32' ABI (32-bit integer, long and
52pointer)
53
54	riscv64-unknown-elf-gcc -specs=picolibc.specs
55	--oslib-semihost -march=rv32imac -mabi=ilp32
56
57## Target Memory Layout
58
59The application needs to be linked at addresses which correspond to
60where the target memories are addressed. The default linker script
61provided with picolibc, `picolibc.ld`, assumes that the target device
62will have two kinds of memory, one for code and read-only data and
63another kind for read-write data. However, the linker script has no
64idea where those memories are placed in the address space. The example
65specifies those by setting a few values before including
66`picolibc.ld`.
67
68The mps2-an385 has at least 16kB of flash starting at 0. Picolibc
69places a small interrupt vector there which points at the first
70instruction of _start.  The mps2-an385 also has 64kB of RAM starting
71at 0x20000000, so arm.ld looks like this:
72
73	__flash =      0x00000000;
74	__flash_size = 0x00004000;
75	__ram =        0x20000000;
76	__ram_size   = 0x00010000;
77	__stack_size = 1k;
78
79	INCLUDE picolibc.ld
80
81The aarch64 virt model lets you define whatever memory spaces you
82like,so we'll just stick things at 0x40000000 (aarch64.ld):
83
84	__flash =      0x40000000;
85	__flash_size = 0x00400000;
86	__ram =        0x40400000;
87	__ram_size   = 0x00200000;
88	__stack_size = 8k;
89
90	INCLUDE picolibc.ld
91
92For the RISC-V 'spike' model, you can have as much memory as you like,
93but execution starts at 0x80000000 so the first instruction in the
94application needs to land there. Picolibc on RISC-V puts _start at the
95first location in read-only memory, so we set things up like this
96(this is riscv.ld):
97
98	__flash = 0x80000000;
99	__flash_size = 0x00080000;
100	__ram = 0x80080000;
101	__ram_size = 0x40000;
102	__stack_size = 1k;
103
104	INCLUDE picolibc.ld
105
106The `-T` flag is used to specify the linker script in the compile
107line:
108
109	arm-none-eabi-gcc -specs=picolibc.specs --oslib=semihost
110	-mcpu=cortex-m3 -Tarm.ld
111
112	aarch64-linux-gnu-gcc -specs=picolibc.specs --oslib=semihost
113	-Taarch64.ld
114
115
116## Final Commands
117
118The rest of the command line tells GCC what file to compile
119(hello-world.c) and where to put the output (hello-world-riscv.elf and
120hello-world-arm.elf):
121
122	riscv64-unknown-elf-gcc --specs=picolibc.specs --oslib=semihost
123	-march=rv32imac -mabi=ilp32 -Thello-world-riscv.ld -o
124	hello-world-riscv.elf hello-world.c
125
126	arm-none-eabi-gcc --specs=picolibc.specs --oslib=semihost
127	-mcpu=cortex-m3 -Thello-world-arm.ld -o hello-world-arm.elf
128	hello-world.c
129
130## Running Under QEMU
131
132To run the hello-world example under qemu, we need to construct a
133virtual machine suitable for this. That means enabling semihosting
134(`-semihosting-config enable=on`), disabling the monitor interface
135(-monitor none), the emulated UART (-serial none) and the graphical
136interface (`-nographic).
137
138For arm, we're using the mps2-an385
139
140	qemu-system-arm -semihosting-config enable=on -monitor none
141	   -serial none -nographic
142	   -machine mps2-an385,accel=tcg
143	   -kernel hello-world-arm.elf
144
145On aarch64, we use the 'virt' machine, which lets us plug in any
146processor we want. In this case, we'll use the cortex-a57:
147
148	qemu-system-aarch64 -semihosting-config enable=on -monitor none
149	   -serial none -nographic
150	   -machine virt -cpu cortex-a57
151	   -kernel hello-world-aarch64.elf
152
153Risc-V is similar to aarch64 in providing a virtual host into which
154you can install any virtual processor you want, in our case, an rv32:
155
156	qemu-system-riscv32 -semihosting-config enable=on -monitor none
157	   -serial none -nographic
158	   -machine virt,accel=tcg -cpu rv32 -bios none
159	   -kernel hello-world-riscv.elf
160
161