RNode on OS3: a Minimal Reticulum Firmware for the CH32V003
I wanted to know how small a useful Reticulum transport could get.
Not a mock-up. Not a “Hello World over LoRa”. Not a proof of concept that only works in a lab once. A real firmware image that can be flashed onto a cheap microcontroller board, detected by rnsd, and used with tools like Sideband and NomadNet.
This release is the result: a small RNode-compatible firmware image based on OS3, targeting the CH32V003 and an E22-900M22S LoRa module built around the SX1262.
The hardware budget is unusually tight:
- 16 KB flash
- 2 KB RAM
That is exactly why this firmware is interesting.

The current hardware setup: CH32V003 dev board, E22-900M22S radio module, and direct wiring during validation.
What This Firmware Is
This is a minimal RNode-style modem firmware for the Reticulum ecosystem.
It provides:
- a UART host interface compatible with the expected RNode framing model
- SX1262 radio control over SPI
- LoRa TX/RX for Reticulum traffic
- correct RNode packet handling up to the upstream logical MTU
- interoperability with
rnsd, Sideband, and NomadNet in the current release configuration
It is intentionally narrow in scope. There is no display stack, no BLE, no Wi-Fi, no GPS, no PMU layer, and no device-side application environment.
This firmware is meant to do one job well: act as a small, understandable, event-driven Reticulum transport.
Reticulum Is Bigger Than LoRa
It is worth being precise here:
- Reticulum is the networking stack
- RNode is one modem/interface model used by parts of the ecosystem
- LoRa is only one physical transport
So this firmware should not be read as “Reticulum on LoRa and nothing else”. It is one transport target, implemented on very constrained hardware, using the RNode model that existing Reticulum-side software already understands.
That makes it useful in two ways:
- as a practical radio modem firmware you can actually flash and use
- as a lower-bound demonstration of what a tiny event-driven system can still do correctly
Target Platform
The current target is:
- MCU: CH32V003
- Core: QingKe V2A / RV32EC
- Flash: 16 KB
- RAM: 2 KB
- Radio module: E22-900M22S
- Radio chipset: SX1262
- Host link: UART
Current linked image size:
- Flash (
.text): 10277 bytes - RAM (
.bss): 1848 bytes
The RAM headroom is small, but the firmware is stable and functional in that footprint.
Hardware Setup
The firmware-side wiring is fixed and should be followed by signal name, not guesswork.
CH32V003 to E22-900M22S
CH32V003 <-> E22-900M22S
------------------------------------------------
CH32 pin Role in firmware E22 signal
------------------------------------------------
PC0 LoRa reset NRST
PC1 LoRa busy BUSY
PC2 LoRa IRQ DIO1
PC3 RX path enable RXEN
PC4 SPI chip select NSS / CS
PC5 SPI clock SCK
PC6 SPI MOSI MOSI
PC7 SPI MISO MISO
3V3 Power VCC
GND Ground GND
ANT RF Antenna
Important Notes
- Both boards must share 3.3V logic
- All grounds must be connected
- The E22 module must have an antenna attached before RF testing
RXENmust be wired, otherwise receive behavior will be incorrectTXENis driven byDIO2, withDIO2directly wired toTXEN
The current design relies on the SX1262/E22 behavior where:
DIO2is configured as the TX enable drive and is wired directly toTXENRXENis still driven explicitly by the MCUDIO3is used internally by the E22 TCXO path
Practical unused or implicit signals:
Signal Status
-----------------------------------------------
TXEN Driven directly by DIO2
DIO2 Directly wired to TXEN
DIO3 Used internally for the E22 TCXO path
Host UART, LEDs, and Reset
CH32 pin Function
-----------------------------------------------
PD5 USART1 TX
PD6 USART1 RX
PD4 Heartbeat LED
PD2 Radio activity LED
PD0 NRST
Indicator behavior:
PD4: heartbeatPD2: radio activity pulse on completed logical TX and RX events
Flashing the Binary Release
This firmware is meant to be distributed and used as a prebuilt binary image.
Download:
- Firmware binary
- CRC-32 (
cksum):4036646072(0xF09D3678) - Size:
10280bytes
After downloading the firmware binary, flash it directly:
minichlink -w ch32v003-rnode-os3.bin flash -b
Flash and reset:
minichlink -w ch32v003-rnode-os3.bin flash -b -r
Released binary filename:
ch32v003-rnode-os3.bin
For end users, the setup flow is simple:
- Wire the CH32V003 board and the E22 module exactly as shown above.
- Download
ch32v003-rnode-os3.bin. - Flash it with
minichlink. - Connect the UART host interface to the machine running Reticulum software.
- Start
rnsd, Sideband, or another compatible host-side tool.
Host Configuration with rnsd
On the host side, this firmware is intended to be used through the regular Reticulum daemon.
A minimal ~/.reticulum/config looks like this:
[reticulum]
enable_transport = False
share_instance = Yes
[interfaces]
[[CH32RNode]]
type = RNodeInterface
enabled = yes
port = /dev/ttyACM0
frequency = 868000000
bandwidth = 125000
txpower = 2
spreadingfactor = 7
codingrate = 5
Adjust the serial device and radio parameters to match your hardware and regional band plan.
Then start the daemon:
rnsd
Once the interface is up, tools such as Sideband and NomadNet can use the running Reticulum instance through the normal host-side path.
Why This Took More Than Basic RF Bring-Up
Getting a radio to emit packets is easy compared to making a device behave like a real RNode modem.
The hard part was protocol fidelity:
- correct RNode detection and startup probing
- correct reporting of radio parameters
- correct handling of the RNode modem header
- surviving a 2 KB RAM budget without corrupting the host-facing path
- implementing split-packet TX and RX behavior that matches the expected RNode model
This is what turns a board from “it can send LoRa” into “it can interoperate with existing Reticulum software without surprises”.
The 508-Byte RNode Limit
One of the key implementation details is the classic RNode logical MTU.
The packet limit is 508 bytes, and that is a hard limit in this framing model:
- raw LoRa frame maximum:
255bytes - modem header:
1byte - useful payload per raw frame:
254bytes - maximum fragments per logical packet:
2 - logical payload maximum:
254 + 254 = 508
This firmware implements that behavior correctly:
- host packets up to 508 bytes are accepted
- larger logical packets are not treated as a third-fragment case, because that case does not exist in classic RNode framing
- TX is fragmented internally into two raw LoRa frames when needed
- RX is reassembled internally before the packet is forwarded to the host
That behavior matters in practice. Without it, announces may appear to work while larger real-world traffic fails or becomes invalid.
Release Status
The current binary release has been validated as follows:
rnsddetects the device- host-side radio configuration succeeds
- announce traffic works
- short messages work
- longer messages using the split-packet path work
- Sideband and NomadNet interoperate with the firmware

rnstatus reporting the CH32-based RNode interface as up and operational on the host.

Bidirectional message exchange validated through the CH32-based RNode link.
This is no longer just a radio bring-up milestone. It is a functional RNode-compatible LoRa modem release on top of OS3.
Why I Think This Matters
To me, the interesting part is not simply that a cheap microcontroller can now participate in the Reticulum ecosystem.
The more interesting part is what this says about the design space:
- a real external protocol can be implemented cleanly on extremely small hardware
- architectural discipline still matters even when memory is scarce
- “small” does not have to mean sloppy
- an event-driven system can remain understandable while still being practically useful
In other words, this firmware is not only a release artifact. It is also a statement about lower bounds.
It shows that a meaningful Reticulum transport can exist much lower in the hardware stack than many people would assume.
Closing
This is not the final form of a user-facing Reticulum device.
It is something narrower: a small, focused, flashable firmware image that does one job correctly.
On a CH32V003 paired with an E22-900M22S, OS3 now provides a working RNode-compatible modem for the Reticulum ecosystem.
For a microcontroller with 2 KB of RAM, that is a satisfying result.