Skip to content

Commit 0bbc88f

Browse files
committed
pbio/drv/uart/uart_ev3.c: Clear entire RX FIFO on interrupt
If data is left in the RX FIFO, the peripheral might not correctly re-trigger interrupts, which causes data reception to get stuck.
1 parent 3e1a107 commit 0bbc88f

File tree

1 file changed

+12
-15
lines changed

1 file changed

+12
-15
lines changed

lib/pbio/drv/uart/uart_ev3.c

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -278,26 +278,23 @@ void pbdrv_uart_flush(pbdrv_uart_dev_t *uart) {
278278
* @param [in] uart The UART device.
279279
*/
280280
void pbdrv_uart_ev3_hw_handle_irq(pbdrv_uart_dev_t *uart) {
281-
282-
/* This determines the cause of UART0 interrupt.*/
283-
unsigned int int_id = UARTIntStatus(uart->pdata->base_address);
284-
285281
/* Clears the system interrupt status of UART in AINTC. */
286282
IntSystemStatusClear(uart->pdata->sys_int_uart_rx_int_id);
287283

288-
/* Check if the cause is receiver data condition.*/
289-
if (UART_INTID_RX_DATA == (int_id & UART_INTID_RX_DATA) || (UART_INTID_CTI == (int_id & UART_INTID_CTI))) {
284+
// Repeatedly attempt to handle all the data which we might have
285+
while ((HWREG(uart->pdata->base_address + UART_IIR) & UART_IIR_IPEND) == 0) {
286+
// We always have *a* character in the FIFO, even if it might be an error
290287
int c = UARTCharGetNonBlocking(uart->pdata->base_address);
291-
if (c != -1) {
292-
ringbuf_put(&uart->rx_buf, c);
293-
}
294-
}
288+
unsigned int err = UARTRxErrorGet(uart->pdata->base_address);
289+
290+
// If there is an overrun, the data we do have is nonetheless valid.
291+
// We don't report overruns, so just ignore the flag
292+
// (reading the LSR register automatically clears it in the hardware side).
293+
err &= ~UART_OVERRUN_ERROR;
295294

296-
/* Check if the cause is receiver line error condition.*/
297-
if (UART_INTID_RX_LINE_STAT == (int_id & UART_INTID_RX_LINE_STAT)) {
298-
while (UARTRxErrorGet(uart->pdata->base_address)) {
299-
/* Read a byte from the RBR if RBR has data.*/
300-
UARTCharGetNonBlocking(uart->pdata->base_address);
295+
if (c != -1 && !err) {
296+
// Push valid characters into the ring buffer
297+
ringbuf_put(&uart->rx_buf, c);
301298
}
302299
}
303300

0 commit comments

Comments
 (0)