Forum: Mikrocontroller und Digitale Elektronik STM32: Schlafen und Aufwachen


von Dosmo (Gast)


Lesenswert?

Hallo zusammen,

ich möchte auf dem STM32 folgendes machen:
Die Hauptschleife soll 1x pro ms ausgeführt werden. Nach Abarbeitung 
aller Prozesse soll die CPU bis zur nächsten ms schlafen gehen.
Dazu bringt Timer2 jede 1ms einen Interrupt, der die CPU aufwecken soll.

Ich hab es so implementiert (vereinfacht dargestellt):
1
volatile uint8_t aufwachen_u8;
2
main()
3
{
4
  InitTimer();
5
  NVIC_SystemLPConfig(NVIC_LP_SEVONPEND, DISABLE);
6
  while (1)
7
  {
8
    while (aufwachen_u8 == 0)
9
    {
10
      __WFE();
11
    }
12
    aufwachen_u8 = 0;
13
    Do_All_Work();
14
  }
15
}
16
17
void TIM2_IRQHandler()
18
{
19
  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
20
  __SEV();
21
  aufwachen_u8 = 1;
22
}

Scheint alles zu funktionieren, aber hab ich vielleicht etwas übersehen, 
bzw. gibt es noch eine Race-Condition o.ä., die man behandeln müßte?

von public (Gast)


Lesenswert?

Servus,

wo erwartest du denn eine Race-Condition? Gibt es hier nicht sogar das 
Commando "__WFI();"? Also wait for interrupt, da du dich davon ja 
aufwecken lässt?

Beste Grüße

von Dosmo (Gast)


Lesenswert?

Es kann ein Problem geben, wenn der aufweckende Interrupt ganz genau vor 
dem Sleep-Befehl kommt. Dann müßte man wachbleiben, kann aber nicht mehr 
verhindern, daß der Sleep ausgeführt wird, und man verpaßt einen Zyklus.

Beim AVR z.B. kann man das Problem verhindern, indem man die Interrupts 
global sperrt und erst mit dem Sleep-Befehl wieder freigibt. Dies 
funktioniert, weil der SEI() mit einem Takt Verzögerung arbeitet.
Beim PIC24 z.B. gibt es einen speziellen Befehl (DISI), der die 
Interrupts global sperrt und nach x Takten automatisch wieder freigibt.
Beim STM32 hab ich eine solchen Mechanismus noch nicht gefunden, daher 
WFE() statt WFI().

von public (Gast)


Lesenswert?

Mir ist folgendes bekannt:

1. __WFI(); weckt den Controller mittels Interrupt auf
2. der STM32 geht nicht in den Standby-Modus wenn noch ein Interrupt 
ansteht


Du musst also alle IRQ-Flags explizit löschen bzw. alle anstehenden IRQs 
abarbeiten bevor du in den Standby-Modus wechseln kannst.

Beste Grüße

von Erwecker (Gast)


Lesenswert?

Hallo

ich habe das Problem, dass ich zwar die __WFI(); Anweisung ausführen 
kann, aber der Controller aus diesem Modus nicht mehr aufwacht...

Eigentlich läuft im Hintergrund ein Timer der periodische Interrupts 
auslöst, jedoch scheint er nach Ausführung der WFI Anweisung nicht mehr 
zu laufen...
Was muss ich ändern, um den Controller nach einer WFI Anweisung wieder 
durch einen Timer erwecken zu können?

von Jim M. (turboj)


Lesenswert?

Erwecker schrieb:
> Was muss ich ändern,

Du muss vor allem Deine Probleme nicht unter fremde alte Threads 
schreiben, sondern einen neuen aufmachen. Bitte Source Code als Anhang 
(*.c) posten.

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.