Home Getting Started Download Discussions Source Report An Issue

Limitations of AVR debugging with Bloom

Using Bloom to debug AVR microcontrollers on Linux comes with some limitations. These are described here.

Breakpoints can cause excessive wear on AVR flash memory

By default, GDB inserts and removes breakpoints liberally, in order to reduce the likelihood of breakpoints being left on the target in the event of GDB terminating abruptly.

Bloom doesn't support hardware breakpoints. All breakpoints set via GDB will be implemented as software breakpoints. This means that all breakpoints are written to the AVR target's flash memory.

When GDB makes unnecessary breakpoint removal/insertion requests, this can cause excessive wear on the target's flash memory.

Some debug tools will delay the applying of breakpoint changes to flash memory, until they receive a flow control command. This reduces the unnecessary updating of flash memory, but does not completely prevent it.


GDB can be configured to keep breakpoints in place, instead of removing them immediately after target execution comes to a halt. This can be done via the always-inserted breakpoint setting:

(gdb) show breakpoint always-inserted Always inserted breakpoint mode is off. (gdb) set breakpoint always-inserted on (gdb) show breakpoint always-inserted Always inserted breakpoint mode is on. (gdb)

Enabling the always-inserted setting will further reduce the excessive wear of flash memory, when debugging via GDB and Bloom. It should also improve debugging performance.

Bloom automatically clears all breakpoints before disconnecting from the debug tool. This means that enabling the always-inserted setting should not affect the likelihood of redundant software breakpoints being left on the target, in the event of GDB terminating abruptly.

Stepping performance

When stepping over a line of code, GDB instructs Bloom to step one instruction at a time. This can have a significant impact on the time it takes to step over an instruction-heavy line of code.

This issue is particularly noticeable when stepping over calls to busy-wait functions, such as _delay_ms() and _delay_us().


Avoid stepping over instruction-heavy lines - instead, use breakpoints. Place a breakpoint at the subsequent line, then continue execution. This will allow the target to execute all the instructions between the PC and breakpoint address, before halting at the subsequent line.

The tbreak command accepts an offset. The following example will install a temporary breakpoint +1 line from the current line, in the current source file.

(gdb) tbreak +1

Alternatively, the until GDB command can be used to continue execution until a specific line is reached:

(gdb) until main.cpp:39

In the example above, we instruct GDB to continue execution and stop at line 39, in main.cpp.

Some IDE debuggers provide similar functionality. In CLion, the 'Run to Cursor' function can be used.

If, by mistake, you've begun stepping over an instruction-heavy line, just interrupt execution with Ctrl+C in the GDB console (or use the 'pause' function in your IDE debugger). Then, insert the necessary breakpoint and resume execution.

GDB timeout warnings

Bloom can only perform one operation on the AVR target at any given time. If GDB sends a command to Bloom whilst some other operation is taking place, Bloom will not be able to service the command from GDB until the other operation is complete. This can result in GDB having to wait for a lengthened period of time, for a response from Bloom. GDB will report these timeouts as warnings, in the form of "Ignoring packet error, continuing..." messages.

In most cases, the warnings can be ignored. Bloom will eventually get around to servicing the command from GDB. After which, GDB will stop printing the warning messages.


To prevent the warnings, increase GDB's remotetimeout setting:

(gdb) show remotetimeout Timeout limit to wait for target to respond is 2. (gdb) set remotetimeout 30 (gdb) show remotetimeout Timeout limit to wait for target to respond is 30. (gdb)

The timeout value is in seconds. The set remotetimeout 30 command will set the timeout to 30 seconds.

Program memory corruption (redundant software breakpoints)

Upon receiving a shutdown signal, Bloom will attempt a clean shutdown, where it will clear all breakpoints on the target before disconnecting from the debug tool. However, if Bloom is not given a chance to shut down properly, any active software breakpoints will remain in the target's program memory. These breakpoints may block program execution on the target, until the target is reprogrammed.

Furthermore, the debug tool can be left in an undefined state, if Bloom is not given a chance to properly disconnect from it. This can result in issues with starting subsequent debug sessions, until the debug tool is disconnected and reconnected.


Do not force Bloom to shut down immediately, unless you deem it absolutely necessary to do so. Do not send a SIGKILL signal to Bloom's process. Sending a single SIGTERM or SIGINT signal will trigger a clean shutdown. Sending more than one of either of those signals will cause Bloom to shut down immediately.

To remove any redundant software breakpoints, reprogram the target. This can be done via GDB's load command or any other AVR programming software.

If Bloom shuts down abruptly on its own, this is a bug and should be reported as such.