nviennot / stm32-emulator

GNU General Public License v3.0
353 stars 35 forks source link

STM32 Emulator

The goal is to simulate 3D printers, but any sort of stm32 microcontroller firmware should work.

The emulator is configured via a configuration file, see example here.

In the following example, I show how to emulate the 3D printer of the Elegoo Saturn and Anycubic MonoX unmodified firmwares downloaded from the vendor website.

This emulator is done in the context of my work on reverse engineering 3D printers so I can write a Rust firmware for 3D printers, Turbo Resin.

Table of content

Emulating the Elegoo Saturn

In the configuration file, we provide an SVD file that provides all the peripheral register addresses for the STM32F407. We then configure various memory regions, framebuffers, and devices. We also patch two functions in the firmware just to speed things up as we don't need to wait for our devices to initialize.

We also specify the firmware binary saturn-v4.4.3-pj-v5.bin, and that's the official binary downloaded from the Elegoo website. The ext-flash.bin is the content of the external SPI flash dumped from the Saturn board itself (I cheated a bit here, I wish we could have just used the downloaded version, it wasn't working, and I was in a hurry).

Youtube demo (click on the image)

Saturn

Try it out

$ git clone https://github.com/nviennot/stm32-emulator.git
$ cd stm32-emulator/saturn
$ cargo run --release -- config.yaml -v

The output

On the following we see some of the output. We can see how the firmware initialize the display for example. These are display commands we need to reproduce when implementing our own firmware. We can also see that it's emitting something on the UART. We also see its interaction with the SPI Flash.

Saturn trace

We can also see that the firmware has issues. The init routines are messy from what I've seen in the decompilation. In the emulation, we can see NULL pointer exceptions, GPIO being re-configured multiple times. On the STM32, address 0 is actually mapped to the flash, and so the memory accesses in the first 4K don't actually fail, so failures of this nature go silent.

Saturn NULL

We can see how the GPIOs are getting configured:

Saturn GPIO

We can see how a specific peripheral gets initialized, like SPI2. That information is coming right off the SVD file.

Saturn SPI2

We can also do instruction tracing with -vvvv:

Saturn instructions

Overall, the emulator is useful to understand what the firmware is doing without having the real printer on hand, which will be helpful in supporting additional printers for TurboResin.

It would be fun to implement a GDB server provided by the emulator, this way we could use GDB to inspect the runtime, and even connect a decompiler like Ghirda or IDA Pro.

Emulating the Anycubic Mono X

Youtube demo (click on the image)

MonoX

Try it out

$ git clone https://github.com/nviennot/stm32-emulator.git
$ cd stm32-emulator/monox
$ cargo run --release -- config.yaml -v

Emulator Features

Existing work

There's some existing work in the STM32 emulation space:

License

The code is released under the GPLv3