5

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?

Gerard Vuyk
  • 181
  • 1
  • 2
  • 6
  • 1
    This seems to be a known problem without an easy solution: http://stackoverflow.com/questions/24875873/stm32f4-uart-hal-driver – Ross Ridge Apr 16 '16 at 00:00
  • 1
    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 Jan 13 '17 at 00:54
  • 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 https://www.keil.com/dd2/pack/ – Long Smith Feb 11 '17 at 23:00

4 Answers4

2

Try this

__HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE);
Tunaki
  • 132,869
  • 46
  • 340
  • 423
Besnik B
  • 21
  • 2
2

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.

Nithin Kurian
  • 91
  • 2
  • 12
0

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.

Chaos_99
  • 2,284
  • 2
  • 25
  • 29
051026luyaok
  • 191
  • 5
  • 2
    Problem is "Size" is variable and my application is time critical, that's why I went with interrupts in the first place. Got this working by editing HAL function `UART_Receive_IT` so incoming bytes go directly to the ring buffer and interrupts don't get disabled – Gerard Vuyk May 13 '16 at 01:09
0

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.