diff --git a/targets/TARGET_STM/TARGET_STM32WB/STM32Cube_FW/stm32_lpm_if.c b/targets/TARGET_STM/TARGET_STM32WB/STM32Cube_FW/stm32_lpm_if.c new file mode 100644 index 0000000000..1adfc4d915 --- /dev/null +++ b/targets/TARGET_STM/TARGET_STM32WB/STM32Cube_FW/stm32_lpm_if.c @@ -0,0 +1,264 @@ +/* USER CODE BEGIN Header */ +/** + *************************************************************************************** + * File Name : stm32_lpm_if.c + * Description : Low layer function to enter/exit low power modes (stop, sleep). + *************************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32wbxx_ll_hsem.h" +#include "stm32wbxx_ll_cortex.h" +#include "app_conf.h" +/* USER CODE BEGIN include */ + +/* USER CODE END include */ + +/* Exported variables --------------------------------------------------------*/ + +/* Private function prototypes -----------------------------------------------*/ +static void Switch_On_HSI( void ); +/* USER CODE BEGIN Private_Function_Prototypes */ + +/* USER CODE END Private_Function_Prototypes */ +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN Private_Typedef */ + +/* USER CODE END Private_Typedef */ +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN Private_Define */ + +/* USER CODE END Private_Define */ +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN Private_Macro */ + +/* USER CODE END Private_Macro */ +/* Private variables ---------------------------------------------------------*/ +/* USER CODE BEGIN Private_Variables */ + +/* USER CODE END Private_Variables */ + +/* Functions Definition ------------------------------------------------------*/ +/** + * @brief Enters Low Power Off Mode + * @param none + * @retval none + */ +void PWR_EnterOffMode( void ) +{ +/* USER CODE BEGIN PWR_EnterOffMode */ + /************************************************************************************ + * ENTER OFF MODE + ***********************************************************************************/ + /* + * There is no risk to clear all the WUF here because in the current implementation, this API is called + * in critical section. If an interrupt occurs while in that critical section before that point, + * the flag is set and will be cleared here but the system will not enter Off Mode + * because an interrupt is pending in the NVIC. The ISR will be executed when moving out + * of this critical section + */ + LL_PWR_ClearFlag_WU( ); + + LL_PWR_SetPowerMode( LL_PWR_MODE_STANDBY ); + + LL_LPM_EnableDeepSleep( ); /**< Set SLEEPDEEP bit of Cortex System Control Register */ + + /** + * This option is used to ensure that store operations are completed + */ +#if defined ( __CC_ARM) + __force_stores( ); +#endif + + __WFI( ); +/* USER CODE END PWR_EnterOffMode */ +} + +/** + * @brief Exits Low Power Off Mode + * @param none + * @retval none + */ +void PWR_ExitOffMode( void ) +{ +/* USER CODE BEGIN PWR_ExitOffMode */ + +/* USER CODE END PWR_ExitOffMode */ +} + +/** + * @brief Enters Low Power Stop Mode + * @note ARM exists the function when waking up + * @param none + * @retval none + */ +void PWR_EnterStopMode( void ) +{ +/* USER CODE BEGIN PWR_EnterStopMode */ + /** + * This function is called from CRITICAL SECTION + */ + while( LL_HSEM_1StepLock( HSEM, CFG_HW_RCC_SEMID ) ); + + if ( ! LL_HSEM_1StepLock( HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID ) ) + { + if( LL_PWR_IsActiveFlag_C2DS( ) ) + { + /* Release ENTRY_STOP_MODE semaphore */ + LL_HSEM_ReleaseLock( HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0 ); + + /** + * The switch on HSI before entering Stop Mode is required on Cut2.0 + * It is useless from Cut2.1 + */ + Switch_On_HSI( ); + } + } + else + { + /** + * The switch on HSI before entering Stop Mode is required on Cut2.0 + * It is useless from Cut2.1 + */ + Switch_On_HSI( ); + } + + /* Release RCC semaphore */ + LL_HSEM_ReleaseLock( HSEM, CFG_HW_RCC_SEMID, 0 ); + + /************************************************************************************ + * ENTER STOP MODE + ***********************************************************************************/ + LL_PWR_SetPowerMode( LL_PWR_MODE_STOP2 ); + + LL_LPM_EnableDeepSleep( ); /**< Set SLEEPDEEP bit of Cortex System Control Register */ + + /** + * This option is used to ensure that store operations are completed + */ +#if defined ( __CC_ARM) + __force_stores( ); +#endif + + __WFI(); +/* USER CODE END PWR_EnterStopMode */ +} + +/** + * @brief Exits Low Power Stop Mode + * @note Enable the pll at 32MHz + * @param none + * @retval none + */ +void PWR_ExitStopMode( void ) +{ +/* USER CODE BEGIN PWR_ExitStopMode */ + /** + * This function is called from CRITICAL SECTION + */ + + /* Release ENTRY_STOP_MODE semaphore */ + LL_HSEM_ReleaseLock( HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0 ); + + while( LL_HSEM_1StepLock( HSEM, CFG_HW_RCC_SEMID ) ); + + if(LL_RCC_GetSysClkSource( ) == LL_RCC_SYS_CLKSOURCE_STATUS_HSI) + { + LL_RCC_HSE_Enable( ); + while(!LL_RCC_HSE_IsReady( )); + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE); + while (LL_RCC_GetSysClkSource( ) != LL_RCC_SYS_CLKSOURCE_STATUS_HSE); + } + else + { + /** + * As long as the current application is fine with HSE as system clock source, + * there is nothing to do here + */ + } + + /* Release RCC semaphore */ + LL_HSEM_ReleaseLock( HSEM, CFG_HW_RCC_SEMID, 0 ); +/* USER CODE END PWR_ExitStopMode */ +} + +/** + * @brief Enters Low Power Sleep Mode + * @note ARM exits the function when waking up + * @param none + * @retval none + */ +void PWR_EnterSleepMode( void ) +{ +/* USER CODE BEGIN PWR_EnterSleepMode */ + + HAL_SuspendTick(); + + /************************************************************************************ + * ENTER SLEEP MODE + ***********************************************************************************/ + LL_LPM_EnableSleep( ); /**< Clear SLEEPDEEP bit of Cortex System Control Register */ + + /** + * This option is used to ensure that store operations are completed + */ +#if defined ( __CC_ARM) + __force_stores(); +#endif + + __WFI( ); +/* USER CODE END PWR_EnterSleepMode */ +} + +/** + * @brief Exits Low Power Sleep Mode + * @note ARM exits the function when waking up + * @param none + * @retval none + */ +void PWR_ExitSleepMode( void ) +{ +/* USER CODE BEGIN PWR_ExitSleepMode */ + + HAL_ResumeTick(); + +/* USER CODE END PWR_ExitSleepMode */ +} + +/************************************************************* + * + * LOCAL FUNCTIONS + * + *************************************************************/ +/** + * @brief Switch the system clock on HSI + * @param none + * @retval none + */ +static void Switch_On_HSI( void ) +{ + LL_RCC_HSI_Enable( ); + while(!LL_RCC_HSI_IsReady( )); + LL_RCC_SetSysClkSource( LL_RCC_SYS_CLKSOURCE_HSI ); + LL_RCC_SetSMPSClockSource(LL_RCC_SMPS_CLKSOURCE_HSI); + while (LL_RCC_GetSysClkSource( ) != LL_RCC_SYS_CLKSOURCE_STATUS_HSI); +} + +/* USER CODE BEGIN Private_Functions */ + +/* USER CODE END Private_Functions */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/targets/TARGET_STM/TARGET_STM32WB/STM32Cube_FW/stm32_lpm_if.h b/targets/TARGET_STM/TARGET_STM32WB/STM32Cube_FW/stm32_lpm_if.h new file mode 100644 index 0000000000..d8e67947fe --- /dev/null +++ b/targets/TARGET_STM/TARGET_STM32WB/STM32Cube_FW/stm32_lpm_if.h @@ -0,0 +1,81 @@ +/* USER CODE BEGIN Header */ +/** +****************************************************************************** +* @file stm32_lpm_if.h +* @brief Header for stm32_lpm_if.c module (device specific LP management) +****************************************************************************** +* @attention +* +*

© Copyright (c) 2019 STMicroelectronics. +* All rights reserved.

+* +* This software component is licensed by ST under BSD 3-Clause license, +* the "License"; You may not use this file except in compliance with the +* License. You may obtain a copy of the License at: +* opensource.org/licenses/BSD-3-Clause +* +****************************************************************************** +*/ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32_LPM_IF_H +#define __STM32_LPM_IF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ + +/** + * @brief Enters Low Power Off Mode + * @param none + * @retval none + */ +void PWR_EnterOffMode( void ); +/** + * @brief Exits Low Power Off Mode + * @param none + * @retval none + */ +void PWR_ExitOffMode( void ); + +/** + * @brief Enters Low Power Stop Mode + * @note ARM exists the function when waking up + * @param none + * @retval none + */ +void PWR_EnterStopMode( void ); +/** + * @brief Exits Low Power Stop Mode + * @note Enable the pll at 32MHz + * @param none + * @retval none + */ +void PWR_ExitStopMode( void ); + +/** + * @brief Enters Low Power Sleep Mode + * @note ARM exits the function when waking up + * @param none + * @retval none + */ +void PWR_EnterSleepMode( void ); + +/** + * @brief Exits Low Power Sleep Mode + * @note ARM exits the function when waking up + * @param none + * @retval none + */ +void PWR_ExitSleepMode( void ); + +#ifdef __cplusplus +} +#endif + +#endif /*__STM32_LPM_IF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/targets/TARGET_STM/TARGET_STM32WB/wb_sleep.c b/targets/TARGET_STM/TARGET_STM32WB/wb_sleep.c index 404571f5a6..3515bf5907 100644 --- a/targets/TARGET_STM/TARGET_STM32WB/wb_sleep.c +++ b/targets/TARGET_STM/TARGET_STM32WB/wb_sleep.c @@ -17,116 +17,22 @@ #if DEVICE_SLEEP -#include "sleep_api.h" -#include "us_ticker_api.h" -#include "us_ticker_data.h" #include "mbed_critical.h" -#include "mbed_error.h" -#include "stm32wbxx_ll_hsem.h" -#include "stm32wbxx_ll_cortex.h" -#include "hw_conf.h" /* Common BLE file where BLE shared resources are defined */ extern void save_timer_ctx(void); extern void restore_timer_ctx(void); extern int serial_is_tx_ongoing(void); +extern void PWR_EnterStopMode(void); +extern void PWR_ExitStopMode(void); + + extern int mbed_sdk_inited; -static void Switch_On_HSI(void) -{ - LL_RCC_HSI_Enable(); - while (!LL_RCC_HSI_IsReady()); - LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI); - while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI); - - return; -} - -static void LPM_EnterStopMode(void) -{ - /** - * This function is called from CRITICAL SECTION - */ - - while (LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID)); - - /** - * Select HSI as system clock source after Wake Up from Stop mode - */ - LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI); - - if (! LL_HSEM_1StepLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID)) { - if (LL_PWR_IsActiveFlag_C2DS()) { - /* Release ENTRY_STOP_MODE semaphore */ - LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0); - - Switch_On_HSI(); - } - } else { - Switch_On_HSI(); - } - - /* Release RCC semaphore */ - LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0); - - return; -} - -static void LPM_ExitStopMode(void) -{ - /** - * This function is called from CRITICAL SECTION - */ - - /* Release ENTRY_STOP_MODE semaphore */ - LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0); - - if ((LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_HSI) || (LL_PWR_IsActiveFlag_C1STOP() != 0)) { - LL_PWR_ClearFlag_C1STOP_C1STB(); - - while (LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID)); - - if (LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_HSI) { - LL_RCC_HSE_Enable(); - while (!LL_RCC_HSE_IsReady()); - LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE); - while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE); - } else { - /** - * As long as the current application is fine with HSE as system clock source, - * there is nothing to do here - */ - } - - /* Release RCC semaphore */ - LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0); - } - - return; -} - -void HW_LPM_StopMode(void) -{ - LL_PWR_SetPowerMode(LL_PWR_MODE_STOP2); - - LL_LPM_EnableDeepSleep(); /**< Set SLEEPDEEP bit of Cortex System Control Register */ - - /** - * This option is used to ensure that store operations are completed - */ -#if defined ( __CC_ARM) - __force_stores(); -#endif - - __WFI(); - - return; -} - /* STM32WB has very specific needs to handling STOP mode. * The target has a cortex-M4 and cortex-M0 and needs to * handle shared ressources btw both cores. * Each core can sleep independantly, but the first one that - * wkaes-up needs to restore the clock tree. + * wakes-up needs to restore the clock tree. */ void hal_deepsleep(void) { @@ -149,12 +55,8 @@ void hal_deepsleep(void) * us_ticker timestamp until the us_ticker context is restored. */ mbed_sdk_inited = 0; - /** - * Enter the STOP mode - */ - LPM_EnterStopMode(); - HW_LPM_StopMode(); - LPM_ExitStopMode(); + PWR_EnterStopMode(); + PWR_ExitStopMode(); restore_timer_ctx(); @@ -166,5 +68,4 @@ void hal_deepsleep(void) core_util_critical_section_exit(); } - #endif