| core | ||
| drivers/ch32v003 | ||
| handlers | ||
| link | ||
| subfsm | ||
| .gitignore | ||
| README.md | ||
| run.sh | ||
os3-rnode
Minimal standalone CH32V003 RNode-compatible LoRa modem firmware extracted from the OS3 tree.
Article and project write-up:
This repository contains only the files required to build the CH32V003 + SX1262 RNode firmware image:
- core event kernel: core/trap.S, core/event.S, core/kernel.S, core/timer.S, core/console.S, core/fsm.S, core/events.inc
- CH32V003 drivers: drivers/ch32v003/bootstrap.S, init.S, exti.S, uart.S, vector.S, flash.S, mcu.S, spi.S, sx1262.S, led.S, mmio.inc
- FSMs: subfsm/rnode_fsm.S, subfsm/lora_fsm.S
- handlers: handlers/heartbeat.S
- linker: link/ch32v003.ld
- build entrypoint: run.sh
The extraction source commit in the original OS3 tree was: 3058b75912041138a990446e3c946457b5da8ef7
Build
The repository builds a single firmware target: CH32V003.
There is no Makefile or external build system here. The whole build is driven by run.sh, which:
- creates
build/ch32v003/ - removes previous
.o,.elf, and.binfiles for that target - assembles every module with
riscv32-unknown-elf-as - links the final image with
riscv32-unknown-elf-ld - generates the flashable binary with
riscv32-unknown-elf-objcopy - prints the resulting image sizes and registered
.kernel_initentries
Prerequisites
Install a RISC-V embedded GNU toolchain and make sure these commands are available in your PATH:
riscv32-unknown-elf-asriscv32-unknown-elf-ldriscv32-unknown-elf-objcopyriscv32-unknown-elf-sizeriscv32-unknown-elf-nm
The firmware is assembled for rv32ec_zicsr with ABI ilp32e, matching the CH32V003.
Build Command
From the repository root, run:
./run.sh
On a successful build, the script produces:
build/ch32v003/kernel.elf- ELF image with symbols and debug infobuild/ch32v003/kernel.bin- raw binary image to flash to the MCU
The script is safe to re-run; it cleans the target output directory before rebuilding.
Typical Build Output
The build ends with a short summary similar to:
Build complete:
- build/ch32v003/kernel.elf
- build/ch32v003/kernel.bin
Section sizes:
text data bss dec hex filename
....
If one of the riscv32-unknown-elf-* tools is missing, the build will fail immediately. In that case, fix the toolchain installation or PATH first.
Flashing
The build output to flash is:
build/ch32v003/kernel.bin
The simplest workflow uses minichlink with a WCH-Link compatible probe.
Write the firmware to flash:
minichlink -w build/ch32v003/kernel.bin flash -b
Write and reset immediately after flashing:
minichlink -w build/ch32v003/kernel.bin flash -b -r
Typical sequence:
- Connect the CH32V003 board to the SX1262/E22 module.
- Connect the SWD probe to the CH32V003.
- Build the firmware with
./run.sh. - Flash
build/ch32v003/kernel.binwithminichlink. - Reset the board and reconnect the host UART side.
If your probe is already attached and detected, the second command is usually the one you want:
minichlink -w build/ch32v003/kernel.bin flash -b -r
Wiring
CH32V003 to E22-900M22S
Connect the radio module to the CH32V003 exactly like this:
PC0->NRSTPC1->BUSYPC2->DIO1PC3->RXENPC4->NSS / CSPC5->SCKPC6->MOSIPC7->MISO3V3->VCCGND->GNDDIO2->TXENon the E22 side
Attach an antenna before RF testing.
CH32V003 to WCH-Link UART bridge
For the host-side RNode UART, connect the CH32V003 USART1 pins to the WCH-Link UART bridge:
PD5(USART1 TX) -> WCH-Link UARTRXPD6(USART1 RX) -> WCH-Link UARTTXGND->GND
CH32V003 to WCH-Link debug/flash header
For flashing and debug access, connect the WCH-Link probe like this:
PD1(SWDIO / SWIO) -> WCH-LinkSWDIOPD0(NRST) -> WCH-LinkNRSTif available3V3-> WCH-Link3V3GND->GND
CH32V003 uses a single-wire debug interface on PD1, so there is no separate SWCLK pin to wire.
LEDs
The firmware uses two status LEDs on port D:
PD4-> heartbeat LEDPD2-> radio activity LED
The radio activity LED is active-low in the current driver.