STM32WB align deepsleep functions with CubeFW

pull/12384/head
jeromecoutant 2020-02-04 15:46:37 +01:00
parent f0370222d8
commit ebae0e56d4
3 changed files with 352 additions and 106 deletions

View File

@ -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
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* 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****/

View File

@ -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
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* 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****/

View File

@ -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