Is there a way for the UART to generate a Tx IRQ (indicating the tx buffer is not full) when using it in "single character mode", ie with FIFOs disabled?
I'm trying to develop a Modbus RTU interface over RS485 (half-duplex) via a Pico UART. Modbus needs accurate byte-to-byte Rx timing measurements to correctly implement the protocol, so I disable the FIFOs and read the usec timer on every Rx IRQ (on which I remove just one byte), and this all works as expected.
However, in this mode, it seems that Tx IRQs don't happen at all. (I am using uart_set_irq_enables() to configure the IRQ for the current line direction.) I can push data into the Tx at the start of a frame while uart_is_writable() - at most 2 bytes - and that is apparently sent. But then there is no Tx IRQ to say it has gone and I could write more data...
I've read the relevant parts of the RP2040 datasheet and the uart section of the Pico C/C++ SDK docs, but nothing seems to describe this particular detail explicitly, or identify a workround.
I have thought of enabling / disabling the fifos according to current line direction (ie enabled for Tx, disabled for Rx), as I don't need accurate Tx timing, only Rx timing. But the documentation of uart_set_fifo_enabled(), which I would need to use, says that "the UART is paused for around two character periods whilst the settings are changed. Data received during this time may be dropped by the UART", and also that it "should not be called from an interrupt context". Both constraints make this approach unworkable.
At this point, in desperation I am considering using a repeating alarm (happening once per character time at the Tx baud rate) during Tx operation, to explicitly check for uart_is_writable() and send the next byte when it returns true. But this is not exactly pretty. And given that Rx IRQs work as expected in this mode, why is the same not true for Tx?
Any help / information would be welcome!
I'm trying to develop a Modbus RTU interface over RS485 (half-duplex) via a Pico UART. Modbus needs accurate byte-to-byte Rx timing measurements to correctly implement the protocol, so I disable the FIFOs and read the usec timer on every Rx IRQ (on which I remove just one byte), and this all works as expected.
However, in this mode, it seems that Tx IRQs don't happen at all. (I am using uart_set_irq_enables() to configure the IRQ for the current line direction.) I can push data into the Tx at the start of a frame while uart_is_writable() - at most 2 bytes - and that is apparently sent. But then there is no Tx IRQ to say it has gone and I could write more data...
I've read the relevant parts of the RP2040 datasheet and the uart section of the Pico C/C++ SDK docs, but nothing seems to describe this particular detail explicitly, or identify a workround.
I have thought of enabling / disabling the fifos according to current line direction (ie enabled for Tx, disabled for Rx), as I don't need accurate Tx timing, only Rx timing. But the documentation of uart_set_fifo_enabled(), which I would need to use, says that "the UART is paused for around two character periods whilst the settings are changed. Data received during this time may be dropped by the UART", and also that it "should not be called from an interrupt context". Both constraints make this approach unworkable.
At this point, in desperation I am considering using a repeating alarm (happening once per character time at the Tx baud rate) during Tx operation, to explicitly check for uart_is_writable() and send the next byte when it returns true. But this is not exactly pretty. And given that Rx IRQs work as expected in this mode, why is the same not true for Tx?
Any help / information would be welcome!
Statistics: Posted by littleowlish — Sat May 11, 2024 2:13 pm — Replies 0 — Views 21