2018-10-11 12:14 AM
Hi. I am interfacing GSM module with STM32L432kc MCU. I am using UART receive interrupt to receive data from GSM and it's working fine. But at some instance UART receive interrupt is not called even when there is data on UART Receive line. Below I am sharing UART RX interrupt function code.
Thanks
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1)
{
HAL_UART_Receive_IT(&huart1, &rx_data, 1); //Receive data(One character one time).
GSM_rx_buffer[rx_index++] = rx_data;
if(rx_index == 100)
rx_index = 0;
}
}
2018-10-11 12:53 AM
With an overflow, or another reception error. You need to clear those errors flags first.
Not a Cube user, though.
I just used to check for error flags, and clear all if any was set.
2018-10-11 01:45 AM
Don't observe the USART registers in debugger while the program is running.
JW
2018-10-11 02:03 AM
Code looks to create a race condition for itself. You might want to check if any of the calls are throwing off an error condition, or if the USART is flagging something.
2018-10-11 09:21 AM
A few things:
(1) HAL_UART_Receive_IT() disables the UART interrupts after it receives how ever many bytes you tell it to receive. It then calls HAL_UART_RcCpltCallback(). Your next call to HAL_UART_Receive_IT() re-initialized the UART receive interrupts. So depending your your baud rate and how heavily loaded your CPU is, the time between stopping the UART receive and re-starting it may cause the UART to miss the start bit of the next byte.
(2) Call HAL_UART_Receive_IT() *after* you store the contents of rx_data into your buffer. Gets rid of the possible race condition.
(3) Provide a HAL_UART_ErrorCallback() function to see if you are getting any receive errors (parity, framing, etc.).
Even better, use DMA in circular mode storing bytes into a temporary buffer. Then have your main code extract bytes from that buffer into your GSM buffer. This can be polled in the main loop, or in some periodic timer interrupt (system tick??).
2018-10-12 01:11 AM
@Community member Hi. How to clear error flags and access peripheral level registers to check the flag status. Currently I am using Eclipse ide and cubeMx to generate the code so, I am calling predefined APIs to configure UART and to receive data or transmit data.
Thanks
2018-10-12 01:28 AM
As an SPL-based example on the F407, I used the following sequence:
if (USART_GetITStatus (USART3, USART_IT_ORE) != RESET)
{
databyte = USART3->SR;
databyte = USART3->DR;
}
According to the F40x Reference Manual, which says:
ORE: Overrun error
This bit is set by hardware when the word currently being received in the shift register is ready to be transferred into the RDR register while RXNE=1. An interrupt is generated if RXNEIE=1 in the USART_CR1 register. It is cleared by a software sequence (an read to the USART_SR register followed by a read to the USART_DR register).
I have not worked with the L4xx yet, and not with CubeMX.
2018-10-12 02:00 AM
Or you simply read in USART3->SR to a variable and then check individual flags as per the USART_SR description in USART chapter of the Reference Manual. Anyway, USART_GetITStatus from SPL does not anything other than reads that register and preforms an & with the mask constant for given flag.
JW
2018-10-12 02:14 AM
> Anyway, USART_GetITStatus from SPL does not anything other than reads that register and preforms an & with the mask constant for given flag.
I actually do that, in most cases. If one character is lost, there is no much fussing about the why, I just clear all error flags. Otherwise, you do the very same thing for each of the error flags.
The advantage of SPL code is "speaking names", (usually) making clear the intention of the coder.
And yet another advantage - the SPL never promised to relieve the user from reading the Reference Manual ... ;)