Skip to content

Commit 96084a3

Browse files
authored
Merge pull request #6561 from LMESTM/Stm32DeepSleepClock
Stm32 deep sleep clock
2 parents a3faf58 + ad4a250 commit 96084a3

File tree

1 file changed

+105
-3
lines changed

1 file changed

+105
-3
lines changed

targets/TARGET_STM/sleep.c

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

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

87184
// Restart HAL tick
88185
HAL_ResumeTick();
89186

90-
// Enable IRQs
91-
core_util_critical_section_exit();
92-
93187
// After wake-up from STOP reconfigure the PLL
94188
SetSysClock();
95189

190+
/* Wait for clock to be stabilized.
191+
* TO DO: a better way of doing this, would be to rely on
192+
* HW Flag. At least this ensures proper operation out of
193+
* deep sleep */
194+
wait_loop(500);
195+
96196
TIM_HandleTypeDef TimMasterHandle;
97197
TimMasterHandle.Instance = TIM_MST;
98198
__HAL_TIM_SET_COUNTER(&TimMasterHandle, EnterTimeUS);
@@ -107,6 +207,8 @@ void hal_deepsleep(void)
107207
rtc_synchronize();
108208
}
109209
#endif
210+
// Enable IRQs
211+
core_util_critical_section_exit();
110212
}
111213

112214
#endif

0 commit comments

Comments
 (0)