Building applications with Picolibc¶
GNU toolchain for ARC-V targets uses riscv64-snps-elf
prefix for
all tools. For example, GCC binary has name riscv64-snps-elf-gcc
.
Usually, to compile an application you need to set target options:
-march
- stands for RISC-V ISA.-mabi
- stands for ABI.-mtune
- stands for a particular GCC instruction scheduling optimization, refer Tuning Instruction Scheduling for ARC-V specific values .-mcmodel
-medlow
forrv32
targets andmedany
forrv64
targets.
All together they correspond to a particular prebuilt standard library. Refer Understanding ARC-V configurations for details.
Getting Started¶
Consider a simple code example:
If I want to build it for the base RMX-100 target and link with a semihosting library, I would use this set of options:
$ riscv64-snps-elf-gcc \
-march=rv32imafc \
-mabi=ilp32f \
-mtune=arc-v-rhx-100-series \
-specs=picolibc.specs \
--crt0=semihost \
--oslib=semihost \
example.c -o example.elf
Passing -specs=picolibc.specs
for linking with Picolibc is mandatory:
- It allows choosing a proper variant of
crt0
startup file through--crt0=
option (see all variants below). - It allows choosing a proper variant of a system library through
--oslib=
option (see all variants below). - It chooses a custom linker script crafted for Picolibc (
picolibc.ld
).
In turn, when picolibc.ld
linker script is used, it's possible to configure
placement and size of code and data sections:
- Set offset of code sections through
-Wl,--defsym=__flash=
option. - Set size of code sections through
-Wl,--defsym=__flash_size=
option. - Set offset of data sections through
-Wl,--defsym=__ram=
option. - Set size of data sections through
-Wl,--defsym=__ram_size=
option.
Here is a full example with custom code and data sections:
$ riscv64-snps-elf-gcc \
-march=rv32imafc \
-mabi=ilp32f \
-mtune=arc-v-rhx-100-series \
-specs=picolibc.specs \
--crt0=semihost \
--oslib=semihost \
-Wl,--defsym=__flash=0x80000000 \
-Wl,--defsym=__flash_size=128K \
-Wl,--defsym=__ram=0x80020000 \
-Wl,--defsym=__ram_size=128K \
example.c -o example.elf
Run the application using nSIM:
$ nsimdrv -p nsim_isa_family=rv32 -p nsim_isa_ext=-all.i.m.a.f.c.zicsr -p nsim_semihosting=1 -p enable_exceptions=0 example.elf
Hello, World!
Refer to Running on nSIM and Running on QEMU to learn how to run ARC-V examples on nSIM or QEMU simulator.
Compiling C++ applications¶
Consider a simple code example:
For compiling C++ applications use -specs=picolibcpp.specs
:
$ riscv64-snps-elf-gcc \
-march=rv32imafc \
-mabi=ilp32f \
-mtune=arc-v-rhx-100-series \
-specs=picolibcpp.specs \
--crt0=semihost \
--oslib=semihost \
-Wl,--defsym=__flash_size=2M \
-Wl,--defsym=__ram_size=2M \
example.c -o example.elf
Using size optimized Picolibc variant¶
Pass -specs=nano.specs
option to link an application with a
size optimized Picolibc variant:
$ riscv64-snps-elf-gcc \
-march=rv32imafc \
-mabi=ilp32f \
-mtune=arc-v-rhx-100-series \
-specs=picolibc.specs \
-specs=nano.specs \
--crt0=semihost \
--oslib=semihost \
example.c -o example.elf
The table below summarizes differences between the regular Picolibc and size optimized one.
Feature | Picolibc | Picolibc Nano |
---|---|---|
Optimization level | -O3 |
-Os |
Support of long long format in i/o functions |
Yes | No |
Support of long double format in i/o functions |
Yes | No |
Support of %b format in i/o functions |
Yes | No |
Support of %n format in i/o functions |
Yes | No |
Faster buffered i/o operations | Yes | No |
Multibyte support for UTF-8 charset | Yes | No |
Wide character support in printf /scanf |
Yes | No |
Choosing a crt0
variant¶
A variant of a startup file (crt0.o
) is chosen through --crt0=
option. See a list of all supported values for this option below.
Option | Uses CSR instructions | Returns exit code | Calls constructors | Reads command line arguments | Sets traps | Initializes ARC-V features |
---|---|---|---|---|---|---|
Not passing --crt0= value (default) |
No | No | Yes | No | No | No |
--crt0=hosted |
No | Yes | Yes | No | No | No |
--crt0=minimal |
No | No | No | No | No | No |
--crt0=semihost |
No | Yes | Yes | Yes | No | No |
--crt0=semihost-trap |
Yes | Yes | Yes | Yes | Yes | No |
--crt0=arcv-hosted |
Yes | Yes | Yes | No | No | Yes |
--crt0=arcv-minimal |
Yes | No | No | No | No | Yes |
--crt0=arcv-semihost |
Yes | Yes | Yes | Yes | No | Yes |
--crt0=arcv-semihost-trap |
Yes | Yes | Yes | Yes | Yes | Yes |
Empty crt0
variant corresponds to --crt0=none
. All arcv-*
variants enable all available ARC-V caches
and support of RVV if it's present.
Choosing a system library¶
So far, Picolibc supports 2 system libraries, and it's chosen through --oslib=
option:
Option | Description |
---|---|
--oslib=dummyhost |
A simple environment without input/output and exit codes. |
--oslib=semihost |
Support of Semihosting environment. |
Tuning instruction scheduling¶
GCC instruction scheduling may be tuned for different ARC-V
targets using -mtune=
option:
Feature | Option |
---|---|
Tune for RMX-100 targets | -mtune=arc-v-rmx-100-series |
Tune for RMX-500 targets | -mtune=arc-v-rmx-500-series |
Tune for RHX-100 targets | -mtune=arc-v-rhx-100-series |
Tune for RPX-100 targets | -mtune=arc-v-rpx-100-series |
For RMX-100 targets it's also possible to choose a version of MPY unit using -param=arcv-mpy-option=
option:
-param=arcv-mpy-option=1c
-param=arcv-mpy-option=2c
(default)-param=arcv-mpy-option=10c
You can choose a number of cycles that a word-size integer load operation takes
(from 1 to 3, 3 is default) using --param=arcv-ld-cycles=<1,3>
option.
Note that all -mtune
values for ARC-V assume that fast unaligned access is supported
(__riscv_misaligned_fast == 1
) by targets. This assumption may be overwritten by
-mstrict-align
when building an application or toolchain libraries itself.
Using a linker script optimized for performance¶
The default Picolibc linker script places .rodata
section right after code
sections. However, this approach may lead to decrease in performance since
addressing through a global pointer may not be available for .rodata
in this
case.
If safety of read only regions is not a priority in a particular case,
picolibc_perf.ld
linker script may be used to increase performance:
$ riscv64-snps-elf-gcc \
-march=rv32imafc \
-mabi=ilp32f \
-mtune=arc-v-rhx-100-series \
-specs=picolibc.specs \
-T picolibc_perf.ld \
--crt0=semihost \
--oslib=semihost \
example.c -o example.elf
This linker script places .rodata
in a data region.
Migrating from Newlib¶
Build with semihosting and ARC-V features¶
Using Newlib:
Using Picolibc:
Build with semihosting and without ARC-V features¶
Using Newlib:
Using Picolibc:
Set offset and size of text and data sections¶
Using Newlib:
...
-specs=semihost.specs \
-specs=arcv.specs \
-T arcv.ld \
-Wl,-defsym=txtmem_addr=0x80000000 \
-Wl,-defsym=txtmem_len=128K \
-Wl,-defsym=datamem_addr=0x80020000 \
-Wl,-defsym=datamem_len=128K \
...
Using Picolibc: