Forum: Compiler & IDEs avarice, gdb, ddd ATMega32


von Wolfgang H. (frickelkram)


Lesenswert?

Hi zusammen,

im Moment versuche ich einen Controller, bestückt mit ATMega32 per JTAG 
unter Linux zu debuggen. Ich compiliere mit GCC und nutze den AVR-Dragon 
für das Programmieren und Debuggen. Als debugger setze ich GDB und als 
Frontend DDD ein.

Leider passieren im DDD seltsame Dinge. Das "continue", "step" und 
"next" funktioniert nicht wie erwartet.

Die Anwendung nutzt V-USB und es gibt einen Timer0 ISR-Routine in der 
Ports eingelesen und entprellt werden (Interruptrate 1/10ms). Der Status 
wir dann per HID-Joystick an das Notebook geschickt. Wenn ich mit das 
Ergebnis mit "jstest /dev/input/js0" anschaue, funktioniert es auch. Der 
Status der Ports wird als "Buttons" dargestellt. Allerdings gibt es noch 
ein paar Fehler im Ablauf, die ich analysieren und korrigieren möchte, 
darum das Debuggen. Mit avarice und DDD habe ich bisher nicht 
gearbeitet, da ich überwiegend mit dem Mega8 gearbeitet habe und 
simulavr verwendet habe. Beim Mega32 bietet sich jetzt aber die 
JTAG-Schnittstelle an.

Der Code ist mit;
  avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega32 -DF_CPU=12000000L 
-DDEBUG=dwarf-2 -DDEBUG_LEVEL=2 -g -c main.c -o main.o
compiliert, keine Warnings oder Fehlermeldungen.

avarice starte ich mit;
  avarice --program --file main.elf --part atmega32 -g :4242
Code wird geladen, fuses angezeigt, keine fehlermeldungen, "Waiting for 
connection"

Dann starte ich ddd;
  ddd --debugger "avr-gdb -x gdb.conf"

Inhalt von gdb.conf:
file main.elf
target remote localhost:4242

ddd startet, source code wird angezeigt. Programmzeiger steht auf der 
main function.

----------------
int main(void) {

    needupdate = 1;

    initProg();

    while (1)
    {   // main event loop
#if !DEBUG_LEVEL
        wdt_reset();
#endif
        usbPoll();

        if (needupdate && usbInterruptIsReady()) {
            needupdate = 0;
            usbSetInterrupt(ReportBuffer, BuildReport());
        }
    }
    return 0;
}
-------------------

Bis hier hin sieht das alles genau so aus wie es sein sollte.

Probleme gibt es wenn ich debuggen möchte.

Ich setze einen Breakpoint auf die 1. Zeile mit der Zuweisung von 1 auf 
needupdate;
"Continue" -> bleibt genau auf der Zeile stehen.
Wenn ich jetzt wieder "Continue" wähle stoppt die Anzeige nach einem 
Moment wieder an der selben Stelle. Diese Codezeile sollte aber nur ein 
einziges mal erreicht werden. Später wird ja nur noch die endlose while 
Schleife durchlaufen.

Verstehe ich da irgendetwas nicht richtig oder verhält sich das System 
falsch? Der Watchdog ist aus. Kann es trotzdem sein das durch das 
Debuggen Resets ausgelöst werden und darum immer wieder der selbe 
(einige Breakpoint im Programm) "angesprungen" wird?

Wie verhält es sich mit den Interrupts, wenn man auf diese Weise mit 
JTAG debugged?

DDD-Version: 3.3.12 (x86_64-pc-linux-gnu)
AVaRICE version 2.10, Feb  8 2010 07:22:54
gcc-Version 4.3.5 (GCC) (--build=x86_64-linux-gnu 
--host=x86_64-linux-gnu --target=avr)
GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
Linux: uname -rm ->  2.6.38-16-generic x86_64 (Ubuntu natty)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Wolfgang Heinemann schrieb:

> Der Code ist mit;
>   avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega32 -DF_CPU=12000000L
> -DDEBUG=dwarf-2 -DDEBUG_LEVEL=2 -g -c main.c -o main.o
> compiliert, keine Warnings oder Fehlermeldungen.

Mit hinreichend neuem GCC kannst du übrigens auch mal -gdwarf-4
probieren.

> avarice starte ich mit;
>   avarice --program --file main.elf --part atmega32 -g :4242

--program ist übrigens inzwischen deprecated.  Ich mag neben
AVRDUDE nicht noch ein zweites Tool in dieser Hinsicht pflegen.
Entweder also mit AVRDUDE programmieren, oder mit der SVN-Version
von AVaRICE dann das "load"-Kommando vom GDB aus benutzen.

> Verstehe ich da irgendetwas nicht richtig oder verhält sich das System
> falsch? Der Watchdog ist aus. Kann es trotzdem sein das durch das
> Debuggen Resets ausgelöst werden und darum immer wieder der selbe
> (einige Breakpoint im Programm) "angesprungen" wird?

Nicht durchs Debuggen, aber sowas passiert beispielsweise, wenn
du Interrupts freigibst, für die du vergessen hast, eine ISR
anzulegen.  Der Standard-Interruptvektor ist ein Sprung auf
Adresse 0.

> Wie verhält es sich mit den Interrupts, wenn man auf diese Weise mit
> JTAG debugged?

Die treten ganz normal auf.  Timer werden normalerweise während
des Programmhalts ebenfalls angehalten, sollten dann also nicht
triggern.  Beim single step kann man aber schon mal plötzlich in
einer ISR landen, aber single step ist sowieso eher langsam, weil
er mit viel Overhead in der ICE-Kommunikation verbunden ist.
Besser ist es, temporäre Breakpoints zu setzen und sich so durch
das Programm zu hangeln.

von Wolfgang H. (frickelkram)


Lesenswert?

Hi,

danke für die Hilfe. Ich habe übers Wochenende nichts gemacht, mir das 
Ganze aber heute noch mal angeschaut.

Die ISR-Routine ist definiert, das hatte ich schon geprüft. Den avarice 
Aufruf habe ich geändert, es macht natürlich nicht unbedingt Sinn das 
Programm bei jeder Simulation neu in das Flash zu brennen.

Das mit den steps habe ich mal gelassen. Statt dessen mit continue 
breakpoints und data watch gearbeitet. Das geht in der Tat deutlich 
besser. Sogar in der ISR Routine stoppt der Debugger wenn sich der 
beobachtete Datenwert ändert.

Alles in Allem funktioniert das jetzt ordendlich obwohl ich am Programm 
nichts geändert habe. Der Fehler, dem ich hinter her gejagt bin war 
übrigens mal wieder ein Standardfehler ... ich hatte die Fuse so gesetzt 
das das EEPROM gelöscht wird. Die Werte aus dem EEPROM sind dann 
natürlich 0 und mein Programm hat nicht die Werte aus dem EEPROM geladen 
die ich im C-Code als Konstanten gesetzt hatte ...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.