Skip to main content
Graduate
June 5, 2024
Solved

UART fired only once - STM32U5 Custom Board

  • June 5, 2024
  • 4 replies
  • 1697 views

Hello,

I'm working with an STM32U5 custom board.

I use the LPUART1 to read input with an interrupt as shown below and to write it back on the same LPUART1 :

 

 

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
 HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_8);
 HAL_UART_Transmit_IT(huart, (uint8_t *)aRxBuffer, 10);
 HAL_UART_Receive_IT(huart, (uint8_t *)aRxBuffer, 10);
}

 

If I execute the code above, the interrupt is fired only once. I can read text back on my terminal but I never gets executed again.
    This topic has been closed for replies.
    Best answer by Karl Yamashita

    You don't check the HAL status when you call HAL_UART_Receive_IT

    If it returns HAL_BUSY, then you'll never get another interrupt. 

    Avoid doing any non crucial stuff from inside the interrupt. Just set a flag and exit the interrupt. Then in the main while loop you can check the flag and do what you need to do.

    Below is an example for checking HAL status for Rx. I didn't write code for checking the HAL status for the HAL_UART_Transmit_IT as I have a ring buffer that does check it. If you need an example of that, I have a project on Github that you can look at.

     

    #include "main.h"
    
    extern UART_HandleTypeDef hlpuart1;
    
    uint8_t aRxBuffer[10];
    bool dataRdyFlag = false;
    HAL_StatusTypeDef hal_status;
    
    // call before main while loop
    void PollingInit(void)
    {
    	UART_EnableInt();
    }
    
    // called from inside main while loop
    void PollingRoutine(void)
    {
    	UART_CheckRdyFlag();
    	UART_CheckRxStatus();
    }
    
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
    	if(huart == &hlpuart1)
    	{
    		dataRdyFlag = true;
    		UART_EnableInt();
    	}
    }
    
    void UART_CheckRdyFlag(void)
    {
    	if(dataRdyFlag)
    	{
    		dataRdyFlag = false;
    		HAL_UART_Transmit_IT(&hlpuart1, (uint8_t *)aRxBuffer, 10);
    	}
    }
    
    void UART_EnableInt(void)
    {
    	hal_status = HAL_UART_Receive_IT(&hlpuart1, (uint8_t *)aRxBuffer, 10);
    }
    
    void UART_CheckRxStatus(void)
    {
    	if(hal_status != HAL_OK)
    	{
    		UART_EnableInt();
    	}
    }

     

     

     

    4 replies

    Super User
    June 5, 2024

    Implement a HAL_UART_ErrorCallback() function and see if that ever gets called.  If so, see what error flag gets set.

    Graduate II
    June 5, 2024

    You don't check the HAL status when you call HAL_UART_Receive_IT

    If it returns HAL_BUSY, then you'll never get another interrupt. 

    Avoid doing any non crucial stuff from inside the interrupt. Just set a flag and exit the interrupt. Then in the main while loop you can check the flag and do what you need to do.

    Below is an example for checking HAL status for Rx. I didn't write code for checking the HAL status for the HAL_UART_Transmit_IT as I have a ring buffer that does check it. If you need an example of that, I have a project on Github that you can look at.

     

    #include "main.h"
    
    extern UART_HandleTypeDef hlpuart1;
    
    uint8_t aRxBuffer[10];
    bool dataRdyFlag = false;
    HAL_StatusTypeDef hal_status;
    
    // call before main while loop
    void PollingInit(void)
    {
    	UART_EnableInt();
    }
    
    // called from inside main while loop
    void PollingRoutine(void)
    {
    	UART_CheckRdyFlag();
    	UART_CheckRxStatus();
    }
    
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
    	if(huart == &hlpuart1)
    	{
    		dataRdyFlag = true;
    		UART_EnableInt();
    	}
    }
    
    void UART_CheckRdyFlag(void)
    {
    	if(dataRdyFlag)
    	{
    		dataRdyFlag = false;
    		HAL_UART_Transmit_IT(&hlpuart1, (uint8_t *)aRxBuffer, 10);
    	}
    }
    
    void UART_EnableInt(void)
    {
    	hal_status = HAL_UART_Receive_IT(&hlpuart1, (uint8_t *)aRxBuffer, 10);
    }
    
    void UART_CheckRxStatus(void)
    {
    	if(hal_status != HAL_OK)
    	{
    		UART_EnableInt();
    	}
    }

     

     

     

    Graduate II
    June 5, 2024

    Probably want to ponder the repercussions of sending out an active receive buffer.

    As Bob indicates, you should pay attention to function return codes, and perhaps probed deeper as to what errors on the UART would preclude a second go around

    TV79Author
    Graduate
    June 6, 2024

    Thank you all for taking the time to answer my question and for reminding me all these good practices.

     

    And thank you @Karl Yamashita  for the code, this is a much better approach than mine and it work like this.

    I will especially focus on this advice "Avoid doing any non crucial stuff from inside the interrupt. Just set a flag and exit the interrupt. Then in the main while loop you can check the flag and do what you need to do."

     

    Best regards

     

     

     

    Super User
    June 6, 2024

    @TV79 wrote:

    I will especially focus on this advice "Avoid doing any non crucial stuff from inside the interrupt. Just set a flag and exit the interrupt. Then in the main while loop you can check the flag and do what you need to do."


    It is excellent advice, and well worth paying attention to!

     

    Also note @Tesla DeLorean's important advice: "pay attention to function return codes"