mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Interrupts und 16Bit Register


Autor: Marco Oklitz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nabend !

Da die Benutzung von Interrupts beim programmieren vom avr in assembler 
(von c mal abgesehen, darin programmier ich nicht) einige Fallstricke 
bereit hält hab ich mal das Internet durchforstet um sicherzugehen das 
bei meinem programm auch alles klappt ! Und nicht solche blöden Fehler 
wie "tritt hin und wieder auf" vorkommenen.

Also meine Frage:

zu beginn der ISR schiebe ich die in der ISR benutzten register auf den 
stack !
das sind bei mir z.B. r16,r17 das statusregister und das Doppelregister 
zl und zh.
am ende der ISR hole ich sie wieder vom stapel.

ich dachte damit wäre alles safe !
doch dann hab ich das gefunden:

---Quote anfang

http://www.avr-asm-tutorial.net/avr_de/interrupts/...

 Die oben beschriebene Zugriffssteuerung über eine Interrupt-Blockage 
mit  CLI/SEI ist auf jeden Fall dann zwingend, wenn ein Doppelregister 
außerhalb von Interrupt-Service-Routinen auf einen neuen Wert gesetzt 
werden muss und innerhalb von Service-Routinen verwendet wird. Zwischen 
dem Setzen des einen Bytes des Doppelregisters und des zweiten könnte 
ein Interrupt zuschlagen und einen völlig verqueren Wert vorfinden. 
Solche Fehler sind teuflisch, weil es in der Regel korrekt funktioniert 
und nur alle paar Stunden ein Mal dieser Fall eintritt. So einen 
eingebauten Bug findet man garantiert nicht, weil er sich so selten in 
freier Wildbahn in der Schaltung zeigt.

Daher sollten folgende Regeln gelten:

    * Register möglichst klar der alleinigen Verwendung innerhalb und 
außerhalb von Interrupt-Service-Routinen zuordnen.
    * Jede gemeinsame Nutzung von Registern intensiv auf mögliche 
Konflikte hin durchdenken. Vorher denken vermeidet die Fehlersuche 
hinterher.
    * Vorsicht bei der gemeinsamen Nutzung von Doppelregistern. 
Interrupts blockieren! Und hinterher nicht vergessen, sie wieder 
zuzulassen.

---Quote ende

Heißt das ich muß die Interrupts beim Benutzen von Doppelregistern 
trotzdem deaktivieren ? obwohl ich sie am anfang der ISR auf den stack 
packe?

Hauptprogramm:
ldi     zl,LOW(UART_RX_STRING)
ldi     zh,HIGH(UART_RX_STRING)

wo ist das problem wenn nach dem laden von zl der Interrupt ausgelöst 
wird, Z sichert, dann verändert, wiederherstellt und dann im 
hauptprogramm zh geladen wird ?

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> wo ist das problem wenn nach dem laden von zl der Interrupt ausgelöst
> wird, Z sichert, dann verändert, wiederherstellt und dann im
> hauptprogramm zh geladen wird ?

Streiche 'wiederherstellt', dann erkennst Du das mögliche Problem. 
Alternativ streiche 'sichert, dann verändert, wiederherstellt' und 
setzte stattdessen 'verwendet', dann tritt das selbe Problem (in die 
andere Richtung) auf.

HTH

Autor: Marco Oklitz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ist mir nicht klar sorry :-(

ich meine ich hab auch kein problem damit die interrupts einfach zu 
sperren !
ich wills doch einfach nur verstehen ! :-))

bei manchen 16bit registern versteh ichs ja weil sich der 16bit inhalt 
verändern kann und dann low und high byte nicht mehr zusammenpassen.
Aber in meinem beispiel verändert sich doch die adresse im sram von 
(UART_RX_STRING) durch den interrupt nicht.
zl wurde vor dem IRQ erfolgreich geladen, über die ISR hinweg gesichert 
per stack. und zh wird nach dem irq geladen. das sollte doch gehen.
wie gesagt ich verstehs halt net.

ich kanns auch einfach als Tatsache hinnehmen, ich meine im datenblatt 
steht ja auch nur:


It is important to notice that accessing 16-bit registers are atomic 
operations. If an interrupt
occurs between the two instructions accessing the 16-bit register, and 
the interrupt code
updates the temporary register by accessing the same or any other of the 
16-bit Timer Registers,
then the result of the access outside the interrupt will be corrupted. 
Therefore, when both
the main code and the interrupt code update the temporary register, the 
main code must disable
the interrupts during the 16-bit access.

vielleicht findet sich ja ein geduldiger Mensch der mich aufklärt ^^

gruß marco

Autor: Marco Oklitz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok vielleicht nicht grade jetzt !

ich geh jetzt auch nach draußen zum feiern  hehe

frohes neues

Autor: Floh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marco Oklitz schrieb:
> wo ist das problem wenn nach dem laden von zl der Interrupt ausgelöst
> wird, Z sichert, dann verändert, wiederherstellt und dann im
> hauptprogramm zh geladen wird ?

Da gibts keine Probleme.
Diese Probleme mit 16bit-Zugriffe entstehen, wenn du auf ein nicht 
sicherbares "Ding" zugreifst, also z.B. eine Speicheradresse oder ein 
I/O-Register.
So als Fallbeispiel:

Du hast eine 16 bit Variable im SRAM, die die Overflows eines Timers 
mitzählt (meinetwegen für ne Uhrzeit).
Dann läuft das ganze im Worst case so ab:

Im Low Byte steht 0xFF im High Byte 0x04

ld r2, lowbyte
 ;<- hier kommt der interrupt
ld r3, highbyte

im Interrupt nach dem Sichern
  ld r16, lowbyte
  ld r17, highbyte
  inc r16
  brne kein_high_inc
  inc r17
kein_high_inc:
  st lowbyte, r16
  st highbyte, r17
Interrupt ende, die REgister werden wieder hergestellt, nicht aber die 
SRAM-Variablen.

Im Hauptprogramm steht dann wegen des Interrupts in
r2 = 0xFF und r3 = 0x05
obwohl es eigentlich 0x00 und 0x05 sein sollten.

Problematik klar?
:-)

Autor: Marco Oklitz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dein beispiel ist vollkommen einleuchtend

also besteht das problem doch nur dann, wenn ich das was ich ich ein 
register im hauptprogramm laden will sich während des interrupts ändern 
könnte oder ändern kann.und nicht durch den stack gesafet werden kann.
damit kann ich umgehen, das ist einleuchtend.
ich dachte das wäre sowas wie ein grundlegendes problem das das high und 
low byte immer direkt hintereinander geladen werden muß, weil es sonst 
zu prozessorinternen problemen führt. das es probleme gibt wenn ich die 
werte ändere ist klar.

danke dir

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.