Emulating the Badge Under Renode

(Eventually)


Sean "xobs" Cross

About Me

Talk Outline

  1. What is Renode?
  2. How is it extensible?
  3. What is the state of the badge?

What is Renode?

Renode is an Emulator

  • Windows
  • Mac
  • Linux
    • CI
    • Github Actions

Generic Whole-system Emulator

  • CPU cores
  • Peripherals
  • Interconnections

Whole-system Emulator

CPU Cores

  • x86
  • arm
  • arm64
  • ppc
  • riscv
  • sparc
  • xtensa

Peripherals

Memory is Just a Peripheral

  • When you write to memory, it remembers the data
  • When you read from memory, you get the value
  • Your program is just initialised memory

Peripherals Are Just Special Memory

  • Writing to a memory address does a thing
  • Reading from an address gets a result
  • Interrupts are just GPIOs

Peripherals Are Just Special Memory

10% Functionality Solves 90% of Usecases

Existing Peripherals in Renode

  • Built-in peripherals for a number of devices
    • STM32
    • NRF52
    • IMXRT
    • LiteX
  • See https://github.com/renode/renode-infrastructure/tree/master/src/Emulator/Peripherals/Peripherals for more

Creating New Peripherals

  • Renode is written in C#
  • Like Java, C# has an eval() function
  • Peripherals can be written and loaded at runtime

SVD Files Are Your Friend

Networks in Renode

  • Built-in support for CAN, Ethernet, and Wireless
  • Also possible to add networks at runtime
  • No latency, just packets of data
    • Different devices run at different speeds

Other Goodies

  • LCD monitor with touchscreen support
  • Python interpreter for quick hacks
  • Attach GDB to any CPU core
  • Attach a serial port to a network connection
  • Scriptable with Robot framework
  • Log function calls

Shortcomings

  • Unable to unload modules
    • Need to restart Renode when you change a file
  • No real audio support
    • Support for verifying I2S, but can't play it
  • Only x64 hosts
    • Runs under Rosetta on Mac
  • Documentation needs work
    • Use the source!

Extending Renode

First, Betrusted

  • FPGA with VexRiscv
  • 2nd FPGA with smaller VexRiscv
  • 16-bit COM bus between them
  • AES extensions
  • x25519 "ENGINE" accelerator
  • SHA accelerator
  • Battery charger and manager
  • Custom lcd, timers, and USB

Betrusted

Emulating it With Renode

  • Good enough to develop the OS!
  • Good enough to catch bugs

Getting Hardware to Users

Getting Hardware to Users

Demonstration!

Getting Started with Renode

  1. Renode Platform Definition (.repl)
  2. Renode Script (.resc)

Example project repl:

using "platforms/cpus/nrf52840.repl"
gpio0:                // PinName in ArduinoIDE
	24 -> led_red@0   // LED_RED
	16 -> led_green@0 // LED_GREEN
	6  -> led_blue@0  // LED_BLUE
camera: Sensors.ArduCAMMini2MPPlus @ {
			spi2;
			twi0 0x30
}
lsm9ds1_imu: Sensors.LSM9DS1_IMU @ twi0 0x6b
lsm9ds1_mag: Sensors.LSM9DS1_Magnetic @ twi0 0x1e

Example project resc

using sysbus
mach create
machine LoadPlatformDescription @platforms/cpus/stm32f103.repl
machine LoadPlatformDescriptionFromString \
"button: Miscellaneous.Button @ gpioPortC 13 { IRQ -> gpioPortC@13 }"
showAnalyzer usart2
macro reset
"""
	sysbus LoadELF @zephyr-stm32f103-button.elf
"""
runMacro $reset

Running it

mono64 Renode.exe project.resc

How to Extend Renode

  1. Find a peripheral that does what you want
    • You might even find a compatible peripheral!
  2. Copy it to your project
  3. Change the constructor
  4. Change the register set
  5. Import the .cs file into Renode
  6. Add it to your platform file

Running Badge Software in Renode

It Doesn't

Xtensa is an Uncommon Architecture

  • Audio DSPs
  • Possibly Intel?
  • NXP

Extensive use of Boot ROM

Extensive use of Boot ROM

    $ esptool.py dump_mem \    
    	0x3ff90000 \       
    	65536 \
    	irom.bin

Add a serial port

namespace Antmicro.Renode.Peripherals.UART {
  public class ESP32_UART : UARTBase, IDoubleWordPeripheral,
							IKnownSize {
    private readonly DoubleWordRegisterCollection registers;
    public ESP32_UART(Machine machine) : base(machine) {
      registers = new DoubleWordRegisterCollection(this,
	  			new Dictionary<long, DoubleWordRegister> {
        {0x00, new DoubleWordRegister(this).WithValueField(0,8,
				writeCallback: (_, v) => TransmitCharacter((byte)v))}
      });
    }
				

Add a serial port

{0x00, new DoubleWordRegister(this)
		.WithValueField(0, 8,
			writeCallback: (_, v) => TransmitCharacter((byte)v))}
				

Load SVD file

sysbus:
	init:
		ApplySVD @esp32s3.svd

Load SVD file


extmem: Unhandled read from offset 0x64.
extmem: Unhandled write to offset 0x64, value 0x3.
sysbus: Read from an unimplemented register SYSTEM:SYSCLK_CONF
	(0x600C0060), returning a value from SVD: 0x1. (3)
sysbus: Read from an unimplemented register SYSTEM:PERIP_CLK_EN0
	(0x600C0018), returning a value from SVD: 0xF9C1E06F.
sysbus: Write of value 0xF9C1E06F to an unimplemented register
	SYSTEM:PERIP_CLK_EN0 (0x600C0018) generated from SVD.
sysbus: Read from an unimplemented register SYSTEM:PERIP_RST_EN0
	(0x600C0020), returning a value from SVD: 0x0.
sysbus: Write of value 0x0 to an unimplemented register SYSTEM:PERIP_RST_EN0 
	0x600C0020) generated from SVD.
sysbus: Read from an unimplemented register SYSTEM:PERIP_RST_EN0
	(0x600C0020), returning a value from SVD: 0x0.
sysbus: Write of value 0x4 to an unimplemented register SYSTEM:PERIP_RST_EN0 (0x600C0020) generated from SVD.						
					

Add Peripherals

Slowly Advance

GDB with ELF

What's Left?

  • SPI Controller
  • Interrupt Controller
  • I2C Controller
  • Touch Controller
  • Display

Displays

  • Implement ISpiDevice
  • Subclass AutoRepaintingVideo
  • Implement Repaint()

Touch Controller

  • Possibly interact with the Display controller
  • Implement II2CPeripheral

Audio is Hard

  • Existing I2S peripherals just pattern-match audio

Getting involved

  • Try Renode for your projects!
  • Add CI tests for your firmware!
  • Explore binaries for unknown targets!

Thank you

Questions?