Skip to content

Commit 3023ea6

Browse files
authored
Merge pull request #74 from ABOSTM/LOWPOWER_SLEEP
Fix LowPower Sleep Mode
2 parents c2e8d13 + afc292f commit 3023ea6

File tree

1 file changed

+172
-0
lines changed

1 file changed

+172
-0
lines changed

src/low_power.c

+172
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,172 @@ 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+
268+
#elif defined(STM32L4xx) || defined(STM32L5xx) || defined(STM32WBxx) || defined(STM32WLxx)
269+
/**
270+
* @brief For STM32L4, STM32L5, STM32WB and STM32WL
271+
* running in LowPower Sleep requires to slow down frequency to 2MHz max.
272+
* @retval None
273+
*/
274+
void SystemClock_Decrease(void)
275+
{
276+
RCC_OscInitTypeDef RCC_OscInitStruct = {};
277+
RCC_ClkInitTypeDef RCC_ClkInitStruct = {};
278+
279+
/** Configure the main internal regulator output voltage
280+
*/
281+
#if defined(STM32L4xx) || defined(STM32WBxx)
282+
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
283+
#elif defined(STM32L5xx) || defined(STM32WLxx)
284+
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2) != HAL_OK)
285+
#endif
286+
{
287+
Error_Handler();
288+
}
289+
290+
/** Initializes the RCC Oscillators according to the specified parameters
291+
* in the RCC_OscInitTypeDef structure.
292+
*/
293+
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
294+
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
295+
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
296+
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_5;
297+
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
298+
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
299+
Error_Handler();
300+
}
301+
302+
/** Initializes the CPU and buses clocks
303+
*/
304+
#if defined(STM32WBxx)
305+
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK4 | RCC_CLOCKTYPE_HCLK2
306+
| RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
307+
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
308+
RCC_ClkInitStruct.AHBCLK2Divider = RCC_SYSCLK_DIV1;
309+
RCC_ClkInitStruct.AHBCLK4Divider = RCC_SYSCLK_DIV1;
310+
#elif defined(STM32WLxx)
311+
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK3 | RCC_CLOCKTYPE_HCLK
312+
| RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1
313+
| RCC_CLOCKTYPE_PCLK2;
314+
RCC_ClkInitStruct.AHBCLK3Divider = RCC_SYSCLK_DIV1;
315+
#elif defined(STM32L4xx)
316+
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
317+
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
318+
#endif
319+
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
320+
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
321+
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
322+
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
323+
324+
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) {
325+
Error_Handler();
326+
}
327+
}
328+
329+
#elif defined(STM32G0xx) || defined(STM32G4xx)
330+
/**
331+
* @brief For STM32G0 and STM32G4
332+
* running in LowPower Sleep requires to slow down frequency to 2MHz max.
333+
* @retval None
334+
*/
335+
void SystemClock_Decrease(void)
336+
{
337+
RCC_OscInitTypeDef RCC_OscInitStruct = {};
338+
RCC_ClkInitTypeDef RCC_ClkInitStruct = {};
339+
340+
/** Configure the main internal regulator output voltage
341+
*/
342+
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
343+
344+
/** Initializes the RCC Oscillators according to the specified parameters
345+
* in the RCC_OscInitTypeDef structure.
346+
*/
347+
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
348+
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
349+
#if defined(STM32G0xx)
350+
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
351+
#endif
352+
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
353+
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
354+
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
355+
Error_Handler();
356+
}
357+
358+
/** Initializes the CPU, AHB and APB buses clocks
359+
*/
360+
#if defined(STM32G4xx)
361+
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
362+
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
363+
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
364+
#elif defined(STM32G0xx)
365+
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
366+
| RCC_CLOCKTYPE_PCLK1;
367+
#endif
368+
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
369+
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV8;
370+
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
371+
372+
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) {
373+
Error_Handler();
374+
}
375+
}
376+
#endif
377+
227378
/**
228379
* @brief Enable the sleep mode.
229380
* @param None
230381
* @retval None
231382
*/
232383
void LowPower_sleep(uint32_t regulator)
233384
{
385+
386+
#if defined(PWR_CSR_REGLPF) || defined(PWR_SR2_REGLPF)
387+
// When LowPower regulator sleep mode is used, it is necessary to decrease CPU Frequency
388+
if (regulator == PWR_LOWPOWERREGULATOR_ON) {
389+
SystemClock_Decrease();
390+
}
391+
#endif
392+
234393
/*
235394
* Suspend Tick increment to prevent wakeup by Systick interrupt.
236395
* Otherwise the Systick interrupt will wake up the device within
@@ -241,6 +400,19 @@ void LowPower_sleep(uint32_t regulator)
241400
/* Enter Sleep Mode , wake up is done once User push-button is pressed */
242401
HAL_PWR_EnterSLEEPMode(regulator, PWR_SLEEPENTRY_WFI);
243402

403+
#if defined(PWR_CSR_REGLPF) || defined(PWR_SR2_REGLPF)
404+
// In case of LowPower Regulator used for sleep, restore Main regulator on exit
405+
if (regulator == PWR_LOWPOWERREGULATOR_ON) {
406+
#if defined(__HAL_RCC_PWR_CLK_ENABLE)
407+
__HAL_RCC_PWR_CLK_ENABLE();
408+
#endif
409+
HAL_PWREx_DisableLowPowerRunMode();
410+
411+
// Restore systemClock which has been decreased by SystemClock_Decrease()
412+
SystemClock_Config();
413+
}
414+
#endif
415+
244416
/* Resume Tick interrupt if disabled prior to SLEEP mode entry */
245417
HAL_ResumeTick();
246418

0 commit comments

Comments
 (0)