What is a system view description (SVD)? What can it be used for? And what is the connection to AVR microcontrollers?
These are a lot of questions, and this time, you will not find the answer by searching Wikipedia. The authoritative answer on what SVD is is given on this website. It is an XML format developed in the ARM ecosystem for describing computing devices. The idea is to have a machine-readable format describing a CPU and its peripheral registers that can be used to derive header files, inform debugger GUIs, and more.
Until a week ago, I was not aware that such a thing existed. But when I tried out the Arduino IDE 2 debugger on an MKR Zero, I noticed that the debugger pane CORTEX PERIPHERALS contained a view of all registers of the particular MCU. Digging a bit deeper revealed that a reference to an SVD file mediated such a view.
Since I am currently working on implementing a GDB server for AVR MCUs to support debugging in the Arduino IDE 2 and PlatformIO, I was curious whether something similar could be done for AVR MCUs. Spoiler alert: Yes, it is possible!
First of all, you need to obtain SVD files for AVR MCUs. But where can you get them? The AVR machine-readable descriptions provided by Microchip are ATDF files, which also use an XML format, but it is different from SVD. Searching the Internet does not lead to any SVD repository. However, one finds a tool atdf2svd written in Rust on GitHub. Since its main intention is to generate Rust header files, this conversion makes some assumptions that are not valid for the debugger use case. First, it removes the stack pointer and the status register from the description, because they are unsafe from a Rust perspective. Second, it includes fuses and lockbits, which are not really necessary. And they would need a bit more work to implement them inside the GDB server.
Although I am not fluent in Rust, which is the understatement of the month, I was able to create a pull request on GitHub so that the two problems are addressed. When specifying the options -a keep_unsafe_cpu_registers and -a remove_fuse_and_lockbit, stackpointer and status register are included, and lockbits and fuses are removed. But before one can employ the SVD files, further massaging of the SVD files is necessary.
When employing the SVD files as they are in the Arduino IDE 2, one will notice that now all the register groups, registers, and bit fields are displayed, but the register values are all constant 0. The reason is that the baseAddress field in the SVD files uses data addresses with a base of 0x0000. However, the debugger needs addresses with a base of 0x800000 to determine that the addresses refer to the data space. So, some final patching is called for.
In addition, there is the question of what to do with the ATDF attribute ocd-rw="". You find this very often in register descriptions of the on-chip debugger (OCD) register and serial I/O registers. It probably means that such a register should not be accessed by the debugger. When reading from the OCD register, the hardware debugger chokes. When reading from a serial I/O register, the current input will be discarded. Writing, on the other hand, is not critical. For OCD registers, it seems to be a no-op. For I/O registers, one can actually supply the next output byte. For these reasons, I believe the best way to deal with this attribute is to forbid the debugger from reading such registers and to remark that in the SVD descriptions. This implies patching the ATDF files before they get converted.
When going over the ATDF files, one notes that the ocd-rw attribute is not entirely consistently used. Sometimes, for the UART or SPI registers, the ocd-rw="" marker is missing, which one can account for. For the ATmegaC1 and ATmegaM1 family, all CAN bus and all PSC registers are marked with ocd-rw="", which, after reading the register descriptions, does not sound reasonable. So another patch to apply.
With all that, the SVD files can finally make their appearance.

As you can see, all register groups are displayed on the left pane. Moreover, if you have selected one of the register groups, changes from the last value are highlighted, as in the case of the PORTB registers above. Furthermore, one can get information on each register by hovering over this register, as shown in the following picture.

All that works also when you use PlatformIO/VSC. You only have to copy the SVD file into your project folder and add the line debug_svd_path=<mcu-name>.svd to the platformio.ini file.
So, what else could one do? As it turns out, the Rust people have collected a lot of patches for each of the AVR SVD files, which I will review in the future. However, for now, I am quite satisfied that the integration of SVD files into the debugging environment has been successful so far. And it makes debugging on the register level much more pleasurable.
The featured image of this blog post is based on a picture by Shawn Suttle on Pixabay.
Leave a Reply