Forum: Mikrocontroller und Digitale Elektronik Eine kurze Frage an die AVR Assembler Experten


von Fischpudding (Gast)


Lesenswert?

eine Frage an die AVR Assembler Experten

Ich hab mir von Pollin ein paar der Microcontroller MEGA 2560PRO Boards 
bestellt und bin grad am Testen. Ich programmiere in Assembler mit dem 
Microship Studio ehemals AVRStudio.
Ich wollte erst mal eine Blink LED über den Timer5 Interrupt blinken 
lassen. Das Ein/Ausschalten wird über den OCRA Compare Interrupt 
gesteuert.
Im Prinzip funktioniert alles aber...
Nun ist es so, daß der Interrupt aufgerufen und abgearbeitet wird ohne 
das ich den globalen Interrupt freigegeben habe (SEI) den OCRA Int hab 
ich freigegeben.
Irgend jemand eine Idee? Oder liegts daran daß das Board einen 
Bootloader hat und dort werden die INTs bereits enabled?

schon mal Danke für die Hilfe

von Stefan F. (Gast)


Lesenswert?

Du hast vergessen, deinen Quelltext und den Schaltplan zu zeigen.

von Gerald K. (geku)


Lesenswert?

Ich würde als erstes mit einem fertigen Beispiel beginnen. Das Flashen 
ist die erste Hürde.

Und anschließen versuchen das Beispiel selbst zu bilden. Und dann erst 
mit neuem Code beginn, wobei man durchaus das Beispiel abwandeln kann.

: Bearbeitet durch User
von Andreas G. (fischpudding)


Lesenswert?

Hab ich nicht vergessen, nur nicht für nötig gehalten. Die Schaltung 
funktioniert und das Programm auch. Nur sind nach dem Reset die 
Interrupts freigegeben. Das stört mich im Prinzip nicht ich hätte nur 
gern gewusst woran das liegt

von Stefan F. (Gast)


Lesenswert?

Andreas G. schrieb:
> Hab ich nicht vergessen, nur nicht für nötig gehalten. Die Schaltung
> funktioniert und das Programm auch.

Na dann brauchst/willst du offenbar keine Hilfe.

Der Fehler ist übrigens in der Zeile mit dem Dingsbums und deine LED hat 
die falsche Farbe.

von Thomas Z. (usbman)


Lesenswert?

Fischpudding schrieb:
> Nun ist es so, daß der Interrupt aufgerufen und abgearbeitet wird ohne
> das ich den globalen Interrupt freigegeben habe (SEI)

nun es wird wohl so sein, dass das dann jemand schon für dich gemacht 
hat.
Bootloader oder InitCode kommen da in Frage.

von Beo Bachta (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Na dann brauchst du keine Hilfe.

Full Ack.

Aber meine Glaskugel sagt dass der Interrupt zufällig durch
direktes Schreiben auf das entsprechende Register (SREG)
enabled wird. Richtig wäre es eine Read-Modify-Write Operation
zu verwenden die nur das betreffende Bit ändert das man ändern
will.

von Stefan F. (Gast)


Lesenswert?

Meine Glaskugel sagt, dass die LED an einem Output-Compare Ausgang 
hängt. Aber da ist auch viel Nebel im Bild.

von Andreas G. (fischpudding)


Lesenswert?

Nein, die LED hängt an einem normalen Port. Hier mal der Ausschnitt 
welcher die LED anschaltet. Dann gibts noch einen Overflow Int, der 
schaltet sie dann wieder aus. Im Main gibts keinen SEI Befehl.
1
LED_Int_Service_T5_compare_match:
2
    PUSH  R16                ; int prefix
3
    IN    R16,    SREG
4
    PUSH  R16
5
    PUSH  R17
6
    LDS    R16,    LED_Status      ; OR PortK & LED_Status
7
    LDS    R17,    PortK
8
    OR    R17,    R16
9
    STS    PortK,    R17
10
    POP    R17                ; int suffix
11
    POP    R16
12
    OUT    SREG,    R16
13
    POP    R16
14
    RETI

Ich denke es ist so wie usbman oben schon geschrieben hat. Bootloader 
oder Init-Code. Wobei... Wenn mit dem Init-Code meiner gemeint sein 
sollte dann kanns auch nicht sein...
Naja, dachte nur jemand hatte den Effekt schon mal

: Bearbeitet durch Moderator
von Stefan F. (Gast)


Lesenswert?

Zeige den ganzen Quelltext, nicht nur den Teil, der den Fehler nicht 
enthält.

von Content B. (Firma: Da) (contentblocker_da)


Lesenswert?

Stefan ⛄ F. schrieb:
> Zeige den ganzen Quelltext, nicht nur den Teil, der den Fehler nicht
> enthält.

An meinem Auto geht der rechte Blinker beim Benutzen doppelt so schnell, 
woran kann das liegen?

A:
Poste alle Karroserieteile und den Schaltplan des Kabelbaums...


Bei Assembler für AVR kann man, z.B. im Bootloder, einen Interrupt 
setzen der dann aktiv wird, wenn irgendeine Bedingung erfüllt wird. Dies 
ist wenn man schlampig programmiert und der Bootloader das Hauptprogramm 
anspringt.

Poste den Code des Bootloaders...

von LostInMusic (Gast)


Lesenswert?

>Nun ist es so, daß der Interrupt aufgerufen und abgearbeitet wird ohne
>das ich den globalen Interrupt freigegeben habe (SEI)

Dann schreib doch ein Mini-Prüfprogramm, das nur das SREG einliest, das 
I-Bit ausmaskiert und eine LED einschaltet, wenn es gesetzt ist. Dann 
weißt Du, ob es im Bootloader passiert ist oder Du doch woanders suchen 
musst.

von Karl B. (gustav)


Lesenswert?

Hi,
wieviel Byte hast Du für SRAM Label Port-K reserviert?
Wo steht die SRAM Init Routine?
Warum bleibst Du nicht im cseg?
Wieso der Umweg über dseg?

ciao
gustav

von hinterslichtgeführter (Gast)


Lesenswert?

Die Gedanken des Karl B. (gustav) sind unergründlich um nicht
zu sagen "wirr".

von c-hater (Gast)


Lesenswert?

Andreas G. schrieb:

> Hab ich nicht vergessen, nur nicht für nötig gehalten. Die Schaltung
> funktioniert und das Programm auch. Nur sind nach dem Reset die
> Interrupts freigegeben. Das stört mich im Prinzip nicht ich hätte nur
> gern gewusst woran das liegt

Kann eigentlich nur an eine lausigen Bootloader liegen, der nicht 
ordentlich aufräumt, bevor er die Kontrolle an die Anwendung übergibt.

Allerdings: Wie sollte ein Bootloader eine normale Flashprozedur 
überleben? Da kann doch nur ein Vollidiot das Chip-Erase vor dem Flashen 
ausgeschaltet haben. Oder der Vollidiot hat in voller Absicht den 
Bootloader zum Flashen seiner Anwendung benutzt.

Wer käme denn für die Rolle dieses hypothetischen Vollidioten in Frage?

von Andreas G. (fischpudding)


Lesenswert?

Das war nur ein Test... .DSEG hat im Moment nur ein Byte. Port K ist ein 
normaler IO Port der leider ausserhalb des Bereiches liegt den man mit 
In/Out ansprechen kann. Ist wohl in den Ram Bereich gemappt. Daher LDS, 
STS.
Hab mir mal das I-Flag ausgeben lassen (danke für den Tipp) und ja das 
ist beim Startup gesetzt. Komisch das. Naja, wenn man es weis, ist es ja 
ok.

von c-hater (Gast)


Lesenswert?

Andreas G. schrieb:

> Hab mir mal das I-Flag ausgeben lassen (danke für den Tipp) und ja das
> ist beim Startup gesetzt. Komisch das. Naja, wenn man es weis, ist es ja
> ok.

Nein, ist es nicht. Das hat nach Reset gelöscht zu sein. Ende der 
Ansage.

von Andreas G. (fischpudding)


Lesenswert?

@c-hater,
Naja, der Bootloader überlebt den Flash über USB. Muss er ja auch. Und 
ja, der Vollidiot hat den Bootloader zum flashen benutzt. Dann gehts 
auch entspannt mit USB. Die normalen 2560 Boards haben einen mega8USB 
für die Kommunikation drauf. Dieses nicht nur einen dummen USB/Seriell 
Wandler. Und ich hab keinen Bock jedesmal über SPI zu flashen. Keine 
Ahnung ob der Ponyprog den 2560 überhaupt kennt

von Karl B. (gustav)


Lesenswert?

Andreas G. schrieb:
> Port K ist ein
> normaler IO Port der leider ausserhalb des Bereiches liegt den man mit
> In/Out ansprechen kann. Ist wohl in den Ram Bereich gemappt. Daher LDS,
> STS.

Hi,
ja, ja "Memory mapped". Der Begriff ist mir im Zusammenhang mit einigen
"Megas" noch in Erinnerung.
Da freute man sich über mehr Features damals, und dann lassen sich die 
Programme nicht 1:1 auf die "neueren" Targets portieren.

ciao
gustav

: Bearbeitet durch User
von Andreas G. (fischpudding)


Lesenswert?

portieren ist einfach. Einfach Assembler anwerfen und alle angemeckerten 
In/Out gegen LDS/STS ersetzen. Man verliert da nur, glaube ich, einen 
Taktzyklus

von Karl B. (gustav)


Lesenswert?

Andreas G. schrieb:
> portieren ist einfach.

Hi,
klar, wenn man das vorher weiß, wie der "neue" AVR angesprochen werden 
will.
Komme deswegen drauf, weil es 'mal bei Einführung von "besseren" AVRµCs
heftige Diskussionen gab damals.
Und ob die Maxime heute noch Gültigkeit hat ?:
Lieber im cseg arbeiten, weil dseg bei den "alten" schon abweichende 
Zugriffszeiten hatte. Ganz zu schweigen dann vom noch "langsamerem" 
eseg.

ciao
gustav

von kseege (Gast)


Lesenswert?

Dazu muss man kein AVR-Assembler Guru sein, die Grundlagen der
Elektronik reichen, der Effekt ist sozusagen "der Grundzustand".

Nach dem Anlegen der Versorgungsspannung haben alle SRAM-zellen
und Register beliebige Werte und nur im Controller enthaltene 
zusätzliche Hardware setzt einige Zellen auf voreingestellte Werte, die 
im Datenblatt
aufgeführt werden. Ob das auch bei Reset passiert oder nur bei
Power-On ist harwareabhängig. Wenn im Datenblatt
dazu nichts steht, geht der vorsichtige Mensch davon aus, daß nur der
ProgramCounter auf seinen definierten Startwert gesetzt wird
und alles Andere undefiniert ist.

Ansonsten steht in den beschreibbaren Zellen, was eventuell vorher
gestartete Programme dort hinterlassen haben und nur Du kannst wissen,
was da vor dem Reset alles gelaufen ist.

Natürlich kann man immer von Anderen erwarten, daß sie die Arbeit für 
einen
selbst erledigen, aber warum sollten sie das tun? Deshalb die alte 
Regel:
If You want to have it done right, You have to do it Yourself.
Einfach "clear global interrupt" und "set stackpointer" als erste 
Befehle eintragen. Hilft zuverlässig gegen Überraschungen.

Mit freundlichen Grüßen an alle, die Automatiken für "normal" halten
und den Grundzustand gar nicht mehr kennen

Klaus

von Andreas G. (fischpudding)


Lesenswert?

Naja, den Stack initialisiere ich immer als erstes. Nur um die Flags hab 
ich mich nie gekümmert. Das ging bisher immer gut.

von Holger D. (hodoe)


Lesenswert?

Andreas G. schrieb:
> Naja, den Stack initialisiere ich immer als erstes. Nur um die
> Flags hab
> ich mich nie gekümmert.

So mache ich es auch. Ich habe nach einem Reset noch nie erlebt, dass 
Bit 7 des SREG nach einem Reset den Wert 1 hat.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Das I-Flag wird beim Reset immer gelöscht. Wäre dies nicht der Fall,
könnte ein Programm schon direkt nach dem Start unterbrochen werden,
noch bevor ein evtl. vorhandener CLI-Befehl ausgeführt wird. Deswegen
ist ein CLI am Programmstart nicht nur überflüssig, sondern auch
unsinnig.

kseege schrieb:
> Natürlich kann man immer von Anderen erwarten, daß sie die Arbeit für
> einen selbst erledigen, aber warum sollten sie das tun? Deshalb die
> alte Regel: If You want to have it done right, You have to do it
> Yourself.

Gerade beim ATmega2560 mit seinen ca. 180 I/O-Registern wäre es ziemlich
mühsam, wenn man diese alle beim Programmstart explizit initialisieren
müsste. Da vertraue ich lieber dem Datenblatt:

"During reset, all I/O Registers are set to their initial values"

von Einer K. (Gast)


Lesenswert?

Yalu X. schrieb:
> Deswegen
> ist ein CLI am Programmstart nicht nur überflüssig, sondern auch
> unsinnig.

Die Annahme ist hier ja, dass der Bootloader das I Bit stehen lässt.
Von da her, ist es evtl. schon sinnvoll, die Interrupts abzuschalten.

von Rolf M. (rmagnus)


Lesenswert?

Content B. schrieb:
> Stefan ⛄ F. schrieb:
>> Zeige den ganzen Quelltext, nicht nur den Teil, der den Fehler nicht
>> enthält.
>
> An meinem Auto geht der rechte Blinker beim Benutzen doppelt so schnell,
> woran kann das liegen?
>
> A:
> Poste alle Karroserieteile und den Schaltplan des Kabelbaums...

Bessere Analogie:

Bei meinem Auto geht der rechte Blinker nicht, woran liegt das? Anbei 
ein Foto vom Rücksitz.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Arduino Fanboy D. schrieb:
> Die Annahme ist hier ja, dass der Bootloader das I Bit stehen lässt.
> Von da her, ist es evtl. schon sinnvoll, die Interrupts abzuschalten.

Sinnvoller wäre es, nicht das Symptom, sondern die Ursache zu bekämpfen,
also den Bootloader zu fixen.

von Einer K. (Gast)


Lesenswert?

Yalu X. schrieb:
> also den Bootloader zu fixen.
Durchaus...

Sieht aber nicht so aus, als hätte er/sie/es die Quellen vor sich 
liegen.

von Content B. (Firma: Da) (contentblocker_da)


Lesenswert?

Naja,

als ASM-Experte ignoriert man halt meinen Beitrag. Soll er doch schaun 
wie er zurecht kommt wärend Andere herumraten...

von rbx (Gast)


Lesenswert?

Fischpudding schrieb:
> Ich hab mir von Pollin ein paar der Microcontroller MEGA 2560PRO Boards
> bestellt und bin grad am Testen.

Aha, spannend..

Fischpudding schrieb:
> Ich programmiere in Assembler mit dem
> Microship Studio ehemals AVRStudio.

löblich.

Fischpudding schrieb:
> Nun ist es so, daß der Interrupt aufgerufen und abgearbeitet wird ohne
> das ich den globalen Interrupt freigegeben habe (SEI) den OCRA Int hab
> ich freigegeben.
> Irgend jemand eine Idee?

Automagie?
Du sagtest, du bist am Testen..

Hast du keinen Debugger?

von Stefan F. (Gast)


Lesenswert?

Ich bin erstaunt, dass einige sich an dem Bootloader fest gebissen 
haben. Man kann wohl davon ausgehen, dass es sich um den Arduino 
Bootloader handelt, mit dem die Mega2560 Board ausgeliefert werden.

Nach meinem Kenntnisstand übergibt er die Kontrolle an das Hauptprogramm 
mit gesperrten Interrupts, wie sich das gehört. Tatsächlich benutzt er 
selbst sogar keine Interrupts. Wer daran zweifelt möge bitte in den 
Quelltext schauen 
https://github.com/Optiboot/optiboot/tree/master/optiboot/bootloaders/optiboot

Deswegen bleibe ich dabei, dass unser Gast Fischpudding seinen gesamten 
Quelltext zeigen soll.

von Christoph db1uq K. (christoph_kessler)


Lesenswert?

Vielleicht läuft etwas im Stack Amok und zerstört das dorthin gerettete 
Flagregister? Ich schiebe das normalerweise einfach in eines der unteren 
16 Register, geht schneller und die unteren 16 sind sowieso nur halb 
benutzbar.

von (prx) A. K. (prx)


Lesenswert?

Das Flag-Register wird typischerweise im Interrupt gerettet. Wozu der 
erst einmal auftreten muss. Wozu das I-Flag schon gesetzt sein muss. ;-)

: Bearbeitet durch User
von Christoph db1uq K. (christoph_kessler)


Lesenswert?

So sieht das bei mir normalerweise aus, aber ich verwende auch keinen 
Bootloader:
1
.def  SavSrg  = r4    ; save status during Interrupt
2
...
3
; init stack
4
  ldi  Tmp,Low(RAMEND)
5
  out  SPL,Tmp  ;
6
  ldi  Tmp,High(RAMEND)
7
  out  SPH,Tmp  ;
8
...
9
Irq:         ; (4)   start IRQ = 4 clock cycles min.
10
  in  SavSrg,SREG  ; (1)   save status register
11
...
12
  out  SREG,SavSrg  ; (1)   restore status register
13
  reti      ; (4)

Beitrag #6733412 wurde von einem Moderator gelöscht.
Beitrag #6733414 wurde von einem Moderator gelöscht.
von Purzel H. (hacky)


Lesenswert?

Led_Status is eine Variable, und nicht die Spannung an der LED selbst ?

von Oliver S. (oliverso)


Lesenswert?

Christoph db1uq K. schrieb:
> ; init stack

Braucht es aber nur bei uralten AVR-Typen. Die neueren, auch der 
Mega2560, initialisieren den Stackpointer beim Reset.

Oliver

von Christoph db1uq K. (christoph_kessler)


Lesenswert?

Für den 2560 könnte es trotzdem interessant sein, wenn man externes SRAM 
benutzt
https://ww1.microchip.com/downloads/en/devicedoc/atmel-2549-8-bit-avr-microcontroller-atmega640-1280-1281-2560-2561_datasheet.pdf
Seite 27 "External Memory Interface"
aber der Assembler muss dazu wissen, wo "RAMEND" liegt, oder kann man 
das nur an das interne SRAM-Ende legen?

Der 6502 legte beim Interrupt-Aufruf immer auch das Flagregister auf den 
Stack.

von (prx) A. K. (prx)


Lesenswert?

Christoph db1uq K. schrieb:
> Der 6502 legte beim Interrupt-Aufruf immer auch das Flagregister auf den
> Stack.

Stack oder Schattenregister wird bei vielen CPU-Architekturen 
automatisch genutzt. AVR ist da eher exotisch.

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.