Debugger springt nicht in Interrupt INT0 / INT1

Ingolf

Neues Mitglied
06. Jan. 2009
8
1
3
Dortmund
Guten Abend :)
Finde es nicht heraus, warum der Debugger (mit Alt-F5 und steppen F11) nicht in die Int0- oder Int1- Routine springt wenn ich PIND2 oder PIND3 rechts im Fenster toggle. Atmel Studio 7 (Version: 7.0.1188 - ) unter Windows 10, AVRISPmkII und STK500, ATMega32/4Mhz. Auf der Hardware funktioniert es, d.h. die LED wird je nach Interrupt ein- und ausgeschaltet.

Hier mein geklauter Code, ATMega32/4Mhz


CodeBox Assembler
.NOLIST
.INCLUDE "m32def.inc"
.LIST

.EQU   fq       =4000000    ; Quarzfrequenz

.def temp = r16

.org 0x000
         rjmp main            ; Reset Handler
.org INT0addr
         rjmp int0_handler    ; IRQ0 Handler
.org INT1addr
         rjmp int1_handler    ; IRQ1 Handler

main:                         ; hier beginnt das Hauptprogramm

         ldi temp, LOW(RAMEND)
         out SPL, temp
         ldi temp, HIGH(RAMEND)
         out SPH, temp

         ldi temp, 0x00
         out DDRD, temp

         ldi temp, 0xFF
         out DDRB, temp

         ldi temp, 0xFF           
         out PORTB, temp   ; STK 500 alle Led aus

         ldi temp, (1<<ISC01) | (1<<ISC11) ; INT0 und INT1 auf fallende Flanke konfigurieren
         out MCUCR, temp

         ldi temp, (1<<INT0) | (1<<INT1) ; INT0 und INT1 aktivieren
         out GICR, temp

;         sei                   ; Interrupts allgemein aktivieren

loop:    rjmp loop             ; eine leere Endlosschleife

int0_handler:
         sbi PORTB, 0
        ldi r17,0xAA
         reti

int1_handler:
         cbi PORTB, 0
        ldi r17,0xBB
         reti


Hat jemand einen Tipp? Danke :)
 
Hallo Ingolf,

schau mal die Zeile 38 an. Die Interrupts müssen global aktiviert werden. SEI ist hier auskommentiert.

Eventuell hast du es einmal für die Hardware mit SEI assembliert und später vor dem debuggen auskommentiert. Vielleicht liegt es ja daran.

Grüße,
Dirk :ciao:
 
Hallo Dirk,
danke für deine schnelle Antwort.
Ich bin mir nicht sicher, aber ich meine ich hätte es vorher auch mit Sei probiert. Kann ich erst morgen testen, pc ist schon aus und morgen früh raus. :-/
Mehr morgen, gute Nacht allerseits.
 
Wenn die Interrupts global unterdrückt sind, wird auch kein Interrupt-Vektor automatisch angesprungen.
Du verwendest INT0 und INT1 als flankengetriggerten Interrupt, d.h. das interruptauslösende Ereignis (=fallende Flanke) setzt das jeweilige externe Interrupt Flag (INTF0, INTF1) im General Interrupt Flag Register (GIFR), was Du auslesen/im Simulator sehen kannst (auch wenn die IRQs global nicht freigegeben sind).
Das gesetzte Flag bleibt solange stehen, bis Du es entweder selbst "löschst", oder der Interrupt nach globaler Aktivierung abgearbeitet wird (=der Interruptvektor durch die Interrupthardware angesprungen wird).
Der Interrupt wartet quasi im Hintergrund...

P.S.: Willkommen im Forum
 
Dankeschön :) Auch für die prima Erklärung.
Also: "sei" wieder aktiviert, im Debugger ist alles so wie du es beschrieben hast.
Die Bits werden gesetzt.
sreg.jpg
Aber die Interruptroutine wird im Debugger nicht angesprungen.
Dann habe ich mal spasseshalber den Test gemacht und ohne "sei" das Programm in die Hardware geladen ...
Ergebnis: Funktioniert auch ohne "sei".
Jetzt bin ich total verwirrt. Warum springt der Debugger nicht in die Interruptroutinen?
Bestimmt mache ich was falsch. Wenn ich nur wüsste was! :(

//Edit: Unter http://www.avr-asm-tutorial.net/avr_de/interrupts/int_vektor.html
etwa in der Mitte der Seite gelesen, daß dieses .org-Zeugs in der Interrupttabelle nicht gut ist.
 
Zuletzt bearbeitet:
Gefunden :)
Unter "Tools|Options|Tools|Tool Settings", den "Mask interrupts while stepping" auf false setzen.
So was ...
 
  • Like
Reaktionen: Dirk
etwa in der Mitte der Seite gelesen, daß dieses .org-Zeugs in der Interrupttabelle nicht gut ist.
Sehe ich nicht so. Die .org-Direktive sorgt dafür, daß die Sprunganweisung zum jeweiligen Interruptvektor immer an der korrekten Flash-Adresse steht. Entweder ich aktiviere einen Interrupt, und platziere entsprechenden Code im korrespondierenden Vektor, oder nicht.
Selbst mit den RETIs in ungenutzten Vektoren, die versehentlich (wie auch immer) aktivierte Interrupts scheinbar behandeln sind nicht problemlos - spätestens, wenn ein unbeabsichtigter ständiger Interrupt den Controller auslastet.
Wenn Du "versehentlich" in so eine RETI-gesicherte IVT JUMPst, gibts auch Stacküberlaufe...
(in ASM gibts kein "versehentlich" - der Controller macht exakt was Du anweist (ob das auch das ist, was Du anweisen willst, ist 'ne andere Sache))
Laß Dir nicht vorschreiben, wie Du mit Deinem Flash umzugehen hast!

Wenn ein Interrupt zuschlägt, wird die korrespondierende Adresse am Anfang des Flash abgearbeitet (eben die in der IVT).Was Du dahin schreibst, ist Deine Sache.
Du kannst beliebigen Code in der IVT platzieren, Du mußt aber berücksichtigen, daß Interrupts dort landen, wenn (falls) Du sie aktivierst.

Aber genug OT, schön daß Du die Ursache gefunden hast. Ich hatte auch mal so'n scheinbaren Fehler im Simulator, in Hardware lief's.
(Timerüberlauf triggert AD-Conversion (ADATE), ADC-Complete-ISR wird im Simulator nie angesprungen - möglicherweise war das damals sogar dieselbe Geschichte?)
 


CodeBox C
.org 0x000         rjmp main            ; Reset Handler
.org INT0addr         rjmp int0_handler    ; IRQ0 Handler
.org INT1addr         rjmp int1_handler    ; IRQ1 Handler
Das sehe ich wie LotadaC, aber man muss hier differenzieren. Du verwendest die Sprungmarken der Tabelle bei ihrem Namen. Genau so sollte es auch gemacht werden. Würdest du jetzt aber die Offsets als Ziffer angeben (wie bei Reset, da ist es aber egal, das ist immer 0) dann hättest du spätestens dann starke Probleme wenn du den Chip tauschst. Beispielsweise der Mega88 und Mega168 unterscheiden sich ausschließlich in der Speichergröße, aber alle Adressen sind deswegen anders. Nutzt du die Namen brauchst du nur den Chip zu ändern -> Werte ändern sich automatisch (falls nötig). Das wars.

* stimmt nicht ganz. Weil wegen mehr Speicher braucht der 168 bei manchen Befehlen auch noch 1 Taktzyklus länger. Details…
 
Noch einen Hinweis: in den Prozessordefinitionsdateien wird auch eine Konstante definiert, die die Größe der IVT bekanntmacht (IntVectorsSize oder so ähnlich) - wenn man den Reset-Label mit .org an diese Stelle setzt, muß der letzte definierte verwendete IRQ nicht mehr zwingend der mit der niedrigsten Priorität sein. Gerade wenn man den Code wiederverwenden will, empfiehlt sich das.

Die Adresse für den Reset-Einsprung (0x0000) ist in keiner Definitionsdatei definiert - verwendet man .org muß also die fixe Zahl verwendet werden (gilt aber mMn in allen AVRs).

Alle AVR mit mehr als 8k Byte Flash (also mehr als 4 kwords) können den gesamten Flash nicht mehr mit RJMP anspringen(*), brauchen also eine IVT wo JMP reinpaßt (zwei Byte "breit"). Willst Du jetzt zB in einem IRQ nur mal ein Bein setzen/löschen/toggeln, kannst Du das mit SBI/CBI und RETI direkt in den zwei Bytes IVT erledigen, ohne JMP.

(*) RJMP adressiert +/- 2k words von der aktuellen Position aus. Der ProgrammCounter kann dabei überlaufen, deswegen kann man auch von 0x0000 nach 0x0FFF (Wordadresse) RJMPen - eben ein Word zurück. Damit kann man übrigens auch in großen AVR halbwegs sicher schnellere RJMPs für Interrupts nutzen - man platziere die ISRs einfach "hinten" im Flash (mit .org), und springe mit RJMP (wobei man ganz Hardcore in der 2byte-IVT schonmal ein Register sichern kann, vor dem RJMP)

Übrigens ist RJMP in der IDE leider nicht wirklich relativ umgesetzt. Die als Konstante anzugebende relative Sprungweite wird von der IDE als absolutes Ziel interpretiert, und nicht direkt in den Opcode übernommen (RJMP 10 springt also nicht etwa 10+1 words weiter, sondern in Wordadresse 10. Konstanten kleiner Null werden bei Null abgeschnitten). Üblicherweise verwendet man aber Label, und überläßt der IDE die Festlegung der Konstante für den Opcode... da paßt das natürlich...
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)