Forum: Projekte & Code Cortex M3 (STM32F103) Stop Mode - Wake Up über RTC


von Chris J. (Gast)


Lesenswert?

Hallo,

da es fast nichts Brauchbares zu dem Thema gibt und es mich einen ganzen 
Tag gekostet hat heraus zu finden, wie es nun wirklich funktioniert 
schreibe ich es mal für die Suchmaschinen hier rein. Da diese Modes sich 
über SWD mit ST-Link nicht debuggen lassen umso schwieriger zu wissen, 
ob es wirklich funktioniert.

Hardware: Bluepill Board mit StdPeriph Library

Der F103 hat 3 Modi: Sleep (+Options), STOP (+Options), Standby 
(+Options), wobei Sleep der einfachste Mode ist, nur der Core bleibt 
stehen, alles andere bleibt an.

Achtung: Stop Mode und Standby Mode, aber auch Sleep schießen die swd 
Schnittstelle ab! Danach ist kein Zugriff mehr auf den Chip möglich! Er 
muss dann durch Umjumpern auf Boot-Mode mit dem Tool ST Utility gelöscht 
werden! Debuggen funktioniert nur begrenzt, da der Debugger auf den Takt 
des Core angewiesen ist.

Beim Aufwecken aus dem Standby Mode startet der Chip komplett neu, es 
wird ein Reset ausgelöst. Dieser Fall wird hier nicht betrachtet.

Um den STM32F103 periodisch über die RTC aufzuwecken ist die Aktivierung 
des RTC Alarms notwendig. Der "normale" Sekunden Interrupt vermag dieses 
nicht.
1
   /* ------------------------------------ */
2
   /* ----- Alarm Interrupt setzen ------- */
3
   /* ------------------------------------ */
4
5
   PWR_BackupAccessCmd(DISABLE);
6
7
   /* RTC Alarm über EXTI17 Kanal an NVIC melden */
8
   EXTI_InitTypeDef EXTI_InitStruct;
9
   EXTI_InitStruct.EXTI_Line    = EXTI_Line17;
10
   EXTI_InitStruct.EXTI_LineCmd = ENABLE;                          /* Enable interrupt */
11
   EXTI_InitStruct.EXTI_Mode    = EXTI_Mode_Interrupt;             /* Interrupt mode */
12
   EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;             /* Trigger auf steigende Flanke */
13
   EXTI_Init(&EXTI_InitStruct);                                    /* Aktivieren und zu EXTI hinzufügen */
14
15
   /* EXTI17 an NVIC koppeln */
16
   NVIC_InitStructure.NVIC_IRQChannel       = RTCAlarm_IRQn;
17
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 13;
18
   NVIC_InitStructure.NVIC_IRQChannelCmd    = ENABLE;
19
   NVIC_Init(&NVIC_InitStructure);
20
21
   /* Alarmperiode setzen */
22
   PWR_BackupAccessCmd(ENABLE);
23
   RTC_WaitForLastTask();
24
   uint32_t cnt = RTC_GetCounter();
25
   RTC_WaitForLastTask();
26
   RTC_SetAlarm(cnt + SLEEPTIME);
27
   RTC_WaitForLastTask();
28
29
   /* Int zulassen */
30
   RTC_ITConfig(RTC_IT_ALR, ENABLE);
31
   NVIC_EnableIRQ(RTCAlarm_IRQn);
32
33
   PWR_BackupAccessCmd(DISABLE);

Für die Auslösung des Alarms ist es normalerweise nicht notwendig einen 
EXTI zu definieren. Die RTC Interrrupts werden in einer Routine 
gesammelt und dort durch ihre Auslöse Bits unterschieden. Da reicht 
jedoch nicht aus, um den STOP Mode oder Sleep Mode wieder zu verlassen! 
Dafür gibt es den EXTI 17, der speziell für diesen Zweck gemacht wurde. 
Er bindet intern den "INT Pin" der RTC an den NVIC an und löst damit 
einen Interrupt aus, der dem eines Pins gleicht.

Durch die Aktivierung des EXTI_17 Kanals wird bei einem Alarm NICHT mehr 
der normale RTC Handler RTC_IRQHandler(void) angesprungen, sondern void 
RTCAlarm_IRQHandler ().

Der neue Alarmhandler setzt die Alarmzeit auf eine Zeit in der Zukunft, 
löscht die IRQ Flags und wird wieder verlassen.
1
void RTCAlarm_IRQHandler ()
2
{
3
  static _Bool led_switch = false;
4
5
  if (RTC_GetITStatus(RTC_IT_ALR) != RESET)
6
  {
7
     PWR_BackupAccessCmd(ENABLE);
8
 
9
    RTC_WaitForSynchro();
10
     RTC_WaitForLastTask();
11
     uint32_t val = RTC_GetCounter();
12
     RTC_WaitForLastTask();
13
     RTC_SetAlarm(val + SLEEPTIME);
14
     RTC_WaitForLastTask();
15
     RTC_ClearITPendingBit(RTC_IT_ALR);
16
     PWR_BackupAccessCmd(DISABLE);
17
 
18
    EXTI_ClearITPendingBit(EXTI_Line17);   // Remove LINE interrupt flag bit
19
  }
20
21
}

Ob der letzte Befehl nötig ist das EXTI IRQ Flag zu löschen weiss ich 
nicht sicher, es geht mit und ohne. RTC_WaitForLastTask() muss zwingend 
zwischen jeden Befehl, lässt man es weg klappt es nicht mehr.

Die Sequenz um die CPU in den Stop Mode zu schicken sieht so aus
1
        /* Wichtig! Löschen der Pending IRQ Flags */
2
        EXTI->PR = 0xFFFFFFFF;
3
        PWR_ClearFlag(PWR_FLAG_WU);
4
        /* Schlafen legen */
5
        PWR_EnterSTOPMode(PWR_Regulator_ON,PWR_STOPEntry_WFI);
6
        SystemInit();

Nach Ausführung von 
PWR_EnterSTOPMode(PWR_Regulator_ON,PWR_STOPEntry_WFI) ist die CPU "weg" 
und wacht erst wieder auf, wenn der RTC Alarm ausgelöst wird. IN diesem 
Fall wird sofort hinterher die ISR Routine aufgerufen und ausgeführt.

Achtung! Nach dem Stop stimmt die Taktfrequenz nicht mehr, da PLL und 
Teiler zurückgesetzt wurden! Es muss zwingend der SystemInit aufgerufen 
werden, der das System neu einstellt.

Die Sequenz um den SLEEP Mode einzuleiten, der in den StdPeriphLibs 
nicht extra erwähnt wird lautet
1
        SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; /* Enable deepsleep */
2
        SetRedLED(ENABLE);
3
        __WFI(); /* Enter sleep mode */

In diesem Fall entfällt der Aufruf von InitSystem, da nur der Core 
angehalten wird.

Gruss,
Christian

von noreply@noreply.com (Gast)


Angehängte Dateien:

Lesenswert?

Ich hänge nochmal die Doku dazu. Quelle: Quelle: en.CD00171190.pdf, 
Table 11 on site 71

Ich würde mir auch noch überlegen, ob im Stop-Mode die Initialisierung 
der Takte über SystemInit() nicht in void RTCAlarm_IRQHandler () besser 
aufgehoben ist. Man hat ja Flags über die Vorgeschichte.

von Dr. Sommer (Gast)


Lesenswert?

Chris J. schrieb:
> Achtung: Stop Mode und Standby Mode, aber auch Sleep schießen die swd
> Schnittstelle ab!

Ich verwende in nahezu jedem Programm den Sleep Modus (einfach nur 
Aufruf von __WFI()) und konnte bisher immer noch problemlos weiter über 
SWD oder JTAG debuggen (bei F103, F407, F373, F302, ...). Lediglich der 
Aufbau einer neuen Verbindung funktioniert mit dem ST-Link nicht 
(Aktivieren der Option "Connect under Reset" soll helfen), beim J-Link 
aber schon (es wird aber der Controller ganz resettet). Musste noch nie 
was umjumpern.

von Chris J. (Gast)


Lesenswert?

Dr. Sommer schrieb:

> Ich verwende in nahezu jedem Programm den Sleep Modus (einfach nur
> Aufruf von __WFI()) und konnte bisher immer noch problemlos weiter über
> SWD oder JTAG debuggen

Da würde ich aber mal untersuchen, ob er wirklich im Sleep etc bleibt 
und nicht direkt wieder raus kommt, denn aus dem normalen Sleep holt ihn 
jeder Systick, jeder Timer, jedes Event wieder raus.... da reicht es 
wenn gewisse Flags (EXTI->PR = 0xFFFFFFFF;) vorher nicht ausdrücklich 
gelöscht wurden, dann überrennt er den WFI oder WFE einfach.

Der nach den englischen ARM Doku Seiten richtige Aufruf für direktes 
Schlafen ist

SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;  /* Enable deepsleep */
    __WFI();                        /* Enter sleep mode */

Und die swd ist nicht ansprechbar, wenn man nicht eine Warteschleife 
einbaut, die nach dem Reset für die nötige Zeit zum Connect sorgt. Ich 
habe da alles durch, jede Möglichkeit etc.

von Dr. Sommer (Gast)


Lesenswert?

Chris J. schrieb:
> Da würde ich aber mal untersuchen, ob er wirklich im Sleep etc bleibt
Ja, tut er. Sieht man an der Leistungsaufnahme und z.B. im Segger 
SystemView Tool.

Chris J. schrieb:
> denn aus dem normalen Sleep holt ihn
> jeder Systick, jeder Timer, jedes Event wieder raus....
Korrekt, das ist ja der Sinn der Sache! Da man __WFI() ja in einer 
Schleife aufruft geht er danach direkt wieder schlafen.

Chris J. schrieb:
> da reicht es
> wenn gewisse Flags vorher nicht ausdrücklich gelöscht wurden, dann
> überrennt er den WFI einfach.
Logisch. Da muss man aufpassen.

Chris J. schrieb:
> Und die swd ist nicht ansprechbar, wenn man nicht eine Warteschleife
> einbaut, die nach dem Reset für die nötige Zeit zum Connect sorgt.
Richtig. Aber wenn die SWD-Verbindung erst einmal steht, kann man 
problemlos weiter debuggen auch wenn zwischendurch __WFI() kommt. Und 
wie gesagt, vernünftige™ Debugger haben auch kein Problem wenn __WFI() 
sofort nach dem Start aufgerufen wird, weil sie das Timing vom Reset 
selbst besorgen ;-)

von Chris J. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Ja, tut er. Sieht man an der Leistungsaufnahme und z.B. im Segger
> SystemView Tool.

Das Bluepill Board kriegt man von 55mA runter auf ca 15, tiefer leider 
nicht. Da hängt ja noch mehr drauf, zb ein 3V Regler usw. Reicht mir 
aber auch.

Dr. Sommer schrieb:
> Korrekt, das ist ja der Sinn der Sache! Da man __WFI() ja in einer
> Schleife aufruft geht er danach direkt wieder schlafen.

Und die Takte alle wieder richtig eingestellt danach? Ich kann Dir 
Screensshots schicken, von RCCGetClocks..... danach ist alles verstellt.

Das funzt zumnindest, wahlweise sleep oder stop.
1
void MakeCPUSleep() {
2
3
#define SLEEP MODE
4
5
    RCC_ClocksTypeDef RCC_Clocks;
6
    SYSTICK_ISR_OFF;                     /* Systick aus */
7
8
#ifdef SLEEP_MODE
9
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;  /* Enable deepsleep */
10
    __WFI();                            /* Enter sleep mode */
11
#else
12
    EXTI->PR = 0xFFFFFFFF;
13
    PWR_ClearFlag(PWR_FLAG_WU);
14
    PWR_EnterSTOPMode(PWR_Regulator_ON,PWR_STOPEntry_WFI);
15
#endif
16
17
    SystemInit();
18
    RCC_HCLKConfig(RCC_SYSCLK_Div1);                     // AHB Clock auf Maximum 64 Mhz
19
    RCC_PCLK1Config(RCC_HCLK_Div2);                      // APB1 Clock auf 32Mhz (32 Mhz ist Maximum)
20
    RCC_PCLK2Config(RCC_HCLK_Div2);                      // APB2 Clock auf 32Mhz
21
22
    SYSTICK_ISR_ON;                                      // Systick ein
23
    RCC_GetClocksFreq(&RCC_Clocks);                      // Clocks holen
24
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);     // Quartz als Cloc k Basis
25
    SysTick_Config(RCC_Clocks.SYSCLK_Frequency/1000);    // Systick für 1ms
26
}

von Dr. Sommer (Gast)


Lesenswert?

Chris J. schrieb:
> SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;  /* Enable deepsleep */
>     __WFI();                        /* Enter sleep mode */
Moment, das löst beim STM32 den Stop/Standby-Modus aus. Ich rede vom 
ordinären Sleep-Modus, ganz oben in der Tabelle die von 
noreply@noreply.com gepostet wurde.

Chris J. schrieb:
> Und die Takte alle wieder richtig eingestellt danach? Ich kann Dir
> Screensshots schicken, von RCCGetClocks..... danach ist alles verstellt.
Das ist dann nicht mehr der normale Sleep-Modus.

von Chris J. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Moment, das löst beim STM32 den Stop/Standby-Modus aus. Ich rede vom
> ordinären Sleep-Modus, ganz oben in der Tabelle die von
> noreply@noreply.com gepostet wurde.

Guckst Du hier:
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0321a/BIHBGGHF.html

hier steht es anders:
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/BABHHGEB.html

Ich lasse mich aber auch gern noch belehren.....

>>Das ist dann nicht mehr der normale Sleep-Modus.

Nein? Argh.... wo sind meine Herztabletten? :-(

Code des STOPs in der Lib, für Stop werden noch weitere register gesetzt
1
void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)
2
{
3
  uint32_t tmpreg = 0;
4
  /* Check the parameters */
5
  assert_param(IS_PWR_REGULATOR(PWR_Regulator));
6
  assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry));
7
8
  /* Select the regulator state in STOP mode ---------------------------------*/
9
  tmpreg = PWR->CR;
10
  /* Clear PDDS and LPDS bits */
11
  tmpreg &= CR_DS_MASK;
12
  /* Set LPDS bit according to PWR_Regulator value */
13
  tmpreg |= PWR_Regulator;
14
  /* Store the new value */
15
  PWR->CR = tmpreg;
16
  /* Set SLEEPDEEP bit of Cortex System Control Register */
17
  SCB->SCR |= SCB_SCR_SLEEPDEEP;
18
19
  /* Select STOP mode entry --------------------------------------------------*/
20
  if(PWR_STOPEntry == PWR_STOPEntry_WFI)
21
  {
22
    /* Request Wait For Interrupt */
23
    __WFI();
24
  }
25
  else
26
  {
27
    /* Request Wait For Event */
28
    __WFE();
29
  }
30
31
  /* Reset SLEEPDEEP bit of Cortex System Control Register */
32
  SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
33
}

von Chris J. (Gast)


Lesenswert?

Ah.... ok. Ist schon Sleep aber zusätzlich noch ohne Takt und PLL, Flash 
etc

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/CHDJJHJI.html

daher auch meine Taktsorgen danach...

von Dr. Sommer (Gast)


Lesenswert?

Also, ich habs jetzt nochmal richtig ausprobiert mit diesem Programm für 
den STM32F103RB auf dem STM32-Olimexino.
1
#include <stm32f1xx.h>
2
3
void TIM2_IRQHandler (void) {
4
  if (TIM2->SR & TIM_SR_UIF) {
5
    // Timer-Interrupt zurücksetzen
6
    TIM2->SR = ~TIM_SR_UIF;
7
8
    // Pin toggeln
9
    uint32_t msk = GPIOA->ODR & (1 << 5);
10
    GPIOA->BSRR = (msk << 16) | (~msk);
11
  }
12
}
13
14
int main (void) {
15
  __disable_irq ();
16
17
  // Systemtakt auf 72MHz und Flash Prescaler konfigurieren
18
  FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY_1;
19
  RCC->CR = RCC_CR_HSEON | (16 << RCC_CR_HSITRIM_Pos) | RCC_CR_HSION;
20
  while ((RCC->CR & RCC_CR_HSERDY) == 0) __NOP ();
21
  RCC->CFGR = (7 << RCC_CFGR_PLLMULL_Pos) | RCC_CFGR_PLLSRC | (4 << RCC_CFGR_PPRE1_Pos);
22
  RCC->CR = RCC_CR_HSEON | (16 << RCC_CR_HSITRIM_Pos) | RCC_CR_HSION | RCC_CR_PLLON;
23
  while ((RCC->CR & RCC_CR_PLLRDY) == 0) __NOP ();
24
  RCC->CFGR = (7 << RCC_CFGR_PLLMULL_Pos) | RCC_CFGR_PLLSRC | (4 << RCC_CFGR_PPRE1_Pos) | RCC_CFGR_SW_1;
25
  while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_1) __NOP ();
26
  RCC->CR = RCC_CR_HSEON | (16 << RCC_CR_HSITRIM_Pos) | RCC_CR_PLLON;
27
28
  // Peripherietakte einschalten
29
  RCC->APB2ENR = RCC_APB2ENR_IOPAEN;
30
  RCC->APB1ENR = RCC_APB1ENR_TIM2EN;
31
32
  // Interrupt einschalten
33
  NVIC->ISER [TIM2_IRQn >> 5UL] = 1UL << TIM2_IRQn;
34
35
  // PA5 auf Output setzen
36
  GPIOA->CRL = 0x44144444;
37
38
  // Timer auf 0,2 Hz stellen
39
  TIM2->PSC = 35999;
40
  TIM2->ARR = 9999;
41
  TIM2->DIER = TIM_DIER_UIE;
42
  TIM2->EGR = TIM_EGR_UG;
43
  TIM2->CR1 = TIM_CR1_CEN;
44
45
  // Interrupts einschalten
46
  __enable_irq ();
47
48
  while (1) {
49
    // Schlafmodus aktivieren
50
    __WFI ();
51
  }
52
}
Das Programm lässt die LED an PA5 mit 0.1Hz blinken. Ob man die 
__WFI-Zeile auskommentiert oder nicht ändert nichts am Verhalten des 
Programms oder an der Debugbarkeit. Der einzige feststellbare 
Unterschied besteht darin, dass der Stromverbrauch unterschiedlich ist: 
Mit WFI 16mA, ohne 28mA.
Zu beachten ist dass hierbei der Quarzoszillator anbleibt und munter 
Strom frisst - nur mit HSI ginge es bis auf 8mA runter.
Das zeigt dass der ganz normale Sleep-Modus mit __WFI() unproblematisch 
ist. Das sieht bei den anderen Sleep-Modi natürlich anders aus.

von Dr. Sommer (Gast)


Lesenswert?

Dr. Sommer schrieb:
> nur mit HSI ginge es bis auf 8mA runter.
Achja, ich meinte mit HSI und ohne PLL, d.h. der ganze Controller läuft 
bei 8MHz.

von noreply@noreply.com (Gast)


Lesenswert?

Chris J. schrieb:
>>>Das ist dann nicht mehr der normale Sleep-Modus.
>
> Nein? Argh.... wo sind meine Herztabletten? :-(

Das SLEEPDEEP-Bit ist notwendige Voraussetzung für Stop bzw. 
Standby-Mode. Stop und Standby-Mode unterscheiden sich dann noch in 
weiteren gesetzten Bit's. Siehe meine Tabelle oben.

von noreply@noreply.com (Gast)


Lesenswert?

Chris J. schrieb:
> Und die Takte alle wieder richtig eingestellt danach? Ich kann Dir
> Screensshots schicken, von RCCGetClocks..... danach ist alles verstellt.

Es gibt noch einen System-Reset, der durch einen "Low-power management 
reset" (Quelle: en.CD00171190.pdf, Kapitel 7) ausgelöst wird. Das könnte 
die notwendige Neukonfiguration der Takte erklären.

Man kann hier mal nachschauen.

"The reset source can be identified by checking the reset flags in the 
Control/Status register,
RCC_CSR (see Section 7.3.10: Control/status register (RCC_CSR))."

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Wenn ihr den Tiefschlaf wollt, dann müsst ihr dafür sorgen, dass dem SWD 
nicht sein Takt geraubt wird.
-> DBGMCU_CR Register bespaßen

The core does not allow FCLK or HCLK to be turned off during a debug 
session. As these
are required for the debugger connection, during a debug, they must 
remain active. The
MCU integrates special means to allow the user to debug software in 
low-power modes.
For this, the debugger host must first set some debug configuration 
registers to change the
low-power mode behavior:
• In Sleep mode, DBG_SLEEP bit of DBGMCU_CR register must be previously 
set by
the debugger. This will feed HCLK with the same clock that is provided 
to FCLK
(system clock previously configured by the software).
• In Stop mode, the bit DBG_STOP must be previously set by the debugger. 
This will
enable the internal RC oscillator clock to feed FCLK and HCLK in STOP 
mode.

von Chris J. (Gast)


Lesenswert?

Nochmal für nen alten Mann zu Mitschreiben:

Wenn ich nur den leichten Schlaf möchte, weil mir das reicht muss ich 
nur WFI setzen, dann holt mir jeder Int, zb an meinem Funk RF Pin oder 
der 1s INT der RTC die CPU zurück ins Leben?

In der Hauptschleife habe ich nur die Statemachine laufen und unten WFI, 
mehr nicht. Da rennt er dann immer wieder rein. Wegen der Funkdaten 
brauche ich ein recht fixes Aufwachen, sonst läuft mir der Fifo voll 
ohne dass er bedient wird.

von Dr. Sommer (Gast)


Lesenswert?

Chris J. schrieb:
> Wenn ich nur den leichten Schlaf möchte, weil mir das reicht muss ich
> nur WFI setzen, dann holt mir jeder Int, zb an meinem Funk RF Pin oder
> der 1s INT der RTC die CPU zurück ins Leben?

Ja genau. Wobei die RTC- und Externen- Interrupts halt schon speziell 
sind, weil sie auch in den tieferen Schlafmodi gehen. Im normalen 
"Sleep"-Modus, der durch Einfaches Aufrufen von __WFI() gestartet wird, 
weckt jeder Interrupt sofort auf. Das siehst du auch in meinem Beispiel 
- da ist es ein Timer-Interrupt. Ich würde normalerweise auch eher einen 
Timer für sowas nehmen als die RTC, der ist flexibler.

Chris J. schrieb:
> In der Hauptschleife habe ich nur die Statemachine laufen und unten WFI,
> mehr nicht.
Du kannst in die Hauptschleife auch ein while(1) __WFI(); packen, und 
die Statemachines in Interrupts. So kannst du alle Warte-Schleifen 
vermeiden und den Prozessor so viel wie möglich schlafen lassen.
Das ist sowieso die Grundidee von WFI - auf Ereignisse (Interrupts) 
warten, ohne den Prozessor sinnlos im Kreis drehen zu lassen 
(Warteschleifen). Da der Prozessor hier auch keine Zeit zum Aufwecken 
braucht (Oszillator bleibt an), ergibt sich keinerlei Nachteil gegenüber 
Warteschleifen.

von noreply@noreply.com (Gast)


Lesenswert?

Ist ungefähr so, aber ich bin nur Theoretiker. ;-)

Noch zum Stromverbrauch:
- Ich würde es erstmal wie Dr. Sommer machen. HSI ohne PLL verwenden und 
versuchen mit 8 MHz Taktfrequenz für HCLK auskommen.
- Danach würde ich versuchen, den HCLK mit dem Vorteiler noch weiter 
runterzubekommen.
- Danach würde ich versuchen HCLK situativ anzupassen.
- Die Kür wäre dann Stop-Mode, wobei der Prozessor mit diversen EXTI 
wieder zum Leben erweckt wird. z.B. Auswerten der Signale der 
Funkschnittstelle->Seriell? am Prozessor über das Interrupt-System.

von Chris J. (Gast)


Lesenswert?

noreply@noreply.com schrieb:
> Die Kür wäre dann Stop-Mode, wobei der Prozessor mit diversen EXTI
> wieder zum Leben erweckt wird. z.B. Auswerten der Signale der
> Funkschnittstelle->Seriell? am Prozessor über das Interrupt-System.

Macht nur bei einem Lochraster Aufbau wo noch ein FTDI und ein RF 
Empfänger versorgt werden nicht soooo viel Sinn, denn unter 40mA komme 
ich nie. Ist schon ok so, er sleept jetzt und damit bin ich zufrieden,. 
Notfalls noch einen Akku mehr dran pappen.

von Dr. Sommer (Gast)


Lesenswert?

noreply@noreply.com schrieb:
> - Ich würde es erstmal wie Dr. Sommer machen. HSI ohne PLL verwenden und
> versuchen mit 8 MHz Taktfrequenz für HCLK auskommen.

HSI ist halt leider ungenau und für manche Interfaces braucht man dann 
doch hohe Taktraten (braucht PLL) :-/
Wie gesagt nutze ich __WFI() in fast jedem Projekt, das ist IMO Schritt 
Nr. 1 zur Reduktion der Leistungsaufnahme. Alles in Interrupts zu machen 
und explizite Zustände zu modellieren zwingt auch zur sauberen 
Programmierung der Abläufe ;-) In meinem Beispiel hat das den Verbrauch 
fast halbiert...

Chris J. schrieb:
> Macht nur bei einem Lochraster Aufbau wo noch ein FTDI und ein RF
> Empfänger versorgt werden nicht soooo viel Sinn, denn unter 40mA komme
> ich nie.
Na, dann reicht vielleicht die schlichte __WFI()-Variante. Wenn du den 
intergrierten USB-Controller statt FTDI-IC verwendest sparst du 
vielleicht noch mehr (den bei Bedarf abschalten o.ä.).

von Chris J. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Na, dann reicht vielleicht die schlichte __WFI()-Variante. Wenn du den
> intergrierten USB-Controller statt FTDI-IC verwendest sparst du
> vielleicht noch mehr (den bei Bedarf abschalten o.ä.).

Wenn ich bloss wüsste wie man den als RS232 verwenden kann gern.... nur 
habe ich von USB Programmierung Null Ahnung, von Ethernet noch viel 
weniger.

von Christopher J. (christopher_j23)


Lesenswert?

Mw E. schrieb:
> Wenn ihr den Tiefschlaf wollt, dann müsst ihr dafür sorgen, dass dem SWD
> nicht sein Takt geraubt wird.
> -> DBGMCU_CR Register bespaßen

Genau so sieht es nämlich aus und zwar sowohl für Sleep- als auch für 
Stop-Mode. Siehe auch Kapitel 31.16 im Handbuch.

Mit dem Stop-Mode kommt man schon ziemlich weit runter mit dem 
Stromverbrauch, d.h. 24µA wenn "voltage regulator on" und 14µA wenn 
"voltage regulator low-power". Die Aufwachzeit aus WFE beträgt dann 
gerade einmal 3,5µs/5,4µs (VR on/low-power) und der Inhalt des RAM und 
der Register bleibt komplett erhalten. Wie man ihn schlafen legen kann 
und wie man ihn dann wieder wach bekommt steht alles in Kapitel 5.3 im 
Handbuch.

In der AN2629 finden sich viele weitere Infos zu den Power-Modi der 
F1-Serie:
www.st.com/resource/en/application_note/cd00171691.pdf

von Dr. Sommer (Gast)


Lesenswert?

Chris J. schrieb:
> Wenn ich bloss wüsste wie man den als RS232 verwenden kann gern.... nur
> habe ich von USB Programmierung Null Ahnung, von Ethernet noch viel
> weniger.

USB-Tutorial mit STM32: Virtueller COM-Port, 
UART auf USB: Eigenbau oder mit der ST-eigenen Bibliothek... Die 
Emulation von RS232 ist aber IMO unnötig und verursacht nur zusätzliche 
Probleme.

von Chris J. (Gast)


Lesenswert?

Christopher J. schrieb:
> In der AN2629 finden sich viele weitere Infos zu den Power-Modi der
> F1-Serie:
> www.st.com/resource/en/application_note/cd00171691.pdf

Ja, aber die Firmware dazu ist nicht aufzutreiben, diese AN hatte ich 
auch schon in der Hand. Aber wo sind die Beispiele?

von Chris J. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Emulation von RS232 ist aber IMO unnötig und verursacht nur zusätzliche
> Probleme.

Ok..... und wenn ich den Text so überfliege und mir überlege wie einfach 
es ist eine UART zu bedienen, die mir über den FTDI dann ein VT100 
Terminal Programm mit Ausgaben füttert, mir sogar Eingaben erlaubt dann 
überlege ich, ob es ein Hobby das wert ist mich da ein zu arbeiten, weil 
ich es nicht mehr beruflich mache, HW/SW Entwicklung habe ich 2006 
zugunsten einer höher bezahlten Tätigkeit (Internationale Normung und 
Zertifizierung) aufgegeben ;-)

In den Libs usw findet sich nichts zu USB, sehr wohl aber viele 
kostenpflichtige Anbieter, zb Segger die ihre Stacks verkaufen wollen.

von Dr. Sommer (Gast)


Lesenswert?

Ja es ist etwas komplizierter. Wenn man vorhandene Bibliotheken nutzt 
reduziert sich das aber stark...

von Dr. Sommer (Gast)


Lesenswert?

Chris J. schrieb:
> In den Libs usw findet sich nichts zu USB, sehr wohl aber viele
> kostenpflichtige Anbieter, zb Segger die ihre Stacks verkaufen wollen.

Doch, ST liefert bei der HAL einen USB-Device-Stack und auch Beispiele 
für VCP (virtueller Com-Port).

von Chris J. (Gast)


Lesenswert?

Eben... genauso wie FPGAs lasse ich das die machen, die den ganzen Tag 
8h dafür Zeit haben und dafür bezahlt werden, während meine Freizeit 
Bastelei ein paar Daten Bytes quer durchs Haus zu schicken und auf einer 
SD Karte mit der sehr einfach zu ändernden Chan Fat zu speichern weiter 
auf die alten Konzepte setzt. Gab neulich im Forum auch so einen 
Knallfrosch, der eine eigene Koptersteuerung entwickeln wollte.... bis 
ihm jemand erklärte, dass die Ardupilot Pixhawk so rund 300 Mannjahre 
intus hat, die man für 80 Euro kaufen kann und es nur wenige Menschen 
gibt, einen Kalman-Filter auch nur erklären können......

von noreply@noreply.com (Gast)


Lesenswert?

Chris J. schrieb:
> Ok..... und wenn ich den Text so überfliege und mir überlege wie einfach
> es ist eine UART zu bedienen, die mir über den FTDI dann ein VT100

Verstehe ich jetzt nicht ganz. Der STM32F1 hat doch genug 
UART/USART-Schnittstellen. Oder ist der Engpaß das VT100-Terminal 
(Laptop ohne serielle Schnittstelle?).

von Chris J. (Gast)


Angehängte Dateien:

Lesenswert?

noreply@noreply.com schrieb:
> Verstehe ich jetzt nicht ganz. Der STM32F1 hat doch genug
> UART/USART-Schnittstellen.

Hat er..... RX und TX + evtl noch CTS auf einen FTDI Chip für 2 Euro, 
FTDI in USB Port, minicom unter Linux aufrufen und schon habe ich meine 
Ausgaben ;-)
Serielle hat der PC natürlich nicht mehr und selbst wenn ohne eine Pumpe 
MAX232 dazwischen gehts ja eh nicht.
Das klappte schon beim Z80, den ich gebaut habe mit der SIO, die mir 
zusammen mit mcurses ein komplettes Betriebssyystem auf dem VT100 
erzeugt mit Eingaben usw.

von noreply@noreply.com (Gast)


Lesenswert?

@Chris J.

Wir diskutieren hier aber über Low-Power-Modes vom STM32F1. Der 
Leistungsverbrauch vom FTDI wird aber doch normalerweise vom Laptop 
bestritten.

von Chris J. (Gast)


Lesenswert?

Danke für den Hinweis, da hatte ich noch einen Verdrahtungsfehler, der 
FTDI wurde bei mir vom Bopard versorgt, +5V war abgeklemmt zum PC.

Ich werde die ganzen Erkenntnisse mal für die Nachwelt aufbereiten ;-)

https://www.youtube.com/watch?v=Bif_tIH7bMk

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.