AnsweredAssumed Answered

Problem waking from Stop Mode 2 using LPUART

Question asked by Clonimus74 on Nov 7, 2017
Latest reply on Mar 25, 2018 by Clonimus74

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

Outcomes