Troubleshooting
If things go not according to plan, a first good step is to have a look at the logging output of PyAvrOCD. If you spot a log entry marked [CRITICAL], it may tell you already what went wrong.
In general, one can distinguish between problems that prohibit the start of the GDB server and problems appearing while debugging.
Debugging does not start
For most of the error messages, it should be obvious what to do. However, there are a few messages that look cryptic, and/or a solution is not apparent.
Apple could not verify “...” is free of malware that may harm your Mac or compromise your privacy.
This is an error message you may get under macOS. It happens when you download executables with a browser or from e-mail, which sets a particular extended attribute. You can remove this extended attribute from the file FILE as follows. Afterward, macOS will start these executables without a hitch.
> xattr -d com.apple.quarantine FILE
No compatible tool discovered
This could mean that no debug tool is connected, that you specified an incompatible debug probe using the --tool option, that another process currently uses it, that the serial line the tool is attached to is busy, or that you have not yet installed the necessary udev rules under Linux.
[Errno 48] Address already in use
This error can happen after the GDB server was terminated before the debugger. If you are working in a CLI environment, you can start PyAvrOCD with a different port using the --port option and tell GDB about the port when connecting with the target remote command. However, waiting a few minutes will also resolve the problem.
ISP programming failed. Wrong connection or wrong MCU?
This error message is displayed when, on a debugWIRE target, the DWEN fuse cannot be set because ISP/SPI programming cannot be initiated. It could be a wiring problem, which, in my experience, is the most likely reason. It could also mean that the MCU is not accessible anymore by ISP programming, which can have many possible causes.
Debug session not started: debugWIRE not activated by power-cycling. Parasitic power supply?
DebugWIRE was not activated despite (automatic) power-cycling. Perhaps there is a parasitic power supply problem? This happens in particular on Xplained-Mini boards since the board power is not switched when an automatic power cycle is performed. A cure can be to power the application circuit connected to the board through the IOREF pin instead of using the 5V or 3.3V pin. If this is not possible, consult the README file of XMiniCore.
Problems while debugging
Code executes slower or faster than expected
Note that PyAvrOCD by itself does not set any timing-related fuses (CKDIV8 on classic chips or FREQSEL on modern chips). This means before debugging, you need to run Burn Bootloader in the Arduino IDE 2 after selecting the right clock settings, or you have to set the timing-related fuses to their desired values by other means.
Loading code and/or debugging feels sluggish
When using debugWIRE, the communication speed is severely limited from the beginning. With Atmel-ICE, the upload speed is roughly one kByte/sec; with the Xplained-Mini boards, it is 0.3 kBytes/sec. Using the readbeforewrite option (which is the default), subsequent uploads may be faster. If the MCU clock frequency is lower than 16 MHz, the upload speed is even slower, and below a clock frequency of 1 MHz, it is no fun at all. Similarly, debugging operations are also somewhat slow.
With JTAG and UPDI targets, this problem should not happen. For JTAG, the default speed is 1 MHz for programming (--prog-clock) and 200 kHz for debugging (--debug-clock). However, you can request higher values when starting PyAvrOCD. Programming speed is only limited by the MCU's maximal frequency (and the wiring). Debugging speed should be no more than a quarter of the actual clock frequency of the target MCU. UPDI communication speed is set to 750 kb/s by default (--comm-speed). On Dx and Ex series chips, speeds up to 1800 kb/s are possible. Refrain from setting speed to 400 kb/s or less.
The debugger does not stop at a line with a set breakpoint, but only later (or not at all)
This happens when the line marked to be stopped at does not contain any machine code. The problem gets worse when the switch Optimize for Debugging in the Arduino IDE 2 is not activated or, if you are working in a CLI environment, you did not use the -Og compiler option.
A different cause for such behavior can be that the UPDI communication speed is too low. I experienced breakpoint and single-step skidding when the UPDI communication was too low, e.g., 400 kHz or less when the MCU ran at 16 MHz. This could lead to stopping at a different location or not stopping at all.
The debugger seems to be confused about the line where it stopped
If the debugger stopped at a line, but from other evidence it is clear that the program flow is somewhere else, it could be that the -mrelax optimization option had been used, which distorts the line numbering information. Compile and link without this option!
When single-stepping, execution jumps around
Probably the same reason as above.
Single-stepping takes forever
You requested a single step, and the debugger seems to take forever to complete this single step. There are a few possible causes. First, when single-stepping a SLEEP instruction, the MCU will go into sleep mode. Second, single-steping a source code line that contains an (implicit) loop can lead to a severe slowdown. Third, this could also be caused by the phenomenon mentioned above (low UPDI communication speed leading to single-step skidding). In all cases, simply stop with Ctrl-C (or the equivalent on the IDE level), set a breakpoint where you want to stop next, and continue execution.
Variables cannot be accessed in the debugger
Again, this might be because you forgot to activate the optimization option for debugging. Or, it can be that the compiler has optimized away your variable. If you really are in need to inspect and maybe change the variable. you can declare it as volatile. Then it will always be visible when in scope. However, handling of it is rather inefficient.
The values of a local variable cannot be changed, or a wrong value is displayed in the debugger
This happened to me recently. The culprit is avr-gcc (version 7.3.0 as distributed with the Arduino IDE). The only way around it is mentioned above. Declare the variable as volatile.
Backtraces are distorted
This sometimes happens when AVR-GDB is not able to figure out the stack frame. I am working on it.
Problems after Debugging
After debugging, the MCU does not seem to execute the stored program, but acts funny
Usually, after having finished debugging, the MCU is released, and the uploaded program will continue to execute. However, if the debugging session has ended abruptly, e.g., by disconnecting power, the debugger did not get a chance to replace the software breakpoints with the original instructions. In this case, the MCU may act strangely. The cure is to simply reflash the MCU.
After debugging, it is impossible to flash a new program using a programmer
When you deal with a debugWIRE target, note that the debugWIRE mode is only left when the command monitor debugwire disable has been typed into the GDB command line before ending the debug session. When you are still in debugWIRE mode, you cannot use SPI programming! You first need to exit debugwire mode. Note also that debugging a debugWIRE target can have adverse effects.
It is also possible that you locked yourself out by setting the wrong fuses (this applies to JTAG and UPDI targets as well).
After debugging, it is impossible to upload a new program using the bootloader.
Usually, the bootloader is erased before debugging starts. This means that you have to reflash the bootloader and maybe change some fuses after debugging.
Signals and error messages
Sometimes, GDB commands fail, often showing a signal that has been received, an error code, and/or an error message. The following is a list of those. When using dw-link, error messages might be brief or missing.
| Signal or error code | Error message | Explanation |
|---|---|---|
SIGHUP |
Enable debugWIRE first: 'monitor debugwire enable or JTAG pins are not enabled or something similar |
If the debugger receives this signal, it means that there is no connection to the target's OCD. You need to enable debugging by setting a fuse or something similar, perhaps by issuing monitor debugwire enable. |
SIGINT |
This is not an error signal. It rather signals that execution has been stopped by a keyboard interrupt (or something equivalent). | |
SIGILL |
Cannot execute because of BREAK instruction | The debugger receives this signal when one tries to single-step or continue executing at a location where the user has placed a BREAK instruction. Alternatively, the BREAK instruction might be a leftover from a previously interrupted debugging session. |
SIGTRAP |
This is not an error signal. Instead, it is issued when execution stops at a place where a BREAK instruction has been placed, and it is not a breakpoint. From this point it is not possible to continue execution. | |
SIGABRT |
See debug server log | This signal is raised after a serious internal error or when execution shall be continued after such an error. Use the monitor info to get more information about the error. |
SIGBUS |
Cannot execute because stack pointer is too low | This signal is raised if the stack threatens to overwrite I/O registers when execution is about to start. |
SIGSEGV |
No program loaded; cannot start execution | This signal is raised when execution is about to start, but there was no prior load command. If this is done intentionally (because it is known that the flash memory has been programmed), one can disable the check by using the command monitor onlywhenloaded disable. |
SISGSYS |
Too many breakpoints set | Execution cannot continue because too many breakpoints have been set. You need to delete some in order to continue execution. |
E01 |
Error code returned when attempting to read or write memory contents while there is no connection to the OCD. | |
E04 |
Error signaling that GDB requested a packet longer than the communicated maximal size. | |
E11 |
Error code returned when writing to flash memory was unsuccessful. | |
E13 |
Error code when writing to memory failed. | |
E14 |
Error code for a read memory failure. | |
E15 |
Error code when GDB sent a data package with the wrong size. |
Internal and fatal dw-link errors
When using the dw-link debug probe, internal errors are reported directly by the dw-link firmware.
If the LED blinks furiously (0.1 seconds on/ 0.1 seconds off), then the debug server has hit an unrecoverable error. This might not be immediately reported by GDB, but one can get information about the specific error by using the monitor info command. The errors are only reported by number. If the error number is less than 100, then it is a connection error. Try again, perhaps after disconnecting and reconnecting everything. Check wiring. If the error persists, try perhaps with a different MCU.
Errors above 100 are serious internal debugger errors. If you have encountered such an internal debugger error, then please try to reproduce the problem and tell me how it happened.
After a reset or a power cycle of the hardware debugger, everything usually works again. If not, you need to unplug everything and put it together again.
| Error # | Meaning |
|---|---|
| 1 | Could not communicate by ISP; check wiring |
| 2 | Could not activate debugWIRE |
| 3 | MCU type is not supported |
| 4 | Lockbits could not be cleared |
| 5 | Lockbits are set but not managed by dw-link |
| 6 | BOOTRST fuse could not be cleared |
| 7 | MCU has a program counter with stuck-at-one bits |
| 8 | RESET line has a capacitive load |
| 9 | Target not powered or RESET shortened to GND |
| 10 | MCU type does not match |
| 11 | DWEN fuse could not be programmed |
| 12 | DWEN fuse is unprogrammed but not managed by dw-link |
| 13 | EESAVE fuse could not be changed |
| 14 | Unknown connection error |
| 101 | No free slot in breakpoint table |
| 102 | Packet length too large |
| 103 | Wrong memory type |
| 104 | Packet length is negative |
| 105 | Reset operation failed |
| 106 | Memory address in flash read operation does not point to page start |
| 107 | Could not complete flash read operation |
| 108 | Could not complete RAM read operation |
| 109 | Memory address in flash write operation does not point to page start |
| 110 | Could not complete flash page erase operation |
| 111 | Could not load data into the flash buffer for writing |
| 112 | Error when programming flash page from buffer |
| 113 | Error verifying flashed page while loading program |
| 114 | Assignment of hardware breakpoint is inconsistent |
| 115 | BREAK inserted by debugger at a point where a step or execute operation is required |
| 116 | Trying to read flash word at an uneven address |
| 117 | Error when single-stepping |
| 118 | A relevant breakpoint has disappeared |
| 119 | Input buffer overflow |
| 120 | Wrong fuse |
| 121 | Breakpoint update while flash programming is active |
| 122 | Timeout while reading from debugWIRE line |
| 123 | Timeout while reading general register |
| 124 | Timeout while reading IO register |
| 125 | Could not reenable RWW |
| 126 | Failure while reading from EEPROM |
| 127 | Bad interrupt |
| 128 | Inconsistent classification of opcodes in range-stepping |
Reporting bugs
If the problematic behavior you have encountered looks like a bug, please send an issue report as described in the section on contributing.