How do you debug your embedded targets?

Hello !
I have currently setup a .gdbinit and an openocd script to debug my embedded targets, but I have a few troubles making it work :

  • gdb is not able to see any symbols (even if debug=true is set in Cargo.toml) except static ones
  • breakpoints tend to behave strangely : I set up a breakpoint in a specific line, and gdb stops way after telling me that the breakpoint was at line 264 when I used the command br
  • debugging peripherals and hal is very tedious because you don't have a global peripheral view with all the registers

Is there a good working setup somewhere ?
Ho do you guys work ?

Thanks :smile:

1 Like

Quick thought: Is your memory layout file (usually called memory.x I think) correct for your microcontroller?

Yeah, I guess it's the RAM. Try to lower it to a value like 4K or something and then try again.

With gdb you can do something like

monitor reset

Do you get to the first instruction? If you hit something that pushes or pops something to/from the stack and it crashes you have the error :wink:

I checked out and I have a good looking memory.x file, at least for the stm32f103C6.

The problem is that I don't have an hard error, but debugging is just very inconvenient... :unamused:

I disaggree with that. Everything you can do with C++ can be done with Rust as well (debugging wise).
When you can attach gdb to your target, you can step around, jump, print variables, registers, doing crazy stuff etc all from gdb/lldb.

It would be good if you explain what you are struggling with. Is it connecting to the target? Printing variables? Setting breakpoints?

What I mean by inconvenient is the points listed in the first post.

Maybe if you have a working setup for the stm32f103 target you could share it with me so that I can compare our configuration files and find the problem !

I am using arm-none-eabi-gdb 7.10.

I am fully able to see code and symbols.

Have you read Introduction - The Embedded Rust Book and others ?

I have a working debugger in this project

Okay, so I think I know why I have trouble debugging : using opt-level = 1 instead of opt-level = 3 in the release profile allow the debugger to have much more information about the code. Maybe the optimization from the compile are too aggressive for a proper debugging experience with opt-level = 3 ?

Anyway, thank you @TheZoq2 and @hellow !

On an embedded platform, you normally want opt-level="s" or "z" instead, because it optimzises for size instead of speed.

Also IIRC LLVM can't emit good debug symbols with opt-level >= 2. I can't find a link to this, but I think I read it somewhere.

Yes, the opt level certainly affects the debugabilty. Pretty much everything becomes at opt level 3 but I need it turned on to fit in flash. I should try s or z though...


I use VSCode and use the Cortex debug extension

It will setup an OpenOCD server and run GDB for you, all within the context of VSCode.
You can run GDB/OpenOCD commands from within the integrated terminal too.

Breakpoints just work, and so does ITM (iprintln)

Registers and peripheral values are shown in the debug sidebar:

This GitHub Gist has the configuration I use throughout the Discovery eBook (You just need to modify the 'executable' part in the launch.json file).

The 2x files live under the .vscode directory in your project

Now you can just focus on your code and debugging: Code -> Press F5 -> Debug -> Repeat


Support for Custom ITM Data Decoders:

  • Ability to define JavaScript modules to decode complex data formats streamed over one or more ITM ports. Data can be printed to a output window, or sent to the graphing system.

oooh (apart from the JS bit, but still)

oooh (apart from the JS bit, but still)

Maybe you can use webassembly :stuck_out_tongue:

1 Like

This is very nice !
Thanks !