Hallo,
ich habe vor Kurzem mit Assembler angefangen und bin nun bei Interrupts
angelangt.
Dazu habe ich ein kurzes Beispielprogramm geschrieben, nur funktioniert
es nicht so wie ich es mir vorstelle.
Ich habe PORTA als Output und PE6 als Input für den Interrupt
eingestellt. Eigentlich wollte ich, dass PORTA bei jedem Interrupt eins
hochzählt.
Stattdessen leuchtet PORTA die ganze Zeit, nur beim Interrupt wird das
Muster 0x55 angezeigt. Mehr oder weniger das Gegenteil von dem was ich
wollte.
Ich probiere jetzt schon seit Stunden herum und habe auch schon im
Internet gesucht, aber finde den Fehler leider nicht.
Ich benutze einen Atmega128 auf einem BIGAVR6.
Vielleicht kann mir jemand helfen, bin schon total verzweifelt.
hhh
Jörg W. schrieb:> M103C-Fuse abgeschaltet?>> Ansonsten rennt dein Stack in irgendwelche IO-Register rein.
Ja, ist deaktiviert. Vielleicht liegt es aber generell an irgendwelchen
Fuse-Bits?
Stefan F. schrieb:> .org INT6addr*2
In so einem Fall sieht man sich die Herkunft des Symbols an, es muss ja
irgendwo definiert worden sein, also öffnet man die zugehörige *.inc und
findet dort:
> .equ INT6addr = $00e
Da hat doch tatsächlich jemand berücksichtigt, dass es bei diesem
Controllertyp mehr Speicher für die IVT braucht. Mit mal 2 definierst Du
einen anderen Interrupt und wo der richtige stehen sollte, ist's leer,
bzw. fordert den Controller zum Reset auf.
Stefan F. schrieb:> Dirk schrieb:>> .org nt6addr *1>> probiert?>> Ja, brachte leider nichts.
Falscher Controller eingestellt?
MWS schrieb:> Stefan F. schrieb:>> .org INT6addr*2>> In so einem Fall sieht man sich die Herkunft des Symbols an, es muss ja> irgendwo definiert worden sein, also öffnet man die zugehörige *.inc und> findet dort:>>> .equ INT6addr = $00e>> Da hat doch tatsächlich jemand berücksichtigt, dass es bei diesem> Controllertyp mehr Speicher für die IVT braucht. Mit mal 2 definierst Du> einen anderen Interrupt und wo der richtige stehen sollte, ist's leer,> bzw. fordert den Controller zum Reset auf.
Ok, klingt einleuchtend. Danke schonmal.
Aber aus irgendeinem Grund funktioniert es nicht. Wenn ich den Button an
PE6 drücke ändert sich leider nichts.
> Stefan F. schrieb:>> Dirk schrieb:>>> .org nt6addr *1>>> probiert?>>>> Ja, brachte leider nichts.>> Falscher Controller eingestellt?
Habe es gerade noch mal kontrolliert, ist auch der Richtige.
SEI steht übrigens falsch, besonders da temp auch in der ISR Verwendung
findet. Nimm an dass EIFR.INTF6 zu diesem Zeitpunkt gesetzt ist, dann
sollte der Controller unmittelbar nach SEI den Int6-Vektor ausführen.
Macht er das, dann wäre alles noch gut.
Wenn er jedoch noch ldi temp, 1<<SE abarbeitet und erst dann den Vektor
anspringt, dann wird temp zerstört und mit dem Inhalt des PORTA geladen.
Dieser Inhalt setzt nicht mehr MCUCR.SE, sondern macht irgendwas anderes
recht Lustiges.
Stefan F. schrieb:> sei> ldi temp, 1<<SE> int6:> in temp, PORTA
Sowas vermeidet man, indem man a) INTF6 vor Freigabe der Interrupts
löscht, b) Konfigurationssequenzen atomar macht (CLI/SEI) oder c) SEI
erst dann schreibt, wenn man mit der Konfiguration durch ist. Auch a, b
und c zusammen ist nicht verkehrt.
Stefan F. schrieb:> Aber aus irgendeinem Grund funktioniert es nicht. Wenn ich den Button an> PE6 drücke ändert sich leider nichts.
Dann lese doch in einem Loop mit PINE.6 was dein uC am Pin sieht und
zeige es mit LED an PORTA (LED=ON / Pin = 1). Oder umgekehrt, egal.
Wenn die LED nicht auf Button reagiert, stimmt irgendetwas mit Pull-Up
bzw. Eingang nicht.
Wenn die LED reagiert, stimmt irgendetwas mit deinem INT nicht.
So schwer ?
P.S.
Bedenke aber, dass 0xFF von uC als NOP gesehen wird.
> ... bin nun bei Interrupts angelangt.
Das heißt, dass zuvor (auf diesem uC) der Aufruf (und die Rückkehr aus)
einer normalen Subroutine funktioniert hat?
Marc V. schrieb:> Bedenke aber, dass 0xFF von uC als NOP gesehen wird.
das könnte zumindest die Belanglosigkeit *1/*2 in dem frühem Stadium
erklären wenn, bzw. da mangels Alternativen, $ffff (eigentlich UOP) als
NOP ($0000) gesehen wird und interessante Folgen (bei allen ints
passiert das gleiche, obwohl es funktioniert hat) verursachen.
Noch ein Bedenkungsvorschlag:
falls sich der Bezeichner EICRB als minderwertig (<$40) herausstellen
sollte bspw. als $3a Wert, dann wäre
out DDRA, temp; $1a sts $1a+$20,temp
und
sts EICRB, temp;$3a out $1a,temp
äquivalent und
out EICRB, temp;$3a
für den mutmaßlichen Plan geeigneter
Dirk B. schrieb:> Marc V. schrieb:>>> Bedenke aber, dass 0xFF von uC als NOP gesehen wird.> das könnte zumindest die Belanglosigkeit *1/*2 in dem frühem Stadium> erklären wenn, bzw. da mangels Alternativen, $ffff (eigentlich UOP) als> NOP ($0000) gesehen wird und interessante Folgen (bei allen ints> passiert das gleiche, obwohl es funktioniert hat) verursachen.>> Noch ein Bedenkungsvorschlag:> falls sich der Bezeichner EICRB als minderwertig (<$40) herausstellen> sollte bspw. als $3a Wert, dann wäre> out DDRA, temp; $1a sts $1a+$20,temp> und> sts EICRB, temp;$3a out $1a,temp> äquivalent und> out EICRB, temp;$3a> für den mutmaßlichen Plan geeigneter
Danke für euren Input. Dadurch hab ich den Fehler gefunden.
Statt
1
lds temp, EICR
2
ori temp, 1<<ISC61
3
sts EICRB, temp
gehört nämlich.
1
in temp, EICR
2
ori temp, 1<<ISC61
3
out EICRB, temp
Wieder was gelernt.
Danke nochmal allen die mir geholfen haben.
Dass das der ursprüngliche Fehler gewesen sein soll, kann ich nicht
glauben. Wie Dirk B. schrieb, wird mit
1
lds temp, EICRB
2
ori temp, 1<<ISC61
3
sts EICRB, temp
DDRA verändert, da dieses jedoch bereits auf 0xFF steht, bewirkt das
ori gar nichts. Und dass EICRB nicht beschrieben wird, heißt
lediglich, dass INT6 nicht durch 'falling edge', sondern durch 'low
level' getriggert wird. Statt einige Male durch das Prellen wird also
vielfach, solange der Taster gedrückt ist, getriggert, wie ließe sich
damit die Aussage
> Stattdessen leuchtet PORTA die ganze Zeit, nur beim Interrupt> wird das Muster 0x55 angezeigt.
erklären?
Hallo,
wenn man mal endlich den kompletten Code mit allen Zeilen sehen könnte.
Dann noch das Makefile dazu und jeder könnte gegen testen.
Wir verwenden solch zwei Macros für das Lesen und Setzen der Register,
dann spart man sich das nachsehen für jeden AVR µC in der
Registerbeschreibung.
... was sich speziell beim ATmega128 empfiehlt, denn hier ist die
Zuordnung doch etwas wirr, so liegt z.B., wie gesehen, EICRB mit 0x3A im
I/O-Bereich, EICRA hingegen ist mit 0x6A 'memory mapped'.
S. Landolt schrieb:> Dass das der ursprüngliche Fehler gewesen sein soll, kann ich nicht> glauben.
bislang sind 3 bekannt:
1)INT6addr*2: wg. NOP Lesung von UOP wohl praktisch folgenlos
2)praktisch Level statt Flanke (aktuell bzw. aktuell nicht mehr)
3) SEI zum unglücklichen Zeitpunkt. Getriggert könnte MCUCR ca. mit
$55-1 initialisiert werden und das MCUCR hat auch
Interruptvectorselect...für 'ne abschließende Erklärung noch zu knapp,
aber evtl. interrupt via bootloadervector --> Nop/UOP-Slide-->reset .org
0 (aus vector_table_0)
vom Gefühl dürfte das Muster $55 nicht konstant angezeigt worden sein,
sondern nur sichtbar. Vielleicht fehlt noch Vcc o.ä. Kleinigkeiten, was
auch schwer erklärbare Fehler/Funktionieren verursachen kann.
>...hier ist die Zuordnung doch etwas wirr
nette Verharmlosung: praktisch sind Bezeichner die ihre Funktion/Zweck
(Vereinfachung kontrollierter Programmierung) nicht erfüllen ein
heftiger Naming-Bug, allerdings hätte die Behebung für (A)SM bspw.
EICRA_m EICRB DDRA DDRF_m Bugs für (B)asic,(C),Pascal verursacht und der
von Karl vorgestellte mini-compiler kann den BUG für die erste Sprache
ASM des ABC zumindest etwas verharmlosen ;-
Kompatibilität geht manchmal sehr spezielle Wege...