cancel
Showing results for 
Search instead for 
Did you mean: 

Can STM32L431 configure the RX of the serial port to EXTI wake-up in STOP2 mode?

AlfRomeo
Associate II

Can STM32L431 configure the RX of the serial port to EXTI wake-up in STOP2 mode? Why can't I wake up? And idle interrupts cannot be used either. The manual states that the EXTI and RX pins have been connected together in hardware, but the STOP2 mode cannot wake up the serial port, so it seems that its method cannot be used. Only the most primitive way of configuring RX as EXTI can be used, but it still cannot wake up

Enter STOP2,

 

 

void EnterStop2ModeRTC(void) 
{
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
  __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF);
  __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG();
  __HAL_RTC_TIMESTAMP_CLEAR_FLAG(&hrtc, RTC_FLAG_TSF);
  __HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG();
  while (__HAL_UART_GET_FLAG(&huart3, USART_ISR_BUSY) == SET)
    ;
  while (__HAL_UART_GET_FLAG(&huart3, USART_ISR_REACK) == RESET)
    ;
  setUca3RxToExti();//Configure RX for serial port 3 as EXTI
  HAL_SuspendTick();
  //HAL_DBGMCU_EnableDBGStopMode();
  __HAL_RCC_PWR_CLK_ENABLE();
  HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI); // Enter STOP2
}

 

 

Exit STOP2

 

 

void ExitStop2ModeRTC(void)
{
  SystemClock_Config(); 
  HAL_ResumeTick();
  SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;
}

 

 

Main

 

 

int main()
{
  .....
  .....
  while (1)
  {
    while (getExitLPM3())
    {
      saveData();
      lcdActionPro(); // lcd
      keyActPro();
      // if (uart[_COM3].active)
      // {
      // }
      }
    }
    EnterStop2ModeRTC();
  }
}

 

 

In the function getExitLPM3(), it is determined whether a flag is set. If it is set, it enters the while function inside

EXTI callback function:

 

 

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if ((GPIO_Pin == GPIO_PIN_5))
  {
    ExitStop2ModeRTC();
    HAL_NVIC_DisableIRQ(EXTI9_5_IRQn);
    setUca3RxToRx();
    // uart[_COM3].active = true;
  }
}

 

 

Exited STOP2 mode in the callback function of EXTI and reconfigured the serial port RX pin as the receive pin

 

 

void setUca3RxToExti(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  GPIO_InitStruct.Pin = GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
  uart[_COM3].active = false;
}

void setUca3RxToRx(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  GPIO_InitStruct.Pin = GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  // // HAL_NVIC_SetPriority(USART3_IRQn, 0, 0);
  // // HAL_NVIC_EnableIRQ(USART3_IRQn);
  __HAL_UART_ENABLE_IT(&huart3, UART_IT_RXNE);
  // __HAL_UART_ENABLE_IT(&huart3, UART_IT_RXNE | UART_IT_IDLE);
}

 

 

UART interrupt

 

 

void USER_USART3_IRQHandler(void)
{
  uint8_t data = 0;
  if (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_RXNE) != RESET)
  {
    data = (uint8_t)huart3.Instance->RDR;
    wrEleQueue(&uart[_COM3].Rx, data);
    // uart[_COM3].active = true;
    // bleAppConfig.rxAct = 1;
    // bleAppConfig.tmrResp = bleAppConfig.tmrRxHold = HAL_LPTIM_ReadCounter(&hlptim1);
    // __HAL_UART_CLEAR_FLAG(&huart3, UART_FLAG_RXNE);
  }
  // if (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_IDLE))
  // {
  //   // uart[_COM3].flag = 1;
  //   uart[_COM3].active = false;
  //   __HAL_UART_CLEAR_IDLEFLAG(&huart3);
  // }
}

 

 

There seems to be a logical problem in the middle, but I can't figure it out haha. The flag bit is set to true and will continue to loop in the inner while loop, unable to exit or enter STOP2. However, I don't know where to set it to false. I originally wanted to use IDLE to interrupt during idle, but after using it, I couldn't receive data. Now when not in use, the first packet of data is always incorrect. Can you help me check? Thank you all

6 REPLIES 6
Saket_Om
ST Employee

Hello @AlfRomeo 

 

I tried to configure EXTI interrupt, on RX UART pin with NUCLEO L4 board, to wake up the MCU. The MCU enter and exit the STOP2 mode successfully.  

Please find attached my code. 

If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar

External EXTI can be used independently, but when the RX configuration of the serial port is set to EXTI, there will be problems

Hello @AlfRomeo 

I updated my code to switch from RX USART configuration to EXTI configuration. The MCU go to STOP2 mode and wakeup correctly. 

Please find attached my code.

If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar
int main()
{
  while (1)
  {
    while (bleAppConfig.rxAct)
    {

    }
    SwithToExti();
    HAL_SuspendTick();
    HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
  }
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if ((GPIO_Pin == BLE_RX_Pin))
  {
    HAL_NVIC_DisableIRQ(EXTI9_5_IRQn);
    MX_USART3_UART_Init();
    __HAL_UART_ENABLE_IT(&huart3, UART_IT_RXNE|UART_IT_IDLE);
    bleAppConfig.rxAct = 1;
    SystemClock_Config();
    HAL_ResumeTick();
    SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;
  }
}

void USER_USART3_IRQHandler(void)
{
  uint8_t data = 0;
  if (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_RXNE) != RESET)
  {
    data = (uint8_t)huart3.Instance->RDR;
    wrEleQueue(&uart[_COM3].Rx, data);
    huart3.Instance->TDR = data;
  }
  if (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_IDLE))
  {
    uart[_COM3].flag = 1;
    bleAppConfig.rxAct = 0;
    __HAL_UART_CLEAR_IDLEFLAG(&huart3);
  }
}

Hello, Why can't I wake up when I write like this? And idle interrupts cannot be used either? The first packet of data is always incorrect

Hello @AlfRomeo 

You are switching to EXTI and entering STOP mode in a while loop. The MCU goes to STOP mode and will wake up if an EXTI interrupt occurs. After the execution of the EXTI IRQ handler, it will return to the main loop and re-enter STOP mode again.

To prevent the MCU from immediately re-entering STOP mode after waking up from an EXTI interrupt, you can use a flag that is set in both the UART RX complete callback function and the EXTI callback function. This flag will be checked before entering STOP mode in the main loop.

If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar

I set rxAct to 1 in the EXTI interrupt callback function, prove that the serial port is activated, and then detect the state of the rxAct flag in the inner while loop, if it is always 1, it will not exit in the inner while loop, and it will not enter the stop2 mode, when the custom serial port receiving function accepts a complete frame of data, it will enter the idle interrupt, and the rxAct flag position will be 0 in the idle interrupt, at this time, the while loop of the inner layer will exit, Then it will enter stop2 mode. The logic of the program is probably like this, that is, the first packet of data received is wrong, and a breakpoint is set in the idle interrupt during debugging, and only one byte of data can be received, and the rest of the bytes are not received