Forums

gdb stub for AVR: breakpoints and single stepping

Started by Ico January 23, 2006
Hello,

I'm working on a `gdb stub' to allow debugging of code in an Atmel AVR
processor using gdb running on the host platform.  Communication between
gdb and the stub is done over RS232. At this moment my platform is the
at90can128, but other AVR types should work as well with little change.

The stub is implemented as an interrupt handler on the serial-rx
interrupt. When the ISR is activated, all registers are pushed on the
stack, and CPU control is handed over to the stub. The stub is a small
piece of code that talks to gdb on the host using the gdb remote
protocol.

At this point, I can read register contents and ram/flash/eeprom memory,
write ram and eeprom, and break the program at any point from the host
debugger. With this functionality, it is possible to interrupt the
program, inspect and change variables and generate a stack trace, which
is already very useful. Code size is still quite small, approx. 500
lines. A premature version can be downloaded at
http://zevv.nl/div/gdbstub.tgz

My next challenge is the implementation of breakpoints and single
stepping. The usual way to put breakpoints in the code is to replace
instructions with a special command which hands over control to the
debugger (or stub). Since the program code is in flash, this can only be
done on a few AVR's which allow for self-programming of flash memory.
However, I'd like to make this stub usable on as much different AVR
types as possible, so I am studying if there might be another way to 
implement breakpoints on the AVR. Any thoughts ?

Regards,

Ico

-- 
:wq
^X^Cy^K^X^C^C^C^C
> My next challenge is the implementation of breakpoints and single > stepping. The usual way to put breakpoints in the code is to replace > instructions with a special command which hands over control to the > debugger (or stub). Since the program code is in flash, this can only be > done on a few AVR's which allow for self-programming of flash memory.
Very difficult. Also, the majority of AVRs that support SPM also have on-chip JTAG, which rather obviates the need for a pure-software solution. Although I haven't tried it, I'm aware that gdb already works directly over the JTAG-ICE. The only way I see to do it is to have a library that links in, the user puts a breakpoint(); function call where desired, recompiles and uploads.
larwe <zwsdotcom@gmail.com> wrote:
>> My next challenge is the implementation of breakpoints and single >> stepping. The usual way to put breakpoints in the code is to replace >> instructions with a special command which hands over control to the >> debugger (or stub). Since the program code is in flash, this can only be >> done on a few AVR's which allow for self-programming of flash memory. > > Very difficult. Also, the majority of AVRs that support SPM also have > on-chip JTAG, which rather obviates the need for a pure-software > solution. Although I haven't tried it, I'm aware that gdb already works > directly over the JTAG-ICE.
Yes, that's true. I was hoping to make a lightweight alternative for the JTAG method, which can also be of used with the smaller members of the AVR family, but the lack of SPM is exactly the problem. For small projects or hobbyists, debugging over the UART would be a pro ofcourse, because no additional JTAG hardware would have to be purchased.
> The only way I see to do it is to have a library that links in, the > user puts a breakpoint(); function call where desired, recompiles and > uploads.
That is what I have so far. It is quite usefull already to be able to inspect and change data and show stack traces, but having dynamic breakpoints would really be a nice-to-have. I think it might be possible to implement breakpoints without SPM, however; if the stub raises a new interrupt and does an IRET right away, the AVR will always execute one instruction before entering the interrupt handler again. This will be a *huge* slowdown (tens or hundreds of times, probably), but this way the stub can just single step CPU instructions until the breakpoint address is reached. This will completely destroy any realtime application behaviour, so it is not my preferred solution, ofcourse. Also, since AVR's don't feature software interrupts, this might render a peripheral useless because a hardware interrupt has to be abused for this. Thanks for your input. I hope do do some more experiments tomorrow. Ico -- :wq ^X^Cy^K^X^C^C^C^C
larwe <zwsdotcom@gmail.com> wrote:
>> My next challenge is the implementation of breakpoints and single >> stepping. The usual way to put breakpoints in the code is to replace >> instructions with a special command which hands over control to the >> debugger (or stub). Since the program code is in flash, this can only be >> done on a few AVR's which allow for self-programming of flash memory. > > Very difficult. Also, the majority of AVRs that support SPM also have > on-chip JTAG, which rather obviates the need for a pure-software > solution. Although I haven't tried it, I'm aware that gdb already works > directly over the JTAG-ICE. > > The only way I see to do it is to have a library that links in, the > user puts a breakpoint(); function call where desired, recompiles and > uploads.
Breakpoints and single stepping are now basically functional, although they seriously slow down execution. I did this by configuring INT0 to generate a level interrupt that is never cleared. When single stepping, the INT0 isr hands over control to the stub after every instruction. When a breakpoint is set, the isr checks if the PC is equal to the breakpoint address, and jumps to the stub if they match. The biggest problem is that INT0 and the associated pin can not be used for other purposes, which is probably not acceptable in most situations. Another challenge would be to make the stub more generic and configurable so it can be used on other AVRs as well. -- :wq ^X^Cy^K^X^C^C^C^C