35
35
extern void HAL_SuspendTick (void );
36
36
extern void HAL_ResumeTick (void );
37
37
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
+
38
133
void hal_sleep (void )
39
134
{
40
135
// Disable IRQs
@@ -83,16 +178,21 @@ void hal_deepsleep(void)
83
178
#else /* TARGET_STM32L4 */
84
179
HAL_PWR_EnterSTOPMode (PWR_LOWPOWERREGULATOR_ON , PWR_STOPENTRY_WFI );
85
180
#endif /* TARGET_STM32L4 */
181
+ // Verify Clock Out of Deep Sleep
182
+ ForceClockOutofDeepSleep ();
86
183
87
184
// Restart HAL tick
88
185
HAL_ResumeTick ();
89
186
90
- // Enable IRQs
91
- core_util_critical_section_exit ();
92
-
93
187
// After wake-up from STOP reconfigure the PLL
94
188
SetSysClock ();
95
189
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
+
96
196
TIM_HandleTypeDef TimMasterHandle ;
97
197
TimMasterHandle .Instance = TIM_MST ;
98
198
__HAL_TIM_SET_COUNTER (& TimMasterHandle , EnterTimeUS );
@@ -107,6 +207,8 @@ void hal_deepsleep(void)
107
207
rtc_synchronize ();
108
208
}
109
209
#endif
210
+ // Enable IRQs
211
+ core_util_critical_section_exit ();
110
212
}
111
213
112
214
#endif
0 commit comments