Reverse Engineering the Renesas RA4M1 USB Protocol

I recently started a new embedded project: building a demo CAN setup on a breadboard with different microcontrollers. I wanted to try something new, so I chose an ESP32-C6 alongside a Renesas RA4M1 (completely new to me). Both have good Rust support, which was a key requirement.

There was just one problem: the cheap development board I picked up doesn't expose SWD pins for debugging. No problem, I thought. The RA4M1 has a built-in USB bootloader in ROM. Renesas provides a flasher program to use it.

That's when the real problems started.


The Problem: A Proprietary Tool That Doesn't Work on NixOS

The official flasher tool, Renesas Flash Programmer (RFP), is a closed-source Windows application. On Linux, there's a version available, but it's dynamically linked against specific system libraries. On NixOS, this means:

Could not start dynamically linked executable: ./rfp-cli
NixOS cannot run dynamically linked executables intended for generic
linux environments out of the box. For more information, see:
https://nix.dev/permalink/stub-ld

I could have used a FHS environment, but that feels like a clunky workaround.

I had three options:

  1. Try to solder wires to SWD pins and use a debug probe (they are on the bottom of the board)
  2. Buy a different board with a 10-pin SWD connector and use a debug probe
  3. Write my own flasher

Option 3 sounded reasonable - no need to buy anything or solder small wires. I only had to understand the protocol... I couldn't find documentation online (it is officially available here which I was not aware of when doing all this 🫠).

So I turned to reversing the Linux CLI tool. Since I'm based in the EU, reverse engineering for interoperability purposes is explicitly allowed under EU Directive 2009/24/EC.


The Approach: Reverse Engineering with Open Source Tools

Step 1: Tracing System Calls with strace

First, I needed to see what the proprietary tool was actually doing. I ran it on a non-NixOS Linux machine with strace:

strace -f -o rfp_trace.log ./rfp-cli -device ra -port /dev/ttyACM0 -a ra4m1-zero-rgb.srec

This gave me a trace of all system calls. The trace confirmed that the RA4M1 USB bootloader presents itself as a CDC-ACM serial device. The tool opens /dev/ttyACM0 and communicates using UART protocol at 9600 baud (B9600).

Step 2: Deep Dive with Rizin and Ghidra

With the serial communication identified, I needed to understand the actual protocol. I used a combination of tools:

  • rizin (formerly radare2) for dynamic analysis
  • rz-ghidra for decompilation
  • Mistral LLM to untangle decompiled pseudocode

Side note: A one shot prompt like this goes really far: The tool rfp-cli uses libRFP.so to flash a cdc-acm (ttyACM0) connected Renesas MA4R1 with the firmware. Use rizin to reverse and document the flashing process in documentation.md. See rfp_trace.log for a trace of one flashing run. Document in detail how this works so that a developer can use that documentation to write an independent implementation.

Tracing all calls leading to uart open(), read(), and write() calls, it was quite easy to reverse how everything works.

The key insight from the disassembly: the flasher uses a frame-based protocol with the following structure:

Offset Size Description
0x00 1 Frame kind (0x01 = COMMAND, 0x81 = DATA)
0x01 2 Payload length (big-endian)
0x03 1 Command ID
0x04 ... Payload data
...+1 1 Checksum (two's complement of length+command+payload)
...+2 1 Frame terminator (0x03)

Sending commands with the following IDs:

  • 0x00: Initial status/handshake
  • 0x3a: Read device signature
  • 0x3b: Read flash area information
  • 0x34: Request baud rate change to 115200
  • 0x12: Erase flash range
  • 0x13: Write flash data
  • 0x15: Read/verify flash data

This information could then be confirmed with the captured strace traces: All writes started with the frame header! 🎉

The full flash procedure looks like this:

loop[For each flasharea]loop[For each eraserange]loop[For each chunk]loop[For each span]Open at 9600baud10 zero bytes(sync)0x000x55(handshake)0xC3Status 0x00OKRead signature0x3a12-bytesignatureRead area 0x3bArea descriptorRequest 1152000x34Switch to115200 baudErase 0x12OKWrite start 0x13OKDATA 0x13OKVerify 0x15Flash dataBootloaderra-flasherra-flasherBootloader

The Implementation: A Minimal Rust Flasher

With the protocol documented, I wrote ra-flasher, a minimal CLI tool in Rust using the serialport crate for serial communication with the RA4M1's CDC-ACM USB bootloader.

Implementation Overview

The implementation follows the flow described in the reversing section. It consists of two main modules: protocol.rs handles the UART/USB ROM boot protocol communication, and image.rs parses Motorola S-record firmware images.

CLI Interface

The tool exposes a simple CLI using serial ports:

# Parse and validate an S-record image without connecting
ra-flasher check firmware.mot

# Inspect device signature and flash area geometry
ra-flasher inspect /dev/ttyACM0

# Flash a firmware S-record image
ra-flasher flash /dev/ttyACM0 firmware.mot

Verification: Does It Actually Work?

To verify my implementation, I flashed a firmware image with my tool, then read it back using the official Renesas tool to confirm the contents matched.


Lessons Learned

  • Documentation exists - RTFM first next time
  • rizin + rz-ghidra + LLM is a powerful combo for reversing
  • strace gets you surprisingly far

The Outcome

After only one evening, I had ra-flasher, a fully functional, open-source CLI flash tool for my RA4M1 dev board:

👉 https://codeberg.org/madmo/ra-flasher

It supports the Waveshare RA4M1-Zero and should work on other RA4 chips as well.


Final Thoughts

This was a fun but needlessly complex deep dive into reverse engineering and protocol implementation. Having a working flasher means I can now develop for the RA4M1 on any platform, including NixOS, without relying on proprietary tools.

If you're working with Renesas RA chips and hitting the same walls I did, give ra-flasher a try. And if you have other RA family chips, contributions to extend support are very welcome!