4
votes

I see HAL provides the following function for receiving serial data with interrupts: HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
which basically setups rx interrupts and returns.
HAL_UART_RxCpltCallback() will be called once the amount of bytes received reaches Size.
HAL disables rx interrupts just before executing this callback

Problem:
The amount of incoming bytes will be variable (from 1 to ~100) and I need to put them into a ring buffer.
So I set Size to 1 and call HAL_UART_Receive_IT() again inside the callback to re-enable interrupts, and it works well if the board gets sent 1 or 2 bytes every now and then, but bytes are missed beyond that

My guess is they are missed because they arrive between interrupt disabling - enabling

Is there a way to keep interrupts running forever without overwriting HAL Cube generated code?
If not, what would be a clean way of overwriting the involved functions?
Is there something I'm missing that would avoid the need to find this solution?

4
This seems to be a known problem without an easy solution: stackoverflow.com/questions/24875873/stm32f4-uart-hal-driverRoss Ridge
Seems like DMA is the thing to write data from any peripheral to any memory buffer including ring buffer (DMA settings). And DMA interrupts is the easy way to handle all data, or even its half, at the receiving moment.Yuriy
It is not really dependent to your question. But I think it might be worthy to try keil io drivers. Here is the link where you can find them for your mcu keil.com/dd2/packLong Smith

4 Answers

1
votes

Try this

__HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE);
1
votes

Circular buffer with DMA(for receiving)seems to be a solution for your requirement. This will always give RX interrupt(you have to just configure it once).

For similar requirements, usually I'm using a 1 byte circular buffer to handle data. Receive processing will be done in the ISR.

0
votes

I think you have to put a special character to indicate the end of the massage, or you make your own protocol e.g. message header, message length , content , checksum and you make the interrupt enabled for one byte and in the interrupt handler you store the received buffer until you find the last byte in the message and then you send to the main task in case of RTOS, or set a global flag. By the way make sure to set the appropriate receive bytes size in

HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

inside

HAL_UART_RxCpltCallback

please check the return of HAL_UART_Receive_IT it may return error and also implement the

void HAL_UART_ErrorCallback(UART_HandleTypeDef *UartHandle);

and check if there an error in the UART bus.

0
votes

You may try UART via the polling method instead of the interrupt method. Polling method: UART won't return until it received the amount of data specified by the "Size" parameter.