Forum: Mikrocontroller und Digitale Elektronik Interrupts und 16Bit Register


von Marco Oklitz (Gast)


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/int_ressourcen.html

 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 ?

von g457 (Gast)


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

von Marco Oklitz (Gast)


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

von Marco Oklitz (Gast)


Lesenswert?

ok vielleicht nicht grade jetzt !

ich geh jetzt auch nach draußen zum feiern  hehe

frohes neues

von Floh (Gast)


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?
:-)

von Marco Oklitz (Gast)


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

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.