How do I add a missing peripheral register to a STM32 MCU model in Renode?

751 views Asked by At

I am trying out this MCU / SoC emulator, Renode.

I loaded their existing model template under platforms/cpus/stm32l072.repl, which just includes the repl file for stm32l071 and adds one little thing.

When I then load & run a program binary built with STM32CubeIDE and ST's LL library, and the code hits the initial function of SystemClock_Config(), where the Flash:ACR register is being probed in a loop, to observe an expected change in value, it gets stuck there, as the Renode Monitor window is outputting:

[WARNING] sysbus: Read from an unimplemented register Flash:ACR (0x40022000), returning a value from SVD: 0x0

This seems to be expected, not all existing templates model nearly everything out of the box. I also found that the stm32L071 model is missing some of the USARTs and NVIC channels. I saw how, probably, the latter might be added, but there seems to be not a single among the default models defining that Flash:ACR register that I could use as example.

How would one add such a missing register for this particular MCU model?

Note1: For this test, I'm using a STM32 firmware binary which works as intended on actual hardware, e.g. a devboard for this MCU.

Note2: The stated advantage of Renode over QEMU, which does apparently not emulate peripherals, is also allowing to stick together a more complex system, out of mocked external e.g. I2C and other devices (apparently C# modules, not yet looked into it). They say "use the same binary as on the real system". Which is my reason for trying this out - sounds like a lot of potential for implementing systems where the hardware is not yet fully available, and also automatted testing. So the obvious thing, commenting out a lot of parts in init code, to only test some hardware-independent code while sidestepping such issues, would defeat the purpose here.

1

There are 1 answers

6
Piotr Zierhoffer On BEST ANSWER

If you want to just provide the ACR register for the flash to pass your init, use a tag.

You can either provide it via REPL (recommended, like here https://github.com/renode/renode/blob/master/platforms/cpus/stm32l071.repl#L175) or via RESC.

Assuming that your software would like to read value 0xDEADBEEF. In the repl you'd use:

sysbus:
    init:
        Tag <0x40022000, 0x40022003> "ACR" 0xDEADBEEF

In the resc or in the Monitor it would be just:

sysbus Tag <0x40022000, 0x40022003> "ACR" 0xDEADBEEF

If you want more complex logic, you can use a Python peripheral, as described in the docs (https://renode.readthedocs.io/en/latest/basic/using-python.html#python-peripherals-in-a-platform-description):

flash: Python.PythonPeripheral @ sysbus 0x40022000
    size: 0x1000
    initable: false
    filename: "script_with_complex_python_logic.py"
```

If you really need advanced implementation, then you need to create a complete C# model.

As you correctly mentioned, we do not want you to modify your binary. But we're ok with mocking some parts we're not interested in for a particular use case if the software passes with these mocks.

Disclaimer: I'm one of the Renode developers.