STM32WB: update deep sleep sequence

Review HSE clock initialization to match with latest CUBE firmware.
Also there is no need to set the full clock tree again after deep sleep exit.

With this change we get a stable deep sleep mode (when allowed by CORDIO stack).
pull/9814/head
Laurent Meunier 2019-03-26 14:47:50 +01:00
parent b21110d6b8
commit 718b16545c
3 changed files with 196 additions and 157 deletions

View File

@ -34,6 +34,8 @@
#include "stm32wbxx.h"
#include "mbed_error.h"
#include "stm32wbxx_ll_hsem.h"
#include "stm32wbxx_ll_hsem.h"
#include "otp.h"
#include "hw_conf.h" /* Common BLE file where BLE shared resources are defined */
// Clock source is selected with CLOCK_SOURCE in json config
@ -56,7 +58,59 @@ uint8_t SetSysClock_PLL_HSI(void);
uint8_t SetSysClock_PLL_MSI(void);
#endif /* ((CLOCK_SOURCE) & USE_PLL_MSI) */
void Configure_RF_Clock_Sources(void);
static void Configure_RF_Clock_Sources(void)
{
static uint8_t RF_ON = 0;
if ( !RF_ON ) {
// Reset backup domain
if ((LL_RCC_IsActiveFlag_PINRST()) && (!LL_RCC_IsActiveFlag_SFTRST())) {
// Write twice the value to flush the APB-AHB bridge
// This bit shall be written in the register before writing the next one
HAL_PWR_EnableBkUpAccess();
HAL_PWR_EnableBkUpAccess();
__HAL_RCC_BACKUPRESET_FORCE();
__HAL_RCC_BACKUPRESET_RELEASE();
}
/**
* Select LSE clock
*/
LL_RCC_LSE_Enable();
while (!LL_RCC_LSE_IsReady());
/**
* Select wakeup source of BLE RF
*/
LL_RCC_SetRFWKPClockSource(LL_RCC_RFWKP_CLKSOURCE_LSE);
/**
* Switch OFF LSI
*/
LL_RCC_LSI1_Disable();
RF_ON = 1;
}
return;
}
static void Config_HSE(void)
{
OTP_ID0_t * p_otp;
/**
* Read HSE_Tuning from OTP
*/
p_otp = (OTP_ID0_t *) OTP_Read(0);
if (p_otp)
{
LL_RCC_HSE_SetCapacitorTuning(p_otp->hse_tuning);
}
return;
}
/**
* @brief Configures the System clock source, PLL Multiplier and Divider factors, AHB/APBx prescalers
@ -112,43 +166,69 @@ void SetSysClock(void)
/******************************************************************************/
uint8_t SetSysClock_PLL_HSE(uint8_t bypass)
{
LL_RCC_HSE_Enable();
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
/**
* Switch to HSE as Sys clok source
* All Peripehrals (HCLK, HCLK2, HCLK4, PCLK1, PCLK2) will be clocked
* @ 32MHZ. This is not optimal but a stable setting for enter and exit
* deep sleep mode (STOP mode).
*
*/
while(!LL_RCC_HSE_IsReady());
LL_RCC_SetSysClkSource( LL_RCC_SYS_CLKSOURCE_HSE );
while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE);
Config_HSE();
/**
* Set RNG on HSI48
*/
LL_RCC_HSI48_Enable();
while (!LL_RCC_HSI48_IsReady());
LL_RCC_SetCLK48ClockSource(LL_RCC_CLK48_CLKSOURCE_HSI48);
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI1
|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
return 0; // FAIL
}
/** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK4|RCC_CLOCKTYPE_HCLK2
|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.AHBCLK2Divider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLK4Divider = RCC_SYSCLK_DIV1;
/**
* Switch OFF MSI and HSI
*/
LL_RCC_MSI_Disable();
LL_RCC_HSI_Disable();
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
return 0; // FAIL
}
/** Initializes the peripherals clocks
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SMPS|RCC_PERIPHCLK_RFWAKEUP
|RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USART1
|RCC_PERIPHCLK_LPUART1;
PeriphClkInitStruct.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
PeriphClkInitStruct.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK1;
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
PeriphClkInitStruct.RFWakeUpClockSelection = RCC_RFWKPCLKSOURCE_LSI;
PeriphClkInitStruct.SmpsClockSelection = RCC_SMPSCLKSOURCE_HSE;
PeriphClkInitStruct.SmpsDivSelection = RCC_SMPSCLKDIV_RANGE0;
// Output clock on MCO1 pin(PA8) for debugging purpose
#if DEBUG_MCO == 2
if (bypass == 0) {
HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_4); // 8 MHz
} else {
HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_2); // 4 MHz
}
#endif
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
return 0; // FAIL
}
return 1;
/**
* Select HSI as system clock source after Wake Up from Stop mode
*/
LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI);
return 1;
}
#endif /* ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) */
#if ((CLOCK_SOURCE) & USE_PLL_HSI)
@ -271,33 +351,3 @@ uint8_t SetSysClock_PLL_MSI(void)
}
#endif /* ((CLOCK_SOURCE) & USE_PLL_MSI) */
void Configure_RF_Clock_Sources(void)
{
// Reset backup domain
if ((LL_RCC_IsActiveFlag_PINRST()) && (!LL_RCC_IsActiveFlag_SFTRST())) {
// Write twice the value to flush the APB-AHB bridge
// This bit shall be written in the register before writing the next one
HAL_PWR_EnableBkUpAccess();
HAL_PWR_EnableBkUpAccess();
__HAL_RCC_BACKUPRESET_FORCE();
__HAL_RCC_BACKUPRESET_RELEASE();
}
/**
* Select LSE clock
*/
LL_RCC_LSE_Enable();
while (!LL_RCC_LSE_IsReady());
/**
* Select wakeup source of BLE RF
*/
LL_RCC_SetRFWKPClockSource(LL_RCC_RFWKP_CLKSOURCE_LSE);
/**
* Switch OFF LSI
*/
LL_RCC_LSI1_Disable();
return;
}

View File

@ -191,55 +191,53 @@ void SystemInit(void)
{
OTP_ID0_t * p_otp;
/* FPU settings ------------------------------------------------------------*/
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
SCB->CPACR |= ((3UL << (10UL*2UL))|(3UL << (11UL*2UL))); /* set CP10 and CP11 Full Access */
#endif
/**
* Read HSE_Tuning from OTP
*/
p_otp = (OTP_ID0_t *) OTP_Read(0);
if (p_otp)
{
LL_RCC_HSE_SetCapacitorTuning(p_otp->hse_tuning);
}
/* Reset the RCC clock configuration to the default reset state ------------*/
LL_RCC_HSE_Enable();
/* Set MSION bit */
RCC->CR |= RCC_CR_MSION;
/**
* Set FLASH latency to 1WS
*/
LL_FLASH_SetLatency( LL_FLASH_LATENCY_1 );
while( LL_FLASH_GetLatency() != LL_FLASH_LATENCY_1 );
/* Reset CFGR register */
RCC->CFGR = 0x00070000U;
/**
* Switch to HSE
*
*/
while(!LL_RCC_HSE_IsReady());
LL_RCC_SetSysClkSource( LL_RCC_SYS_CLKSOURCE_HSE );
while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE);
/* Reset PLLSAI1ON, PLLON, HSECSSON, HSEON, HSION, and MSIPLLON bits */
RCC->CR &= (uint32_t)0xFAF6FEFBU;
/**
* Switch OFF MSI
*/
LL_RCC_MSI_Disable();
/*!< Reset LSI1 and LSI2 bits */
RCC->CSR &= (uint32_t)0xFFFFFFFAU;
/*!< Reset HSI48ON bit */
RCC->CRRCR &= (uint32_t)0xFFFFFFFEU;
/* Reset PLLCFGR register */
RCC->PLLCFGR = 0x22041000U;
/* Reset PLLSAI1CFGR register */
RCC->PLLSAI1CFGR = 0x22041000U;
/* Reset HSEBYP bit */
RCC->CR &= 0xFFFBFFFFU;
/* Disable all interrupts */
RCC->CIER = 0x00000000;
/* Configure the Vector Table location add offset address ------------------*/
#ifdef CORE_CM0PLUS
/* program in SRAM2A */
#if defined(VECT_TAB_SRAM)
SCB->VTOR = RAM2A_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM2A for CPU2 */
#elif defined(VECT_TAB_SRAM2B)
#elif defined(VECT_TAB_SRAM2B)
/* program in SRAM2B */
SCB->VTOR = RAM2B_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM2B for CPU2 */
#else
#else
/* program in FLASH */
SCB->VTOR = VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif /* Program memory type */
#else
#endif /* Program memory type */
#else
#if defined(VECT_TAB_SRAM)
/* program in SRAM1 */
SCB->VTOR = RAM1_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM1 for CPU1 */
@ -294,78 +292,68 @@ void SystemInit(void)
*/
void SystemCoreClockUpdate(void)
{
uint32_t tmp = 0, msirange = 0, pllvco = 0, pllr = 2, pllsource = 0, pllm = 2;
uint32_t tmp, msirange, pllvco, pllr, pllsource , pllm;
/* Get MSI Range frequency--------------------------------------------------*/
/* Get MSI Range frequency--------------------------------------------------*/
/*MSI frequency range in Hz*/
msirange = MSIRangeTable[(RCC->CR & RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos];
/*MSI frequency range in Hz*/
msirange = MSIRangeTable[(RCC->CR & RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos];
/*SystemCoreClock=HAL_RCC_GetSysClockFreq();*/
/* Get SYSCLK source -------------------------------------------------------*/
switch (RCC->CFGR & RCC_CFGR_SWS)
{
case 0x00: /* MSI used as system clock source */
SystemCoreClock = msirange;
break;
/* Get SYSCLK source -------------------------------------------------------*/
switch (RCC->CFGR & RCC_CFGR_SWS)
{
case 0x00: /* MSI used as system clock source */
SystemCoreClock = msirange;
break;
case 0x04: /* HSI used as system clock source */
/* HSI used as system clock source */
SystemCoreClock = HSI_VALUE;
break;
case 0x04: /* HSI used as system clock source */
/* HSI used as system clock source */
SystemCoreClock = HSI_VALUE;
break;
case 0x08: /* HSE used as system clock source */
SystemCoreClock = HSE_VALUE;
break;
case 0x08: /* HSE used as system clock source */
SystemCoreClock = HSE_VALUE;
break;
case 0x0C: /* PLL used as system clock source */
/* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
case 0x0C: /* PLL used as system clock source */
/* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
SYSCLK = PLL_VCO / PLLR
*/
pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1 ;
*/
pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1UL ;
switch (pllsource)
{
case 0x02: /* HSI used as PLL clock source */
pllvco = (HSI_VALUE / pllm);
break;
if(pllsource == 0x02UL) /* HSI used as PLL clock source */
{
pllvco = (HSI_VALUE / pllm);
}
else if(pllsource == 0x03UL) /* HSE used as PLL clock source */
{
pllvco = (HSE_VALUE / pllm);
}
else /* MSI used as PLL clock source */
{
pllvco = (msirange / pllm);
}
pllvco = pllvco * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1UL);
SystemCoreClock = pllvco/pllr;
break;
case 0x03: /* HSE used as PLL clock source */
pllvco = (HSE_VALUE / pllm);
break;
default: /* MSI used as PLL clock source */
pllvco = (msirange / pllm);
break;
}
pllvco = pllvco * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1);
SystemCoreClock = pllvco/pllr;
break;
default:
SystemCoreClock = msirange;
break;
}
/* Compute HCLK clock frequency --------------------------------------------*/
#ifdef CORE_CM0PLUS
/* Get HCLK2 prescaler */
tmp = AHBPrescTable[((RCC->EXTCFGR & RCC_EXTCFGR_C2HPRE) >> RCC_EXTCFGR_C2HPRE_Pos)];
#else
/* Get HCLK1 prescaler */
tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos)];
#endif
/* HCLK clock frequency */
SystemCoreClock = SystemCoreClock / tmp;
default:
SystemCoreClock = msirange;
break;
}
/* Compute HCLK clock frequency --------------------------------------------*/
/* Get HCLK1 prescaler */
tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos)];
/* HCLK clock frequency */
SystemCoreClock = SystemCoreClock / tmp;
}
/**
* @}
*/

View File

@ -43,7 +43,6 @@ extern void save_timer_ctx(void);
extern void restore_timer_ctx(void);
extern int serial_is_tx_ongoing(void);
extern int mbed_sdk_inited;
extern void SetSysClock(void);
static void Switch_On_HSI( void )
{
@ -63,6 +62,11 @@ static void LPM_EnterStopMode(void)
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() )
@ -173,9 +177,6 @@ void hal_deepsleep(void)
HW_LPM_StopMode();
LPM_ExitStopMode();
/* After wake-up from STOP reconfigure the whole clock tree */
SetSysClock();
restore_timer_ctx();
/* us_ticker context restored, allow HAL_GetTick() to read the us_ticker