Hallo zusammen, wie schon in der Überschrift erwähnt versuche ich einen STM32F103C8T aus dem STOPMode mit Hilfe eines RTC-Alarms aufzuwecken. Im SleepMode klappt das auch schon. Nur im STOPMode wacht der STM32 nicht mehr auf. Nur ein Signal auf dem entsprechend konfiguriertem Pin PA0 schafft hier Abhilfe. Hier ein Auszug aus meiner main.c: __HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE(); __HAL_RTC_ALARM_EXTI_ENABLE_IT(); HAL_GPIO_WritePin(LED_A_GPIO_Port, LED_A_Pin, SET); HAL_RTC_SetAlarm_IT(&hrtc, &alarm_a, RTC_FORMAT_BIN); HAL_SuspendTick(); HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI); // HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); HAL_ResumeTick(); SystemClock_Config(); HAL_GPIO_WritePin(LED_A_GPIO_Port, LED_A_Pin, RESET); Da ja laut STM Dokumentation die EXTI_Line17 speziell im STOPMode konfiguriert werden muss, habe ich die zwei oberen Zeilen verwendet, was jedoch kein Unterschied macht. Ich habe Zwar schon einige Beiträge zu dem Thema gefunden. Entweder wurde hier jedoch der SleepMode verwendet oder nicht die HAL Librarys genutzt. Ich hoffe jemand kennt sich besser mit dem Thema aus und kann mir helfen. Gruß Alex
Ich benutze die die HAL nicht, sondern mache das "Native". Sieht bei mir ziemlich ähnlich aus. Bei mir habe ich aber noch folgenden Code für den RTC-Interrupt:
1 | void RTCAlarm_IRQHandler() |
2 | {
|
3 | if((RTC->CRL&RTC_CRL_ALRF)!=0) |
4 | {
|
5 | RTC->CRL &= ~RTC_CRL_ALRF; |
6 | }
|
7 | EXTI->PR = EXTI_EMR_MR17; |
8 | }
|
Ob das nötig ist? Ich steck da nach einigen Jahren nicht mehr drin.
Erstmal danke für die Antwort. Meine Interruptcode setzt eigentlich auch das Flag zurück. Hier die entsprechende Stelle:
1 | void RTC_IRQHandler(void) |
2 | {
|
3 | /* USER CODE BEGIN RTC_IRQn 0 */
|
4 | |
5 | /* USER CODE END RTC_IRQn 0 */
|
6 | HAL_RTCEx_RTCIRQHandler(&hrtc); |
7 | /* USER CODE BEGIN RTC_IRQn 1 */
|
8 | HAL_RTC_AlarmIRQHandler(&hrtc); |
9 | HAL_GPIO_TogglePin(LED_B_GPIO_Port, LED_B_Pin); |
10 | |
11 | /* USER CODE END RTC_IRQn 1 */
|
12 | }
|
Wie sieht denn deine "Native" Konfiguration aus falls du die noch hast?
Bitte sehr. Den folgenden Code habe zum Testen des Stop-Modes verwendet. Sicherheithalber habe ich nichts bereinigt und den Code einfach roh hier eingestellt (abgekippt). Also bitte nicht schlagen.
1 | void RTC_IRQHandler() |
2 | {
|
3 | if((RTC->ISR&RTC_ISR_ALRAF)!=0) |
4 | {
|
5 | RTC->ISR ^= RTC_ISR_ALRAF; |
6 | }
|
7 | EXTI->PR = EXTI_EMR_MR17; |
8 | }
|
9 | |
10 | int Test_StopMode(bool LSI_Enabled) |
11 | {
|
12 | // Delay und LED blinken lassen
|
13 | if(1==2) |
14 | {
|
15 | RCC->AHBENR |= RCC_AHBENR_GPIOAEN; |
16 | GPIOA->MODER = 0x28000100; // GPIO_MODER_MODER4_0*1; |
17 | for(int i=0; i<20; i++) |
18 | {
|
19 | GPIOA->ODR ^= 0x010; |
20 | for(int i=0; i<500000; i++) |
21 | {
|
22 | __asm("nop"); |
23 | }
|
24 | }
|
25 | }
|
26 | |
27 | // fCPU = 1MHz
|
28 | RCC->CFGR |= RCC_CFGR_HPRE_DIV8; |
29 | |
30 | // alle GPIO auf Input mit Pulldown
|
31 | RCC->AHBENR |= RCC_AHBENR_GPIOAEN; |
32 | GPIOA->PUPDR = 0xa6aaa8aa; // außer PA13/PA14 (SWD-Debug) und PA4 (LED) |
33 | RCC->AHBENR |= RCC_AHBENR_GPIOBEN; |
34 | GPIOB->PUPDR = 0x00000008; // Achtung: bei 0xaaaaaaaa ist PB1 möglicherweise (aber wann/warum???) floating! |
35 | RCC->AHBENR |= RCC_AHBENR_GPIOFEN; |
36 | GPIOF->PUPDR = 0x0000000a; |
37 | |
38 | // GPIOA4 (LED) auf Ausgang (all Pulldown, except PA4 (LED-Output) and PA13/PA14 (SWD-Debug))
|
39 | GPIOA->MODER = 0x28000100; |
40 | // GPIOA->MODER = 0x00000100; // PA4 (LED)
|
41 | GPIOB->MODER = 0x00000000; |
42 | GPIOF->MODER = 0x00000000; |
43 | |
44 | RCC->APB1ENR |= RCC_APB1ENR_PWREN; |
45 | |
46 | bool Interrupt = true; |
47 | |
48 | // Start LSI-Timer
|
49 | if(LSI_Enabled) |
50 | {
|
51 | RCC->CSR |= RCC_CSR_LSION; |
52 | while((RCC->CSR&RCC_CSR_LSIRDY)==0) |
53 | {
|
54 | __asm("nop"); |
55 | }
|
56 | |
57 | PWR->CR |= PWR_CR_DBP; |
58 | |
59 | RCC->BDCR |= RCC_BDCR_BDRST; |
60 | RCC->BDCR = 0; |
61 | RCC->BDCR |= RCC_BDCR_RTCSEL_0*2; // LSE RTC |
62 | RCC->BDCR |= RCC_BDCR_RTCEN; |
63 | |
64 | // Disable write protection
|
65 | RTC->WPR = 0xCA; |
66 | RTC->WPR = 0x53; |
67 | |
68 | // Change Prescaler
|
69 | RTC->ISR |= RTC_ISR_INIT; |
70 | while((RTC->ISR&RTC_ISR_INITF)==0) |
71 | {
|
72 | __asm("nop"); |
73 | }
|
74 | // RTC->PRER = 0x00090013; // T = 5ms (= (0x09+1)*(0x0013+1)/40000Hz)
|
75 | // RTC->PRER = 0x000f0018; // T = 10ms (= (0x0f+1)*(0x0018+1)/40000Hz)
|
76 | // RTC->PRER = 0x000f0031; // T = 20ms (= (0x0f+1)*(0x0031+1)/40000Hz)
|
77 | // RTC->PRER = 0x000f00f9; // T = 100ms (= (0x0f+1)*(0x00f9+1)/40000Hz)
|
78 | // RTC->PRER = 0x000f09c3; // T = 1.00s (= (0x0f+1)*(0x09c3+1)/40000Hz)
|
79 | // RTC->PRER = 0x000f3fff; // T = 6.55s (= (0x0f+1)*(0x3fff+1)/40000Hz)
|
80 | const int msT = 100; // max. 8192ms |
81 | RTC->PRER = 0x00090000+msT*4-1; |
82 | |
83 | RTC->ISR ^= RTC_ISR_INIT; |
84 | |
85 | if(Interrupt) |
86 | {
|
87 | EXTI->RTSR |= EXTI_FTSR_TR17; // rising edge |
88 | EXTI->IMR |= EXTI_IMR_MR17; |
89 | EXTI->PR |= EXTI_EMR_MR17; |
90 | NVIC_Init(RTC_IRQn, 3, ENABLE); |
91 | }
|
92 | else
|
93 | {
|
94 | EXTI->RTSR |= EXTI_RTSR_TR17; // rising edge |
95 | EXTI->EMR |= EXTI_EMR_MR17; |
96 | }
|
97 | |
98 | // Alarm bei jeder Sekunde
|
99 | RTC->ALRMAR = RTC_ALRMAR_MSK4 | RTC_ALRMAR_MSK3 | RTC_ALRMAR_MSK2 | RTC_ALRMAR_MSK1; |
100 | RTC->CR |= RTC_CR_ALRAE | RTC_CR_ALRAIE; |
101 | |
102 | // Enable write protection
|
103 | RTC->WPR = 0xFE; |
104 | RTC->WPR = 0x64; |
105 | }
|
106 | |
107 | while(true) |
108 | {
|
109 | // Sleep
|
110 | PWR->CR |= PWR_CR_LPDS; |
111 | SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; |
112 | if(Interrupt) |
113 | {
|
114 | __WFI(); |
115 | }
|
116 | else
|
117 | {
|
118 | if((RTC->ISR&RTC_ISR_ALRAF)!=0) |
119 | {
|
120 | RTC->ISR ^= RTC_ISR_ALRAF; |
121 | }
|
122 | // Debug: Prüfen ob Dauerschlaf, wenn RTC_ISR_ALRAF bereits beim Aufruf von "__WFE()" gesetzt ist: (ist aber alles Ok)
|
123 | if(1==2) |
124 | {
|
125 | while((RTC->ISR&RTC_ISR_ALRAF)==0) |
126 | {
|
127 | __asm("nop"); |
128 | }
|
129 | }
|
130 | __WFE(); |
131 | }
|
132 | SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); |
133 | |
134 | // Toggle LED
|
135 | if(1==1) |
136 | {
|
137 | GPIOA->ODR ^= 0x010; // Toggle LED |
138 | for(int i=0; i<-1000; i++) |
139 | {
|
140 | __asm("nop"); |
141 | }
|
142 | }
|
143 | }
|
144 | |
145 | //
|
146 | // - 16.11.2016
|
147 | //
|
148 | // - VCC = 3.46V
|
149 | //
|
150 | // - Interrupt = true;
|
151 | //
|
152 | // - Programm im Flash
|
153 | //
|
154 | // - LSI_Enabled==FALSE
|
155 | // xMHz / xms -> 5.5µA
|
156 | //
|
157 | // - LSI_Enabled==TRUE
|
158 | // 1MHz / 5ms -> 17.9µA (20.1µA im SRAM)
|
159 | // 1MHz / 10ms -> 12.3µA (13.4µA im SRAM)
|
160 | // 1MHz / 20ms -> 9.5µA (19.1µA im SRAM)
|
161 | // 1MHz / 100ms -> 7.3µA ( 7.4µA im SRAM)
|
162 | // 1MHz / 6.5s -> 6.7µA ( 6.7µA im SRAM)
|
163 | // 8MHz / 5ms -> 11.8µA
|
164 | // 8MHz / 10ms -> 9.3µA
|
165 | // 8MHz / 100ms -> 7.0µA
|
166 | // 8MHz / 6.5s -> 6.7µA
|
167 | //
|
168 | // -> Ergebnis
|
169 | // - I(xMHz, x) = 5.5µA
|
170 | // - I(1MHz, t) = 6.7µA + 11.2µA*5ms/t
|
171 | // - I(8MHz, t) = 6.7µA + 5.1µA*5ms/t
|
172 | // - Verbrauch in SRAM und FLASH gleich (etwas langsamer vermutlich wegen fehledem Optimize-Compiler-Flag)
|
173 | |
174 | // - Stromaufnahme in Pausephase - im Flash (30.03.2017)
|
175 | // VCC/V | I/µA
|
176 | // ------+-------
|
177 | // 2.0 | 5.5
|
178 | // 2.5 | 6.0
|
179 | // 3.0 | 6.5
|
180 | // 3.3 | 6.9 +1mA@1MHz für 50µs; +2.2mA@8MHz für 10µs; +0.2µA mit IWDG
|
181 | // 3.5 | 7.2
|
182 | // 4.0 | 7.9
|
183 | // 4.5 | 8.9
|
184 | // 5.0 | 19..12 sinkt nach und nach
|
185 | return 0; |
186 | }
|
Vielen Dank schonmal, Ich habe beide Programme jetzt miteinander verglichen und wie du schon geschrieben hast machen beide ungefähr das Gleiche. Das Problem lag in meinem Fall bei den Interrupt Handlern. Ich habe bei mir nur den RTC_IRQHandler benutzt, welcher auch automatisch von CubeMX generiert wird. Gefehlt hat der spezielle RTC_Alarm_IRQHandler. Dieser musste bei mir selbst geschrieben werden. Mich wundert jetzt nur, dass dieser auch bei dir fehlt oder ich übersehe auch nur wieder etwas. Mich würde nur noch interessieren, ob ich die Einstellung für den Alarm Interrupt in CubeMX nur nicht gefunden habe oder ob man diese immer manuell vornehmen muss. Falls jemand auch CubeMX benutzt kann er ja mal seine Ideen hier schreiben. Ich nutze die Version 5.0.1.
Ich Trottel hab den Code aus meinem STM32F0-Ordner genommen. Der Code für den STM32F1 sieht anders aus. Dort verwende ich auch den RTCAlarm_IRQHandler. (Bzw. wenn unbenötigt nötig würde es aber auch ohne Interrupt per "Event" gehen.)
Ist mir auch schon mal passiert. Leider spuckt der Compiler keine Fehlermeldung aus, wenn die C-Funktion des Interrupt Handlers den falschen Namen hat. Ich glaube, man müsste die ganzen Weak referenzen aus der startup_stm32.s entfernen. Kennt jemand eine elegantere Lösung, diesen Fehler zu vermeiden?
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.