PlatformIO Community

AVR simulator as aid tool for debugging code

Hello,

Something I noticed when using platformio with AVR microcontrollers is the lack of debugging tools. As suggested in VSCode PIO debugger for AVR, projects like dwire-debug could change this situation after solving some problems and limitations, like only one breakpoint, assembler listings among them.

However, another project that could be of use is simavr, an opensource AVR simulator. Something amazing about this is that it not only emulates the AVR core but also, interruptions, peripherals and also includes a GDB server.

It isn’t long since I found about this simulator (or even Platformio) so some mistakes could have been made, but this is my first working attempt to integrate simavr with platformio and VSCode.

To make this work the first step is to install simavr itself which can be done by a simple apt-get install simavr or downloading and installing from source code. I didn’t verify this but it looks like is possible to compile for mac and windows too.

Next is to create a platformio project as usual and modify the platformio.ini file by adding a custom debugger, just like this one.

Finally copy the simavr_env.py file to the root of the project. The simavr_env.py script creates a target, called simulate, for the pio command, and to launch the simulator and GDB session the following command is required: pio run -t simulate -e debug

This python script automatically handles the generation of arguments for simavr based in the board_mcu and board_f_cpu definitions, so the simulated controller will always be the same as the one in the board definition in platformio.ini

The emulated environment works without any modification to the microcontroller’s source code, however, to enhance the experience the header simavr/avr/avr_mcu_section.h should be included together with some macros as explained in the simavr’s project page, like this example.

Among the new features comes the possibility to log any register or variable and graph them as if a logic analyzer were connected. Also, it looks like it can also emulate external devices like displays, buttons, and even sensors, but I haven’t tested those yet.

I just found about simavr a couple of days ago but it allowed me to get the debugging experience I had with other microcontrollers like stm32. I don’t know if my approach is the best one, but at least it doesn’t require to fiddle with internal configuration files but only the platformio.ini file.

Now it would be interesting if simavr were included in the platformio environment maybe as a board to avoid conflicts with the existing ones, but that’s only a suggestion.

2 Likes

@ivankravets intersting for possible direct integration into platform-atmelavr?

2 Likes

Yeah, I was thinking something like that.

At first, I tough that adding simavr as another board would be the right way, but I realized that it would be better to add it as a debug server. Right now I’m reviewing the process that is being used to integrate the Renode Simulation Framework to Platformio, and probably most of the steps would be applicable for simavr too.

Besides that, after using simavr for a while I found some minor problems with the GDB server, like some of the commands for restarting and halting the processor, aren’t recognized or implemented. I’ve already addressed the issue in the repository of the project so let’s look if this can help to move things.

I will continue to test this simulator and report the problems/solutions I find, but any help would be welcomed.

Very nice find! Especially when it says something like …

AVR simulator for linux, or any platform that uses avr-gcc

… plus it sounds like it’s much easier to integrate. And that no avr parts will be harmed in the process! :laughing:

I’ll give it a try in the next day or two also, on both arch linux and Windows 10, and see how it goes! :wink:

@pfeerick could you try to compile it on Windows? We would bee glad if share your experience. So, I don’t see any problem to add 1-Click simulation for AVR.

Thanks, @msquirogac for the research!

I uploaded a minimum example to test simavr and platformio here. There are two examples, the main difference is that one of them enables the VCD output and the other doesn’t, but both of them are able to debug.

So far if the avr_mcu_section.h header and its macros aren’t used then the debugger works without major problems (besides ones stated in previous posts), both with and without the Arduino framework.

However, if those are included, which is necessary in order to get plots like this VCD, then things get a bit more challenging.
screenshot3
The first problem is that those macros do heavy use of “non-trivial designated initializers” and it looks like avr-gcc has support for it but avr-g++ doesn’t. That means potential problems with Arduino projects, or with projects that use avr-g++ compiler. A workaround would be to change the extension from .cpp to .c but that would be possible only for projects that don’t use specific c++ structures.

The second problem is the placement of the mmcu section inside memory. For what I understood those macros place variables and strings in a section called mmcu, then the simulator recovers them from the elf binary to configure and dump data from the specified memory addresses.

The tricky part is that any unused variable is removed when compiling, that’s why the command -Wl,–undefined=_mmcu,–section-start=.mmcu=0x910000 is added to the compiler, which I found after reviewing some examples in simavr. I also found that the -Og also has some effects so it should be left aside?

After crossing that problem a third one arises with the GDB command load. I guess that the address 0x910000 is outside the memory map of the controller and GDB refuses to load it but I’m not sure. A workaround would be to comment out the load command but I don’t know what would be the implications of that.

After all of this, the VCD capability is enabled and works fine. By the way, the generated trace file has a .vcd extension and can be open with gtkwave.

@ivankravets , should I open an issue on Platformio’s GitHub repository requesting this feature? and in which one should be, platform-atmelavr?
I would like to keep contributing to this idea and I think the repository could be a better place.

Hi @msquirogac! Thanks for your hints about simavr. I’ve already added initial support so we can use it as a debug server. But it looks like there is a problem with simavr on OS X. I simply cannot execute command load from the avr-gdb, it fails with the following error:

Remote target does not support flash erase

Any thoughts?
Also filed an issue in their repository:

@valeros, Maybe is a thing of avr-gdb itself?
I got two different results depending on which version of avr-gdb I used in the same computer and same OS. I didn’t have any problem with the version built-in platformio, but the same error appeared with the one from my old Debian.

Edit: I’ve just tested the upstream branch, the error doesn’t appear on my Debian box.

@msquirogac It works on my Ubuntu too. But on OSX this error persists. I tried different versions, even with avr-gdb + simavr from brew.

So if anyone is willing to test the debug using simavr on Windows and Linux, please try the following config:

[env:simavr]
platform = https://github.com/platformio/platform-atmelavr.git
framework = arduino
board = AT90CAN32  ; Change to desired board
debug_tool = simavr
1 Like

@valeros Maybe it’s a thing of the compilation flags of avr-gdb itself which can be recovered with this command:

avr-gdb -ex "show configuration"

Platformio’s avr-gdb for linux has this configuration (this one works for me):

GNU gdb (AVR_8_bit_GNU_Toolchain_3.6.2_1759) 7.8
This GDB was configured as follows:
configure --host=x86_64-pc-linux-gnu --target=avr
–with-auto-load-dir=$debugdir:$datadir/auto-load
–with-auto-load-safe-path=$debugdir:$datadir/auto-load
–without-expat
–with-gdb-datadir=/home/toolsbuild/workspace/avr8-gnu-toolchain/avr8-gnu-toolchain-linux_x86_64/share/gdb (relocatable)
–with-jit-reader-dir=/home/toolsbuild/workspace/avr8-gnu-toolchain/avr8-gnu-toolchain-linux_x86_64/lib/gdb (relocatable)
–without-libunwind-ia64
–without-lzma
–without-guile
–with-separate-debug-dir=/home/toolsbuild/workspace/avr8-gnu-toolchain/avr8-gnu-toolchain-linux_x86_64/lib/debug (relocatable)
–with-zlib
–without-babeltrace

While my Debian’s avr-gdb has this other (this trigger the same error as you):

GNU gdb (GDB) 7.7.1
This GDB was configured as follows:
configure --host=x86_64-linux-gnu --target=avr
–with-auto-load-dir=$debugdir:$datadir/auto-load
–with-auto-load-safe-path=$debugdir:$datadir/auto-load
–with-expat
–with-gdb-datadir=/usr/share/gdb (relocatable)
–with-jit-reader-dir=/usr/lib/gdb (relocatable)
–without-libunwind-ia64
–without-lzma
–with-separate-debug-dir=/usr/lib/debug (relocatable)
–without-zlib
–without-babeltrace

Oh… nice! So you were able to make a windows binary… I was having trouble as stuff was missing, sites with pre-built libraries no longer having valid SSL certificates, yada, yada. Linux was straightforward, just wasn’t what I wanted to try out…

And to boot, I was just going to try this, and now VSCode 1.45.0 is giving me The task provider for "C/C++" tasks unexpectedly provided a task of type "shell". FFS can’t VSCode (or is it the C/C++ extension this time?) do just one update that doesn’t break platformIO? :rofl: :rofl:

So, PlatformIO is still working dispute that error… but I get this… apparently I don’t qualify! :stuck_out_tongue_winking_eye:

PackageManager: Installing tool-simavr @ ~1.6.0
Error: Could not find a version that satisfies the requirement '~1.6.0' for your system 'windows_x86'
The terminal process terminated with exit code: 1

@valeros, is this package compatible only with x64?

@pfeerick, does this Windows x64 package work for you? https://bintray.com/beta/#/platformio/dl-packages/tool-simavr?tab=files

It looks like VSCode bug

Thanks for linking the github issue. It looks like the fix is pending, I replied further on the github issue just now.

That simavr executable runs on my system… which is x64 bit…

image

so not sure what when wrong there! :open_mouth:

Downloaded the package, poked

    "system": [
        "windows",
        "windows_amd64",
        "windows_x86"
    ],

in instead of

    "system": [
        "windows_amd64"
    ],

into the package.json and it’s running nicely so far. Just a stupid simple test…

image

1 Like

@valeros Some news. I’ve started to dissect simavr code, especially the code related to the GDB server. After sniffing an exchange between simavr and GDB I found that one version of avr-gdb sends the vFlashErase command while the other doesn’t, and as simavr doesn’t support said that command it triggers the error you found.

The workaround would be to find a way to avoid sending that command for this target, at least until it gets implemented. I will keep reviewing that code and maybe send PR if the author doesn’t fix it.

Edit: the load command isn’t needed if the .elf file is passed as argument to simavr

simavr -g -f <freq> -m <model> firmware.elf
1 Like

@valeros
The biggest difference between both GDB compile flags is the inclusion of the expat library, and the reason why it is used in GDB is explained here.

To be able to write into flash memory, GDB needs to obtain a memory map from the target.

Also:

GDB assumes that areas of memory not covered by the memory map are RAM, and uses the ordinary ‘M’ and ‘X’ packets to write to addresses in such ranges.

So not including that lib would make avr-gdb unable to use of all the vFlash commands, or make it believe that everything is RAM, which is exactly what I captured with the sniffer. The version with expat tried to use vFlash commands while the version without it used only ‘M’ commands and the later are supported by simavr.

Could you provide a PR to simavr repository with a fix? We can rebuild binary for macOS from your branch. Thanks!

We use official Microchip toolchain to keep compatibility with Arduino projects. I recommend to keep the same official toolchains for all systems but add fix to simavr which will just ignore this “Erase” command.

1 Like

Thanks! Fixed! :blush:

1 Like