2024-10-31 01:03 AM - last edited on 2024-10-31 01:16 AM by Andrew Neil
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
2024-11-01 05:52 AM
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.
2024-11-03 04:42 PM
External EXTI can be used independently, but when the RX configuration of the serial port is set to EXTI, there will be problems
2024-11-04 01:50 AM
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.
2024-11-04 04:41 PM
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
2024-11-05 01:15 AM
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.
2024-11-05 01:58 AM
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