Code Samples
These code samples relate to this article:
Cross Compiling to Bare Metal RISC-V with CMake.
CMake is an open-source, cross-platform family of tools designed to build, test and package software. In this post I’d like to use it to generate a cross-compiling Makefile.
CMake has great support for detecting it’s local build environment, but it’s less clear on how to use it for cross compiling to embedded targets. I’ve based this article on a tutorial for ARM bare-metal programming.
Using CMake can free you from vendor specific IDEs and toolchains, without needing to create your own build scripts. It can also provide a more automation friendly build environment.
Basic Setup
An example of compiling a stripped down (and non-functional) bare-metal test program is in the scratchpad repo
There are two files used, one to define the target toolchain and one to define the project.
- The CMAKE_TOOLCHAIN_FILE variable defines the toolchain.
- See cmake/riscv.cmake.
- The CMAKE_SYSTEM_PROCESSOR variable define the ISA and extensions. One of the cannonical isa definition strings must be set here.
- This toolchain file example has been setup to automatically find the RISC-V GCC cross compiler from either xPack embedded toolchain or RISC-V GNU Toolchain.
- The CMakeLists.txt file defines the project.
- See src/CMakeLists.txt.
- This example project has been extended to add some post processing common to embedded systems development.
The Basics
In a bare-metal project control over the compiler and linker options is
important. Basic configuration is via CMAKE_C_FLAGS
and CMAKE_EXE_LINKER_FLAGS
.
The example below also allows the linker script to be specified via LINKER_SCRIPT
,
and the stack size to be controlled via STACK_SIZE
.
Embedded Specialization
I’ve also added an example of creating a hex file version of the firmware image below. It should be easy to adapt the code to create a bin file or other image format.
I like to have the option of quickly inspecting the compiler output, so a disassembly from the final linked elf file and intermediate files is also generated.
In case it is not clear from the CMake syntax above, the following
commands will be executed when building with TARGET=test
,
CMAKE_OBJDUMP=riscv-none-embed-gcc-objdump
and
CMAKE_OBJCOPY=riscv-none-embed-gcc-objcopy
.