hallo, es geht um den sleep modus auf einem meiner mikrokontroller (sleep=keine CPU Taktung). meine interrupts muessen sehr kurz sein. deshalb setze ich in meinen interruptroutinen nur ein flag, dass etwas gemacht werden muss. die eigentliche arbeit wird dann in der main gemacht, die ja durch die interrupts geweckt wird void main(){ while(1){ if(TueEtwasFlag1){ TueEtwasFlag1=0; TueEtwas1(); } if(TueEtwasFlag2){ TueEtwasFlag2=0; TueEtwas2(); } if(kein Flag gesetzt){ // <------------------- problemzeitpunkt sleep(); } } } mein problem ist nun, dass diese Flags irgendwann gesetzt werden können. mal kommen diese sehr oft und mal sehr selten. wenn nun ein flag gesetzt wird, während des "problemzeitpunkts" geht mein kontroller schlafen, obwohl noch was zu tun ist. wie kann ich dafuer sorgen, dass der kontroller nur schlafen geht, wenn auch wirklich keine arbeit mehr anliegt???? danke schonmal fuers lesen moklok
@ Can Cobe (moklok) >wie kann ich dafuer sorgen, dass der kontroller nur schlafen geht, wenn >auch wirklich keine arbeit mehr anliegt???? Das muss deine State Machine in der Hauptschleife machen. Siehe [[Sleep Mode]] und Statemachine MFG Falk
>wie kann ich dafuer sorgen, dass der kontroller nur schlafen geht, wenn >auch wirklich keine arbeit mehr anliegt???? Wichtig ist, erst mal zu erkennen, dass keine Arbeit mehr anliegt. Kannst du das? Welche Art von Arbeit (Interrupts) ist das?
Can Cobe schrieb: > wie kann ich dafuer sorgen, dass der kontroller nur schlafen geht, wenn > auch wirklich keine arbeit mehr anliegt???? Einfach Interrupt sperren:
1 | cli(); |
2 | if(kein Flag gesetzt){ |
3 | // <------------------- kein problemzeitpunkt
|
4 | sei(); |
5 | sleep(); |
6 | }
|
7 | sei(); |
Peter
1 | cli(); |
2 | if(kein Flag gesetzt){ |
3 | // <------------------- kein problemzeitpunkt
|
4 | sei(); |
5 | // <------------------- jetzt ist hier problemzeitpunkt
|
6 | sleep(); |
7 | }
|
8 | sei(); |
Peter schrieb: >
1 | > cli(); |
2 | > if(kein Flag gesetzt){ |
3 | > // <------------------- kein problemzeitpunkt |
4 | > sei(); |
5 | > // <------------------- jetzt ist hier problemzeitpunkt |
6 | > sleep(); |
7 | > } |
8 | > sei(); |
9 | >
|
Nein, denn nach SEI wird garantiert noch der folgende Befehl ausgeführt, also das SLEEP, ehe in einen Interrupt gesprungen werden kann. Peter
AVR libc doku:
1 | As the \c sleep_mode() macro might cause race conditions in some |
2 | situations, the individual steps of manipulating the sleep enable |
3 | (SE) bit, and actually issuing the \c SLEEP instruction, are provided |
4 | in the macros \c sleep_enable(), \c sleep_disable(), and |
5 | \c sleep_cpu(). This also allows for test-and-sleep scenarios that |
6 | take care of not missing the interrupt that will awake the device |
7 | from sleep. |
8 | |
9 | Example: |
10 | \code |
11 | #include <avr/interrupt.h> |
12 | #include <avr/sleep.h> |
13 | |
14 | ... |
15 | set_sleep_mode(<mode>); |
16 | cli(); |
17 | if (some_condition) |
18 | { |
19 | sleep_enable(); |
20 | sei(); |
21 | sleep_cpu(); |
22 | sleep_disable(); |
23 | } |
24 | sei(); |
25 | \endcode |
26 | |
27 | This sequence ensures an atomic test of \c some_condition with |
28 | interrupts being disabled. If the condition is met, sleep mode |
29 | will be prepared, and the \c SLEEP instruction will be scheduled |
30 | immediately after an \c SEI instruction. As the intruction right |
31 | after the \c SEI is guaranteed to be executed before an interrupt |
32 | could trigger, it is sure the device will really be put to sleep. |
AVR Instruction Set: "SEI – Set Global Interrupt Flag Description: Sets the Global Interrupt Flag (I) in SREG (Status Register). The instruction following SEI will be executed before any pending interrupts." Peter
haha, danke!!! das mit dem "executed before any pending interrupt" wusste ich noch nicht und erleichtert die aufgabe immens...
Und ich ärgere mich gerade über die AVR Datenblätter (ATmega128RFA1, ATmega1281)... Da steht alles mögliche über die sleep modes, aber nirgends, dass man nach dem setzen der ganzen Register noch den Assembler Befehl "sleep" braucht!
X- Rocka schrieb: > Da steht alles mögliche über die sleep modes, aber > nirgends, dass man nach dem setzen der ganzen Register noch den > Assembler Befehl "sleep" braucht naja, aber durch mitdenken fragt man sich ja ab wann der Prozessor nun wirklich schläft oder nicht?
Peter schrieb: > X- Rocka schrieb: >> Da steht alles mögliche über die sleep modes, aber >> nirgends, dass man nach dem setzen der ganzen Register noch den >> Assembler Befehl "sleep" braucht > > naja, aber durch mitdenken fragt man sich ja ab wann der Prozessor nun > wirklich schläft oder nicht? Hast ja recht, bin ja auch irgendwann drauf gekommen, dass nur Register setzen es nicht sein kann. Aber auch erst, als ich mir das Datenblatt samt Instruction Set des ATmega1281 angesehen habe. Spiele nämlich gerade wieder mit dem RFA1 rum, und da haben die nicht das Instruction Set reingepackt.
X- Rocka schrieb: > Da steht alles mögliche über die sleep modes, aber > nirgends, dass man nach dem setzen der ganzen Register noch den > Assembler Befehl "sleep" braucht! ATmega1281 Datenblatt S.56: "• Bit 1 – SE: Sleep Enable The SE bit must be written to logic one to make the MCU enter the sleep mode when the SLEEP instruction is executed." Also ich finde das eindeutig. Wenn ich eine Funktionseinheit im AVR programmiere, gehe ich immer in die dafür zuständige "Register Description" und klappere die ab. Dann läuft auch fast alles auf Anhieb. Peter
Peter Dannegger schrieb: > Also ich finde das eindeutig. Ja, ist es. Zu viel zu schnell gewollt und nicht gründlich genug gelesen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.