PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Interrupts global deaktivieren; wann?



cumi
28.11.2006, 16:51
Hallo Zusammen

Ich programmiere unter C auf einem AVR. Ich habe immer die Optimierung 2 eingeschaltet.
Nun wann muss ich genau die Interrupts kurz global deaktivieren?
Also im Datasheet von Atmel schreiben sie ja immer man solle sie deaktivieren, wenn man ein 16-Bit Register ausliesst. Also zB.:

cli();
word tmp=TCNT1;
sei();
Muss man die Interrupts auch deaktivieren, wenn man einfach mit words (das ist bei mir ein 16-Bit langer unsigned typ) rechne?
Also gibt es noch andere Fälle wie der schreibende oder lesende Zugriff auf ein 16-Bit-Reguster?

Vielen Dank für eure Hilfe!
Grüsse cumi

SprinterSB
28.11.2006, 17:10
In dem obigen Fall musst du dann deaktivieren, wenn in einer ISR irgendein Register veränderd wird, daß das TEMP-Register verwendet.

Für normale Variablen findest du mehr Infos im Wiki https://www.roboternetz.de/wissen/index.php/Fallstricke_bei_der_C-Programmierung#Nicht-atomarer_Code

cumi
28.11.2006, 17:20
Jetzt programmiere ich schon mehr als ein halbes Jahr für diese Controller und merke erst jetzt, dass mein Code die im Wiki beschriebenen Fehler drin hat.
Ich habe es jetzt bei einer sehr Interrupt-freudigen Applikation gemerkt.
Nun zum beheben. Am einfachsten ist es einfach all diese Stellen mit cli und sei vor IRQ zu schützen, oder?
Ich habe nun einen Algorithmus, welcher ca. 50 Zeilen lang ist und nur mit 16-Bit und 32-Bit Variabeln rechnet. Jetzt wie mache ich das am Besten? Daneben messe ich noch eine Frequenz am Analog-Comparator (bis ca. 6kHz) und generiere über den Timer noch ein Servo-Siganl etc. Ich sollte die Interrupts also nicht lange aufhalten. Jetzt wenn ich am Anfang vom Algorithmus cli mache und dann immer wieder einmal sei und gleich wieder cli (ohne etwas dazwischen) werden dann im Takt nachdem cli ausgeführt wurde die IRQ abgearbeitet, bevor schonwieder sei kommt?

PicNick
28.11.2006, 18:44
Du darfst nicht vergessen, daß du nur dort was schützen mußt, wo es auch Konflikte geben kann. D.h. mehr-byte felder, auf die sowohl der "normale" als auch der ISR-Code hingreift.
Also, wenn z.B. die ISR eine 32-Bit Zahl hochzählt und in der Hauptschleife rechnest du mit genau derselben Zahl.

Wenn dein Rechen-Algorithmus seine eigenen felder hat, brauchst du dort nix zu machen.

cumi
28.11.2006, 18:57
Ich hab jetzt gleich den Wiki-Artikel nochmals etwsa genauer gelesen und habe dies auch bemerkt. Ich war wohl etwas zu voreilig mit der Verurteilung meines Codes. Dann ist mein Code ja komplett in Ordnung :)
In diesem Fall liegt mein Problem irgendwo anders. Weitersuchen...

PicNick
28.11.2006, 19:03
.. Problem irgendwo anders
Jetzt könnt' ja einer kommen und fragen, worin sich dein Problem äußert ?

cumi
28.11.2006, 19:07
da hast du recht. Langsam bin ich soweit dass ich das ganze Problem mal formreif aufbereite. Das Problem lässt sich eben nicht auf zwei Zeilen schildern. Ich muss da schon den ganzen Quellcode posten.
Danke für deine Hilfe!

SprinterSB
29.11.2006, 08:31
[...] Jetzt wenn ich am Anfang vom Algorithmus cli mache und dann immer wieder einmal sei und gleich wieder cli (ohne etwas dazwischen) werden dann im Takt nachdem cli ausgeführt wurde die IRQ abgearbeitet, bevor schonwieder sei kommt?

Nein. Ein CLI sperrt unmittelbar die IRQs. Genaugenommen werden nicht die IRQs gesperrt, sondern daß die entsprechende ISR ausgeführt wird. Die entsprechenden IRQ-Flags bleiben gesetzt (bei flankengetriggerten IRQs), bis man sie von Hand löscht werden oder man ein SEI macht. In letzterem Fall wird die ISR dann entsprechend verzögert abgearbeitet.

Ein SEI unmittelbar gefolgt von einem CLI wird auch keine IRQ durchlassen, weil ein SEI nicht unmittelbar wirkt. Wenn man so etwas wie ein yield (anstehende IRQs abarbeiten) haben will, muss zwischen dem SEI und dem CLI also mindestens eine weitere Instruktion stehen.

Eine SEI-NOP-CLI-Sequenz wird also die Abarbeitung genau einer ISR erlauben -- nicht mehr, denn nach einer ISR wird immer eine Instruktion der Appliation abgearbeitet, und diese ist dann das CLI.