HPM Environment Setup
An HPM project is a standard HPM SDK CMake project built with a RISC-V GCC toolchain (compiler prefix riscv32-unknown-elf-). The BSPs bsp-hpm5301evklite and bsp-rmcs-slave-lite are fully buildable projects and serve as the examples on this page; Code Generation describes how libxr hpm setup generates LibXR code in such a project.
Toolchain
The HPM SDK reads the toolchain installation directory (the parent of bin) from the environment variable GNURISCV_TOOLCHAIN_PATH, and the compiler is bin/riscv32-unknown-elf-gcc inside it; when the variable is missing, the CMake configuration fails with GNURISCV_TOOLCHAIN_PATH is not set yet. The SDK itself is pointed to by HPM_SDK_BASE.
Sources of the toolchain:
- Windows: the HPMicro development environment package sdk_env, whose
toolchains/directory holds the toolchain; the command line opened bystart_cmd.cmdsetsGNURISCV_TOOLCHAIN_PATHand the other environment variables; - Linux x64: the
riscv32-unknown-elftoolchain published as hpm-linux-gcc-release v0.1.0; - Docker:
ghcr.io/xrobot-org/docker-image-hpm:mainships that Linux toolchain (GCC 15.2.0) in/opt/hpm-riscv32-unknown-elf, with the path recorded in bothGNURISCV_TOOLCHAIN_PATHandXR_HPM_TOOLCHAIN_ROOT, see Docker Environment Setup.
Project Layout
Taking bsp-hpm5301evklite as the example:
.
|-- CMakeLists.txt
|-- CMakePresets.json
|-- app.yaml
|-- main.c
|-- boards/
| `-- hpm5301evklite/
| |-- tool_config.hpmpc
| |-- pinmux.c
| `-- ...
|-- cmake/
| `-- LibXR.CMake
|-- User/
| `-- app_main.cpp
`-- libxr/
CMakeLists.txtbrings in the HPM SDK withfind_package(hpm-sdk REQUIRED HINTS $ENV{HPM_SDK_BASE}), pointsBOARD_SEARCH_PATHatboards/, and setsCONFIG_DMA_MGR 1(the HPM drivers of LibXR depend on the SDK's dma_mgr component)app.yamldeclares the dependency onboard_gpt_pin;boards/<board>/contains the single.hpmpcfile (the BSPs name ittool_config.hpmpc);libxr hpm setupand the VS Code extension recognize an HPM project by these twoboards/<board>/pinmux.cis generated by the HPM Pinmux Tool fromtool_config.hpmpcand providesinit_bsp_pins()main.csits in the project root: a board clock function first adds the GPIO clock to the clock group (init_board_clock()in bsp-hpm5301evklite,board_init_clock_group()in bsp-rmcs-slave-lite), theninit_bsp_pins(), then the SDK board'sboard_init()and the clock functions of the peripherals (init_uart3_clock()and its siblings), and finallyapp_main(). Until the GPIO clock is in the clock group, the GPIO directions and levels set byinit_bsp_pins()have no effectUser/holds the generatedapp_main.cpp;libxr hpm setupgenerateslibxr_config.yamlnext to itlibxr/is the LibXR submodule
Build
CMakePresets.json provides the debug-flash-xip, debug-ram and release-flash-xip presets (Ninja generator, HPM_BUILD_TYPE of flash_xip or ram). The BSP uses XRobot Modules, so xrobot setup runs once before configuring; it fetches the Modules from xrobot.lock and generates Modules/CMakeLists.txt:
xrobot setup
cmake --preset release-flash-xip
cmake --build --preset release-flash-xip
The artifacts land in build/output/, for example demo.elf and demo.bin.
CMake Integration
cmake/LibXR.CMake selects the platform with three variables and adds LibXR as a subproject:
set(LIBXR_SYSTEM None)
set(LIBXR_DRIVER hpm)
set(LIBXR_NO_EIGEN True)
xr links ${HPM_SDK_LIB_ITF}, so LibXR compiles with the same options and include paths as the SDK; the application target app and the final ELF target link xr. Toolchain detection is handled by find_package(hpm-sdk).
The LibXR HPM Drivers
The drivers in driver/hpm are added to the build by the directory's CMakeLists.txt:
hpm_gpio.*: GPIOhpm_i2c.*: I2C masterhpm_pwm.*: PWMhpm_timebase.*: timebase on MCHTMRhpm_dma.*: initializes the SDK's dma_mgr once, for the DMA background path of the I2C
The drivers call SDK driver functions only; pin muxing, clocks and the initialization order belong to the project (init_bsp_pins(), board_init() and the init_*_clock() functions), and the LibXR objects are created in app_main(). The drivers depend on the SDK's dma_mgr component, which the BSPs enable with CONFIG_DMA_MGR 1.
HPMI2C implements the LibXR I2C master abstraction on top of the SDK's hpm_i2c_drv: blocking byte-stream transfers and register/memory-address transfers; 7-bit master addressing by default with SetAddressMode() switching to the SDK's 10-bit master addressing; wait strategies such as POLLING and CALLBACK can use the DMA-backed path on dma_mgr; on typical master failures such as a timeout, a busy bus or no response, the driver rebuilds the controller with its most recent successful configuration.
HPMPWM takes the same constructor arguments on both code paths (peripheral address, clock, output channel index, comparator index, polarity): SoCs with a standard PWM peripheral go through the SDK's hpm_pwm_drv, the others through the GPTMR path. SetDutyCycle() accepts a duty cycle of 0.0 to 1.0, and SetConfig() sets the frequency.
Docker Build
The image ghcr.io/xrobot-org/docker-image-hpm:main ships the RISC-V toolchain (GCC 15.2.0), CMake, Ninja and the HPM SDK v1.13.0, with GNURISCV_TOOLCHAIN_PATH and HPM_SDK_BASE already set:
docker run --rm -v "$PWD:/work" -w /work ghcr.io/xrobot-org/docker-image-hpm:main \
bash -c 'pip install xrobot==1.0.1 && xrobot setup && cmake --preset release-flash-xip && cmake --build --preset release-flash-xip'