UART interrupts incompletely enabled for FIFO mode #500

Closed
opened 2021-06-29 10:57:34 -05:00 by MustBeArt · 3 comments
MustBeArt commented 2021-06-29 10:57:34 -05:00 (Migrated from github.com)

Using the SDK interface routines to the UART, enabling FIFO mode doesn't work correctly on receive.

Symptom: the last few characters of a burst are not received promptly.

Explanation: uart_set_irq_enables() only enables the receive data ready interrupt for receive. In FIFO mode, that interrupt only fires when the receive FIFO fills up to the threshold. If a few more characters are received, but not enough to reach the FIFO threshold, that does not trigger another receive data ready interrupt (see 4.2.6.2 of the RP2040 data sheet). In order to get an interrupt for those last few characters, we also need to enable the receive timeout interrupt (see 4.2.6.4).

Proposed solution: in uart_set_irq_enables():

    uart_get_hw(uart)->imsc = (!!tx_needs_data << UART_UARTIMSC_TXIM_LSB) |
                              (!!rx_has_data << UART_UARTIMSC_RXIM_LSB) |
                              (!!rx_has_data << UART_UARTIMSC_RTIM_LSB);  // <--- there it is
Using the SDK interface routines to the UART, enabling FIFO mode doesn't work correctly on receive. Symptom: the last few characters of a burst are not received promptly. Explanation: uart_set_irq_enables() only enables the receive data ready interrupt for receive. In FIFO mode, that interrupt only fires when the receive FIFO fills up to the threshold. If a few more characters are received, but not enough to reach the FIFO threshold, that does not trigger another receive data ready interrupt (see 4.2.6.2 of the RP2040 data sheet). In order to get an interrupt for those last few characters, we also need to enable the receive timeout interrupt (see 4.2.6.4). Proposed solution: in uart_set_irq_enables(): ``` uart_get_hw(uart)->imsc = (!!tx_needs_data << UART_UARTIMSC_TXIM_LSB) | (!!rx_has_data << UART_UARTIMSC_RXIM_LSB) | (!!rx_has_data << UART_UARTIMSC_RTIM_LSB); // <--- there it is ```
lurch commented 2021-06-29 12:44:31 -05:00 (Migrated from github.com)

Interesting...
4.2.7. in the RP2040 datasheet shows that the FIFOs are enabled, https://github.com/raspberrypi/pico-sdk/blob/develop/src/rp2_common/hardware_uart/include/hardware/uart.h#L216 shows that the UARTIFLS_RXIFLSEL is set to 0, the register-description for UARTIFLS says that a RXIFSEL of 0 triggers the receive interrupt when "Receive FIFO
becomes >= 1 / 8 full", and the UART introduction says "Separate 32x8 Tx and 32x12 Rx FIFOs".

All of which combined (using my naive understanding), suggests that the receive interrupt will only trigger when the receive fifo contains at least 32 / 8 (i.e. 4) characters?

@kilograham Maybe we want a test similar to https://github.com/raspberrypi/pico-examples/blob/master/uart/uart_advanced/uart_advanced.c but which doesn't turn off the FIFOs?

Interesting... 4.2.7. in the RP2040 datasheet shows that the FIFOs _are_ enabled, https://github.com/raspberrypi/pico-sdk/blob/develop/src/rp2_common/hardware_uart/include/hardware/uart.h#L216 shows that the `UARTIFLS_RXIFLSEL` is set to `0`, the register-description for `UARTIFLS` says that a `RXIFSEL` of 0 triggers the receive interrupt when "Receive FIFO becomes >= 1 / 8 full", and the UART introduction says "Separate 32x8 Tx and 32x12 Rx FIFOs". All of which combined (using my naive understanding), suggests that the receive interrupt will only trigger when the receive fifo contains at least `32 / 8` (i.e. `4`) characters? @kilograham Maybe we want a test similar to https://github.com/raspberrypi/pico-examples/blob/master/uart/uart_advanced/uart_advanced.c but which **doesn't** turn off the FIFOs?
kilograham commented 2021-06-29 14:16:08 -05:00 (Migrated from github.com)

cc @liamfraser @Wren6991

cc @liamfraser @Wren6991
Wren6991 commented 2021-07-09 05:40:45 -05:00 (Migrated from github.com)

4.2.6.4. UARTRTINTR The receive timeout interrupt is asserted when the receive FIFO is not empty, and no more data is received during a 32-bit period. The receive timeout interrupt is cleared either when the FIFO becomes empty through reading all the data (or by reading the holding register), or when a 1 is written to the corresponding bit of the Interrupt Clear Register, UARTICR

That does sound like what we want! Thanks, I'll open a PR.

> 4.2.6.4. UARTRTINTR The receive timeout interrupt is asserted when the receive FIFO is not empty, and no more data is received during a 32-bit period. The receive timeout interrupt is cleared either when the FIFO becomes empty through reading all the data (or by reading the holding register), or when a 1 is written to the corresponding bit of the Interrupt Clear Register, UARTICR That does sound like what we want! Thanks, I'll open a PR.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-raspberrypi/pico-sdk#500
No description provided.