Hi,
I used Cube example to wake the processor (STM32L476) from stop mode 2.
I use HSI for the LPUART, MSI as wakeup clock.
The processor doesn't wake at all from stop mode, and I can't figure out why.
Here is my code:
Main
int main(void)
{HAL_Init();
/* Configure the system clock */
SystemClock_Config();MX_GPIO_Init();
MX_DMA_Init();LED_Init();
MX_LPUART1_UART_Init();LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_MSI);
/* Infinite loop */
while (1)
{
volatile static uint8_t test_byte = 0;LED_Blinking_3s();
while (!test_byte);
/* Prepare LPUART for entering Stop Mode */
PrepareLpuartToStopMode();
/* Enter Stop mode 2 */
EnterStop2Mode();test_byte = 0;
}
}
Clock configuration:
/** System Clock Configuration
*/
void SystemClock_Config(void)
{LL_FLASH_SetLatency(LL_FLASH_LATENCY_3);
if (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_3)
Error_Handler();LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
LL_RCC_HSI_Enable();
/* Wait till HSI is ready */
while (LL_RCC_HSI_IsReady() != 1)
{}
LL_RCC_HSI_SetCalibTrimming(16);
LL_RCC_LSI_Enable();
/* Wait till LSI is ready */
while (LL_RCC_LSI_IsReady() != 1)
{}
LL_RCC_MSI_Enable();
/* Wait till MSI is ready */
while (LL_RCC_MSI_IsReady() != 1)
{}
LL_RCC_MSI_EnablePLLMode();
LL_RCC_MSI_EnableRangeSelection();
LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_11);
LL_RCC_MSI_SetCalibTrimming(0);
LL_PWR_EnableBkUpAccess();
LL_RCC_ForceBackupDomainReset();
LL_RCC_ReleaseBackupDomainReset();
LL_RCC_LSE_SetDriveCapability(LL_RCC_LSEDRIVE_LOW);
LL_RCC_LSE_Enable();
/* Wait till LSE is ready */
while (LL_RCC_LSE_IsReady() != 1)
{}
LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
LL_RCC_EnableRTC();
HAL_RCCEx_EnableLSECSS_IT();
LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_MSI, LL_RCC_PLLM_DIV_6, 20, LL_RCC_PLLR_DIV_2);
LL_RCC_PLL_EnableDomain_SYS();
LL_RCC_PLL_Enable();
/* Wait till PLL is ready */
while (LL_RCC_PLL_IsReady() != 1)
{}
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI); //LL_RCC_SYS_CLKSOURCE_PLL);
/* Wait till System clock is ready */
while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI) //LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
{}
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
LL_Init1msTick(48000000); //80000000);
LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK);
LL_SetSystemCoreClock(48000000); //80000000);
LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_HSI);
LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_PCLK1);
LL_RCC_SetI2CClockSource(LL_RCC_I2C3_CLKSOURCE_PCLK1);
LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE_LSE);
LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_MSI);
LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_SYSCLK);
/* SysTick_IRQn interrupt configuration */
NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
}
LPUART Init:
void MX_LPUART1_UART_Init(void)
{
LL_LPUART_InitTypeDef LPUART_InitStruct;LL_GPIO_InitTypeDef GPIO_InitStruct;
/* Peripheral clock enable */
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPUART1);
/**LPUART1 GPIO Configuration
PB13 ------> LPUART1_CTS
PB10 ------> LPUART1_RX
PB11 ------> LPUART1_TX
PB12 ------> LPUART1_RTS
*/
GPIO_InitStruct.Pin = LL_GPIO_PIN_13|LL_GPIO_PIN_12;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_8;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);GPIO_InitStruct.Pin = LL_GPIO_PIN_10|LL_GPIO_PIN_11;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
GPIO_InitStruct.Alternate = LL_GPIO_AF_8;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);/* LPUART1 DMA Init */
/* LPUART_TX Init */
LL_DMA_SetPeriphRequest(DMA2, LL_DMA_CHANNEL_6, LL_DMA_REQUEST_4);LL_DMA_SetDataTransferDirection(DMA2, LL_DMA_CHANNEL_6, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
LL_DMA_SetChannelPriorityLevel(DMA2, LL_DMA_CHANNEL_6, LL_DMA_PRIORITY_MEDIUM);
LL_DMA_SetMode(DMA2, LL_DMA_CHANNEL_6, LL_DMA_MODE_NORMAL);
LL_DMA_SetPeriphIncMode(DMA2, LL_DMA_CHANNEL_6, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_CHANNEL_6, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA2, LL_DMA_CHANNEL_6, LL_DMA_PDATAALIGN_BYTE);
LL_DMA_SetMemorySize(DMA2, LL_DMA_CHANNEL_6, LL_DMA_MDATAALIGN_BYTE);
/* LPUART1 interrupt Init */
NVIC_SetPriority(LPUART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(LPUART1_IRQn);LPUART_InitStruct.BaudRate = 115200;
LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_8B;
LPUART_InitStruct.StopBits = LL_LPUART_STOPBITS_1;
LPUART_InitStruct.Parity = LL_LPUART_PARITY_NONE;
LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX;
LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE; //LL_LPUART_HWCONTROL_RTS_CTS;
LL_LPUART_Init(LPUART1, &LPUART_InitStruct);LL_LPUART_EnableIT_RXNE(LPUART1);
/* Set the wake-up event type : specify wake-up on RXNE flag */
LL_LPUART_SetWKUPType(LPUART1, LL_LPUART_WAKEUP_ON_RXNE);LL_LPUART_Enable(LPUART1);
}
Preparing the UART for entering stop mode:
void PrepareLpuartToStopMode(void)
{
uint8_t dummy_byte;/* Empty RX Fifo before entering Stop mode 2 (Otherwise, characters already present in FIFO
will lead to immediate wake up */
while (LL_LPUART_IsActiveFlag_RXNE(LPUART1))
{
/* Read Received character. RXNE flag is cleared by reading of RDR register */
dummy_byte = LL_LPUART_ReceiveData8(LPUART1);
}/* Clear OVERRUN flag */
LL_LPUART_ClearFlag_ORE(LPUART1);/* Make sure that no LPUART transfer is on-going */
while(LL_LPUART_IsActiveFlag_BUSY(LPUART1) == 1)
{
}
/* Make sure that LPUART is ready to receive */
while(LL_LPUART_IsActiveFlag_REACK(LPUART1) == 0)
{
}/* Configure LPUART1 transfer interrupts : */
/* Clear WUF flag and enable the UART Wake Up from stop mode Interrupt */
LL_LPUART_ClearFlag_WKUP(LPUART1);
LL_LPUART_EnableIT_WKUP(LPUART1);/* Enable Wake Up From Stop */
LL_LPUART_EnableInStopMode(LPUART1);UNUSED(dummy_byte);
}
Entering stop mode function:
static void EnterStop2Mode(void)
{
/** Request to enter Stop mode 2
* Following procedure describe in STM32L4xx Reference Manual
* See PWR part, section Low-power modes, Stop mode 2
*/
/* Set STOP 2 mode when CPU enters deepsleep */
LL_PWR_SetPowerMode(LL_PWR_MODE_STOP2);/* Set SLEEPDEEP bit of Cortex System Control Register */
LL_LPM_EnableDeepSleep();/* Request Wait For Interrupt */
__WFI();
}
Update: Adding the ISR code:
void LPUART1_IRQHandler(void)
{
/* USER CODE BEGIN LPUART1_IRQn 0 */
/* Check WUF flag value in ISR register */
if(LL_LPUART_IsActiveFlag_WKUP(LPUART1) && LL_LPUART_IsEnabledIT_WKUP(LPUART1))
{
LL_RCC_HSI_Enable();
/* Wait till HSI is ready */
while(LL_RCC_HSI_IsReady() != 1)
{
}/* Configure LPUART1 transfer interrupts : */
/* Disable the UART Wake UP from stop mode Interrupt */
LL_LPUART_DisableIT_WKUP(LPUART1);/* WUF flag clearing */
LL_LPUART_ClearFlag_WKUP(LPUART1);
/* Call function in charge of handling Character reception */
LPUART1->TDR = LPUART1->RDR;
}
else if (LL_LPUART_IsActiveFlag_RXNE(LPUART1))
{
LPUART1->TDR = LPUART1->RDR;}
/* USER CODE END LPUART1_IRQn 0 */
/* USER CODE BEGIN LPUART1_IRQn 1 *//* USER CODE END LPUART1_IRQn 1 */
}
Thanks for your help