my IT is called after receiving 8 bytes:
HAL_UART_Receive_IT(&huart2, buffer1, 8);
where buffer1 has length 8.
in my callback function I copy the 8 bytes to a seperate buffer2 and empty buffer1 & restart reception. this way i am continuously receiving:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
for(int i=0; i<8; i++){
buffer2[i] = buffer1[i];
buffer1[i] = '\0';
}
HAL_UART_Receive_IT(&huart2, buffer1, 8);
}
Problem: if I enter more than 8 bytes into my serial port, the callback function is executed after 8 bytes, then I get an overrun error and can no longer receive
my behaviour is as follows, IT is called after 8 bytes, then, after the restart i seem to be reading one more byte into my buffer1, after that the error occurs. it seems to me that the reaming bytes are stored somewhere, is there a way to discard the overflow?
i know that the uart function works my buffer1 in a circular manner, my expectation therefore:
example- receiving 10 bytes. IT after 8 bytes restart receive read the remaining 2 bytes.
When you receive 8 chars, your MCU triggers interrupt after each individual character. Your MCU UART has no input buffer, the one and only thing is 1 char sized data register (DR for unified data register or TDR/RDR if they are separate for send/receive). If you had overrun characters, then by definition, all the data that was sent, was lost forever (was never saved anywhere). Your UART is soft-locked until you remove overrun error by reading data register (the act of reading clears overrun flag and unlocks the peripheral as per F103's reference manual, check yours, I'd expect it to be similar or the same).
Basically, the problem is that you never handle overrun error, and it's not very clear from your description what you want to do about it. If you want to discard overrun data and never save it as if it was never sent to MCU, you can clear overrun flag before calling interrupt receive again:
If there was no overrun, it will do nothing at all. If there was an overrun, it will read the first overrun byte that was received while data register was empty (other data was lost), it will clear overrun flag and return the peripheral to operational condition, but if and only if there is no incoming data while calling
HAL_UART_Receive_IT(&huart2, buffer1, 8);
. We could easily have timing issues - let's not forget that MCU executes this in microseconds, while physically UART could still be sending/receiving. So I would modify my solution the following way:void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
Where Busy() checks if there is an ongoing transmission. Basically, if the line is not idle, you want to let it finish communication first, then clear overrun flag knowing that nothing new will be received while you're clearing it. You can enable IDLE interrupt for that, if you don't want to have it block anything (which makes sense if you use interrupt solution)
How about this logic:
Warning: be sure to handle underrun. If only 5 characters are sent and not 8, IDLE will trigger too, make sure it won't cause a problem (it probably won't, just keep it in mind). Alternatively, you can try to enable IDLE interrupt only after receiving 8 chars.
Make sure you check reference manual on how to clear IDLE flag. STM32F103, which I have next to me, says one needs to read USART_SR and then USART_DR, and it will clear IDLE flag.