UART receive interrupt stops triggering after several hours of successful receive
Asked Answered
P

2

5

I am using STM32f4 discovery board connected with xbee to receive temperature data from remote temperature sensor. Code used is CMIS UART example code. I will receive packet data, 1 byte at a time. In other words UART receive interrupt will be called whenever each byte receives. Once I gets the complete packet I will copy the temperature data. My UART callback function works without any issue. But after several hours, UART receive interrupt stops working and UART cannot receive anything. However UART transmission still works. I am using UART1 with baud rate 115200. I have set UART interrupt priority as 0 and no other interrupt shares this priority. All other interrupt priority are lower than UART. Can any one please tell me why UART interrupt stops triggering?

#define PACKET_DELIMETER 0x7E

uint8_t g_frame_ok=0; //flag to indicate complete packet received
uint8_t g_index_of_aoBuf=0; //Index of receive buffer
uint8_t g_aoBuf_of_xbee[100]={0};//Receive Buffer
uint8_t r_byte=0; //Receiving byte 

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *allUartHandle)
{
 __HAL_UART_FLUSH_DRREGISTER(allUartHandle); 

 if(HAL_UART_Receive_IT(allUartHandle, (uint8_t *)&r_byte, 1) == HAL_OK) //Interrupt occurs when each byte arrives
 {
    if(r_byte==PACKET_DELIMETER)
    {
        //start receiving packet
    }
    if( g_index_of_aoBuf>=g_aoBuf_of_xbee[2]+4)
    {
        g_frame_ok=1;
        BSP_LED_On(LED4);
    }           
   }
 }
Pomp answered 1/7, 2015 at 9:3 Comment(4)
If I understood correctly, your code is derived from CMSIS UART example ? Could you include a link to this example ? I never used these APIs, but it really looks like you are doing it horribly wrong...Vehement
I have downloaded example code from this link. st.com/web/en/catalog/tools/PF259243. Example code receive interrupt callback function is different than my code. In example code, receive interrupt will be called for specific amount of buffer size. But in my code receive interrupt will be called for each byte. Can you please tell me whats wrong I am doing here ?Pomp
If the UART peripheral is the same as / similar to the one on the stm32f0 series, you really need to check for overflow and framing errors and "clear" the condition appropriately. Otherwise a single bit error can lock up the peripheral until you reboot. The free software & examples from ST almost never do sufficient error handling for robust production code.Tellurion
did u found the solution of this issue? In my case it stops after 10 - 15 mins only!Saveall
V
5

I never used the API you mention, so I may be wrong, but here are a few things I noticed after taking a look :

HAL_UART_RxCpltCallback is not an UART interrupt. It's a callback from the HAL subsystem that will be called when a receive request you issued is completed. This means it will only be called some time after you issue a receive request. You don't have access to the UART interrupt, and you shouldn't try to mess with it if you use the HAL layer.

About this, HAL_UART_Receive_IT is actually a function that will issue a receive request. It will always return immediately, and it will never receive anything. This means the data in the receive buffer just after the call is not valid. Once you issued the request, HAL_UART_RxCpltCallback will be called anytime after, when the receive is complete. Only at this point the data in the buffer will be valid. To retrieve the data you can use the same variable from the HAL_UART_Receive_IT, but the data buffer will also be available through (UART_HandleTypeDef*)->pRxBuffPtr from the callback parameter.

I think it's OK to call HAL_UART_Receive_IT again in the callback, but it's probably better to do it at the end.

Also, what is __HAL_UART_FLUSH_DRREGISTER used for ? To me it looks like it will do more harm than good.

Vehement answered 1/7, 2015 at 12:25 Comment(0)
H
3

Variables that are shared between a callback function and the rest of the program must be declared as volatile, to prevent the compiler from optimizing the code incorrectly.

You also have to ensure that writes and reads to such variables are atomic, or alternatively protect them with a semaphore. Otherwise you may get race condition bugs.

Either or both of these two classic bugs could cause the problem you describe: both tend to cause intermittent, unexpected behavior which is hard to re-produce.

Also, if your CPU allows it, set a breakpoint which triggers on write access to the interrupt enable register and check the trace.

Homophone answered 1/7, 2015 at 11:25 Comment(3)
In CMSIS, mutex and semaphore cannot be used completely in ISR, and when you use interrupts like dma in uart, you need to read data in the interrupt service routine like HAL_UART_RxCpltCallback function. What is the best solution in this condition?Heraclitus
@Heraclitus Please post it as a new question, not a comment to an old post.Homophone
Ok @Homophone I posted my question here: linkHeraclitus

© 2022 - 2024 — McMap. All rights reserved.