Modified for BG96
Fork of mbed-dev by
Diff: targets/TARGET_STM/sleep.c
- Revision:
- 187:0387e8f68319
- Parent:
- 186:707f6e361f3e
--- a/targets/TARGET_STM/sleep.c Fri Jun 22 16:45:37 2018 +0100 +++ b/targets/TARGET_STM/sleep.c Thu Sep 06 13:40:20 2018 +0100 @@ -31,11 +31,12 @@ #include "sleep_api.h" #include "us_ticker_api.h" -#include "hal_tick.h" +#include "us_ticker_data.h" #include "mbed_critical.h" #include "mbed_error.h" -extern void rtc_synchronize(void); +extern void save_timer_ctx(void); +extern void restore_timer_ctx(void); /* Wait loop - assuming tick is 1 us */ static void wait_loop(uint32_t timeout) @@ -49,23 +50,64 @@ return; } + // On L4 platforms we've seen unstable PLL CLK configuraiton // when DEEP SLEEP exits just few µs after being entered // So we need to force MSI usage before setting clocks again -static void ForceClockOutofDeepSleep(void) +static void ForcePeriphOutofDeepSleep(void) { + uint32_t pFLatency = 0; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + +#if (TARGET_STM32L4 || TARGET_STM32L1) /* MSI used for L4 */ + /* Get the Clocks configuration according to the internal RCC registers */ + HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &pFLatency); + + // Select HSI ss system clock source as a first step +#ifdef RCC_CLOCKTYPE_PCLK2 + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK + | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; +#else + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK + | RCC_CLOCKTYPE_PCLK1); +#endif + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, pFLatency) != HAL_OK) { + error("clock issue\r\n"); + } +#else /* HSI used on others */ + /* Get the Clocks configuration according to the internal RCC registers */ + HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &pFLatency); + + /**Initializes the CPU, AHB and APB busses clocks + */ +#ifdef RCC_CLOCKTYPE_PCLK2 + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK + | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; +#else + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK + | RCC_CLOCKTYPE_PCLK1); +#endif + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, pFLatency) != HAL_OK) { + error("clock issue"); + } +#endif // TARGET_STM32L4 +} + +static void ForceOscOutofDeepSleep(void) +{ RCC_OscInitTypeDef RCC_OscInitStruct = {0}; - uint32_t pFLatency = 0; /* Enable Power Control clock */ __HAL_RCC_PWR_CLK_ENABLE(); -#ifdef PWR_FLAG_VOS - /* Poll VOSF bit of in PWR_CSR. Wait until it is reset to 0 */ - //while (__HAL_PWR_GET_FLAG(PWR_FLAG_VOS) != RESET) {}; -#endif - /* Get the Oscillators configuration according to the internal RCC registers */ HAL_RCC_GetOscConfig(&RCC_OscInitStruct); @@ -80,25 +122,6 @@ if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { error("clock issue\r\n"); } - - /* Get the Clocks configuration according to the internal RCC registers */ - HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &pFLatency); - - // Select HSI ss system clock source as a first step -#ifdef RCC_CLOCKTYPE_PCLK2 - RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK - | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; -#else - RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK - | RCC_CLOCKTYPE_PCLK1); -#endif - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI; - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, pFLatency) != HAL_OK) { - error("clock issue\r\n"); - } #else /* HSI used on others */ /**Initializes the CPU, AHB and APB busses clocks */ @@ -109,27 +132,17 @@ if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { error("clock issue"); } - - /* Get the Clocks configuration according to the internal RCC registers */ - HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &pFLatency); +#endif // TARGET_STM32L4 +} - /**Initializes the CPU, AHB and APB busses clocks - */ -#ifdef RCC_CLOCKTYPE_PCLK2 - RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK - |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2); - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; -#else - RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK - |RCC_CLOCKTYPE_PCLK1); -#endif - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, pFLatency) != HAL_OK) { - error("clock issue"); - } -#endif // TARGET_STM32L4 +/* The content of this function has been split into 2 separate functions + so that the involved structures are not allocated on the stack in parallel. + This will reduce the maximum stack usage in case on non-optimized / debug + compilers settings */ +static void ForceClockOutofDeepSleep(void) +{ + ForceOscOutofDeepSleep(); + ForcePeriphOutofDeepSleep(); } void hal_sleep(void) @@ -144,12 +157,24 @@ core_util_critical_section_exit(); } +extern int serial_is_tx_ongoing(void); + void hal_deepsleep(void) { + /* WORKAROUND: + * MBED serial driver does not handle deepsleep lock + * to prevent entering deepsleep until HW serial FIFO is empty. + * This is tracked in mbed issue 4408. + * For now, we're checking all Serial HW FIFO. If any transfer is ongoing + * we're not entering deep sleep and returning immediately. */ + if(serial_is_tx_ongoing()) { + return; + } + // Disable IRQs core_util_critical_section_enter(); - uint32_t EnterTimeUS = us_ticker_read(); + save_timer_ctx(); // Request to enter STOP mode with regulator in low power mode #if TARGET_STM32L4 @@ -174,6 +199,7 @@ #else /* TARGET_STM32L4 */ HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); #endif /* TARGET_STM32L4 */ + // Verify Clock Out of Deep Sleep ForceClockOutofDeepSleep(); @@ -186,22 +212,10 @@ * deep sleep */ wait_loop(500); - TIM_HandleTypeDef TimMasterHandle; - TimMasterHandle.Instance = TIM_MST; - __HAL_TIM_SET_COUNTER(&TimMasterHandle, EnterTimeUS); + restore_timer_ctx(); -#if DEVICE_RTC - /* Wait for RTC RSF bit synchro if RTC is configured */ -#if (TARGET_STM32F2) || (TARGET_STM32F4) || (TARGET_STM32F7) - if (READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL)) { -#else /* (TARGET_STM32F2) || (TARGET_STM32F4) || (TARGET_STM32F7) */ - if (__HAL_RCC_GET_RTC_SOURCE()) { -#endif /* (TARGET_STM32F2) || (TARGET_STM32F4) || (TARGET_STM32F7) */ - rtc_synchronize(); - } -#endif // Enable IRQs - core_util_critical_section_exit(); + core_util_critical_section_exit(); } #endif