Skip to content

Commit f4578c7

Browse files
committed
fix: in case of LowPower Sleep, it is necessary to decrease CPU Frequency
Decrease CPU freq before setting LPR mode, Restore CPU freq after wakeup Signed-off-by: Alexandre Bourdiol <[email protected]>
1 parent 51dc4ef commit f4578c7

File tree

1 file changed

+162
-0
lines changed

1 file changed

+162
-0
lines changed

src/low_power.c

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,170 @@ void LowPower_EnableWakeUpPin(uint32_t pin, uint32_t mode)
224224
}
225225
}
226226

227+
#if defined(PWR_CSR_REGLPF)
228+
/**
229+
* @brief For STM32L0 and STM32L1, running in LowPower Sleep requires
230+
* to slow down frequency to MSI range1.
231+
* @retval None
232+
*/
233+
void SystemClock_Decrease(void)
234+
{
235+
RCC_OscInitTypeDef RCC_OscInitStruct = {};
236+
RCC_ClkInitTypeDef RCC_ClkInitStruct = {};
237+
238+
/** Configure the main internal regulator output voltage
239+
*/
240+
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
241+
242+
/** Initializes the RCC Oscillators according to the specified parameters
243+
* in the RCC_OscInitTypeDef structure.
244+
*/
245+
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
246+
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
247+
RCC_OscInitStruct.MSICalibrationValue = 0;
248+
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_1;
249+
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
250+
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
251+
Error_Handler();
252+
}
253+
254+
/** Initializes the CPU, AHB and APB buses clocks
255+
*/
256+
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
257+
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
258+
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
259+
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
260+
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
261+
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
262+
263+
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) {
264+
Error_Handler();
265+
}
266+
}
267+
#elif defined(STM32L4xx) || defined(STM32L5xx) || defined(STM32WBxx) || defined(STM32WLxx)
268+
/**
269+
* @brief For STM32L4, STM32L5, STM32WB and STM32WL
270+
* running in LowPower Sleep requires to slow down frequency to 2MHz max.
271+
* @retval None
272+
*/
273+
void SystemClock_Decrease(void)
274+
{
275+
RCC_OscInitTypeDef RCC_OscInitStruct = {};
276+
RCC_ClkInitTypeDef RCC_ClkInitStruct = {};
277+
278+
/** Configure the main internal regulator output voltage
279+
*/
280+
#if defined(STM32L4xx) || defined(STM32WBxx)
281+
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
282+
#elif defined(STM32L5xx) || defined(STM32WLxx)
283+
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2) != HAL_OK)
284+
#endif
285+
{
286+
Error_Handler();
287+
}
288+
289+
/** Initializes the RCC Oscillators according to the specified parameters
290+
* in the RCC_OscInitTypeDef structure.
291+
*/
292+
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
293+
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
294+
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
295+
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_5;
296+
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
297+
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
298+
Error_Handler();
299+
}
300+
301+
/** Initializes the CPU and buses clocks
302+
*/
303+
#if defined(STM32WBxx)
304+
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK4 | RCC_CLOCKTYPE_HCLK2
305+
| RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
306+
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
307+
RCC_ClkInitStruct.AHBCLK2Divider = RCC_SYSCLK_DIV1;
308+
RCC_ClkInitStruct.AHBCLK4Divider = RCC_SYSCLK_DIV1;
309+
#elif defined(STM32WLxx)
310+
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK3 | RCC_CLOCKTYPE_HCLK
311+
| RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1
312+
| RCC_CLOCKTYPE_PCLK2;
313+
RCC_ClkInitStruct.AHBCLK3Divider = RCC_SYSCLK_DIV1;
314+
#elif defined(STM32L4xx)
315+
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
316+
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
317+
#endif
318+
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
319+
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
320+
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
321+
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
322+
323+
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) {
324+
Error_Handler();
325+
}
326+
}
327+
#elif defined(STM32G0xx) || defined(STM32G4xx)
328+
/**
329+
* @brief For STM32G0 and STM32G4
330+
* running in LowPower Sleep requires to slow down frequency to 2MHz max.
331+
* @retval None
332+
*/
333+
void SystemClock_Config(void)
334+
{
335+
RCC_OscInitTypeDef RCC_OscInitStruct = {};
336+
RCC_ClkInitTypeDef RCC_ClkInitStruct = {};
337+
338+
/** Configure the main internal regulator output voltage
339+
*/
340+
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
341+
342+
/** Initializes the RCC Oscillators according to the specified parameters
343+
* in the RCC_OscInitTypeDef structure.
344+
*/
345+
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
346+
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
347+
#if defined(STM32G0xx)
348+
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
349+
#endif
350+
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
351+
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
352+
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
353+
Error_Handler();
354+
}
355+
356+
/** Initializes the CPU, AHB and APB buses clocks
357+
*/
358+
#if defined(STM32G4xx)
359+
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
360+
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
361+
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
362+
#elif defined(STM32G0xx)
363+
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
364+
| RCC_CLOCKTYPE_PCLK1;
365+
#endif
366+
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
367+
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV8;
368+
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
369+
370+
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) {
371+
Error_Handler();
372+
}
373+
}
374+
375+
#endif
376+
227377
/**
228378
* @brief Enable the sleep mode.
229379
* @param None
230380
* @retval None
231381
*/
232382
void LowPower_sleep(uint32_t regulator)
233383
{
384+
385+
#if defined(PWR_CSR_REGLPF) || defined(PWR_SR2_REGLPF)
386+
// When LowPower regulator sleep mode is used, it is necessary to decrease CPU Frequency
387+
if (regulator == PWR_LOWPOWERREGULATOR_ON) {
388+
SystemClock_Decrease();
389+
}
390+
#endif
234391
/*
235392
* Suspend Tick increment to prevent wakeup by Systick interrupt.
236393
* Otherwise the Systick interrupt will wake up the device within
@@ -246,7 +403,12 @@ void LowPower_sleep(uint32_t regulator)
246403
if (regulator == PWR_LOWPOWERREGULATOR_ON) {
247404
__HAL_RCC_PWR_CLK_ENABLE();
248405
HAL_PWREx_DisableLowPowerRunMode();
406+
407+
// Restore systemClock which has been decreased by SystemClock_Decrease()
408+
SystemClock_Config();
249409
}
410+
411+
250412
#endif
251413

252414
/* Resume Tick interrupt if disabled prior to SLEEP mode entry */

0 commit comments

Comments
 (0)