Skip to content

Commit 8007b1d

Browse files
committed
Use temporarily MSI or HSI when exiting Deep Sleep
There are cases where HW registers are found in unpexcepted state when exiting Deep Sleep only few micro-seconds after it was entered. By using an internal clock that does not depend on anythin and clocking the system without using PLL, this allows SetSysClock default configuration to run fine whatever possible configuration we find the HW in when exiting Deep Sleep. Also we shall restore interrupts only after all cloks are back to expected running state.
1 parent f5385e7 commit 8007b1d

File tree

1 file changed

+86
-3
lines changed

1 file changed

+86
-3
lines changed

targets/TARGET_STM/sleep.c

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,88 @@
3535
extern void HAL_SuspendTick(void);
3636
extern void HAL_ResumeTick(void);
3737

38+
// On L4 platforms we've seen unstable PLL CLK configuraiton
39+
// when DEEP SLEEP exits just few µs after being entered
40+
// So we need to force MSI usage before setting clocks again
41+
static void ForceClockOutofDeepSleep(void) {
42+
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
43+
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
44+
uint32_t pFLatency = 0;
45+
46+
/* Enable Power Control clock */
47+
__HAL_RCC_PWR_CLK_ENABLE();
48+
49+
#ifdef PWR_FLAG_VOS
50+
/* Poll VOSF bit of in PWR_CSR. Wait until it is reset to 0 */
51+
//while (__HAL_PWR_GET_FLAG(PWR_FLAG_VOS) != RESET) {};
52+
#endif
53+
54+
/* Get the Oscillators configuration according to the internal RCC registers */
55+
HAL_RCC_GetOscConfig(&RCC_OscInitStruct);
56+
57+
#if (TARGET_STM32L4 || TARGET_STM32L1) /* MSI used for L4 */
58+
/**Initializes the CPU, AHB and APB busses clocks
59+
*/
60+
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
61+
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
62+
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
63+
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_4; // Intermediate freq, 1MHz range
64+
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
65+
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
66+
error("clock issue\r\n");
67+
}
68+
69+
/* Get the Clocks configuration according to the internal RCC registers */
70+
HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &pFLatency);
71+
72+
// Select HSI ss system clock source as a first step
73+
#ifdef RCC_CLOCKTYPE_PCLK2
74+
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK
75+
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
76+
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
77+
#else
78+
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK
79+
| RCC_CLOCKTYPE_PCLK1);
80+
#endif
81+
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
82+
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
83+
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
84+
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, pFLatency) != HAL_OK) {
85+
error("clock issue\r\n");
86+
}
87+
#else /* HSI used on others */
88+
/**Initializes the CPU, AHB and APB busses clocks
89+
*/
90+
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
91+
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
92+
RCC_OscInitStruct.HSICalibrationValue = 16;
93+
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
94+
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
95+
error("clock issue");
96+
}
97+
98+
/* Get the Clocks configuration according to the internal RCC registers */
99+
HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &pFLatency);
100+
101+
/**Initializes the CPU, AHB and APB busses clocks
102+
*/
103+
#ifdef RCC_CLOCKTYPE_PCLK2
104+
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
105+
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2);
106+
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
107+
#else
108+
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
109+
|RCC_CLOCKTYPE_PCLK1);
110+
#endif
111+
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
112+
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
113+
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
114+
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, pFLatency) != HAL_OK) {
115+
error("clock issue");
116+
}
117+
#endif // TARGET_STM32L4
118+
}
119+
38120
void hal_sleep(void)
39121
{
40122
// Disable IRQs
@@ -83,13 +165,12 @@ void hal_deepsleep(void)
83165
#else /* TARGET_STM32L4 */
84166
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
85167
#endif /* TARGET_STM32L4 */
168+
// Verify Clock Out of Deep Sleep
169+
ForceClockOutofDeepSleep();
86170

87171
// Restart HAL tick
88172
HAL_ResumeTick();
89173

90-
// Enable IRQs
91-
core_util_critical_section_exit();
92-
93174
// After wake-up from STOP reconfigure the PLL
94175
SetSysClock();
95176

@@ -107,6 +188,8 @@ void hal_deepsleep(void)
107188
rtc_synchronize();
108189
}
109190
#endif
191+
// Enable IRQs
192+
core_util_critical_section_exit();
110193
}
111194

112195
#endif

0 commit comments

Comments
 (0)