I am tracking down an issue where I lose occasional bytes received through the UART (SAMV70). I am running at 115Kb. I am using RX interrupts and setting the UART to interrupt on each character since I have variable size packets.
I have registered a UART error callback, but the code is never hitting the UART Error callback, even though I am getting occasional framing errors. (I have trapped them in the debugger) I looked at the ASF _uart_interrupt_handler and it does not seem correct.
It appears that it will only call the error callback if the interrupts are disabled. If they are enabled, it clears the error, reads the holding register but does not call the error callback or the done callback. Is this correct? I would think it should call the error callback without clearing the errors, so the user can handle the error or at least know they occurred.
I added some comments to the ASF handler below:
static void _uart_interrupt_handler(struct _usart_async_device *device)
{
ASSERT(device);
void *hw = device->hw;
// UART TX
if (hri_uart_get_SR_TXRDY_bit(hw) && hri_uart_get_IMR_TXRDY_bit(hw)) {
hri_uart_clear_IMR_TXRDY_bit(hw);
device->usart_cb.tx_byte_sent(device);
} else if (hri_uart_get_SR_TXEMPTY_bit(hw) && hri_uart_get_IMR_TXEMPTY_bit(hw)) {
hri_uart_clear_IMR_TXEMPTY_bit(hw);
device->usart_cb.tx_done_cb(device);
} else if (hri_uart_get_SR_RXRDY_bit(hw) && hri_uart_get_IMR_RXRDY_bit(hw)) { // If Rx Ready and RX RDY Interrupt enabled
if (hri_uart_read_SR_reg(hw) & (UART_SR_OVRE | UART_SR_FRAME | UART_SR_PARE)) { // If we have an RX error
hri_uart_read_RHR_reg(hw); // Read the Rx Holding register
hri_uart_write_CR_reg(hw, UART_CR_RSTSTA); // Reset error bits
return; // Return with no callbacks
}
device->usart_cb.rx_done_cb(device, (uint8_t)hri_uart_read_RHR_RXCHR_bf(hw)); // If no error, call done callback
} else if (hri_uart_read_SR_reg(hw) & (UART_SR_OVRE | UART_SR_FRAME | UART_SR_PARE)) { // else if Rx Rda and Rx Int no enabled & Rx errors
hri_uart_write_CR_reg(hw, UART_CR_RSTSTA); // Reset error bits
device->usart_cb.error_cb(device); // Call uart error callback
}
}