Universal Asynchronous Receiver/Transmitter (UART) interface for hardware platforms.
More...
|
| enum | hw_uart_data_bits_t { hw_uart_data_bits_5 = 5,
hw_uart_data_bits_6 = 6,
hw_uart_data_bits_7 = 7,
hw_uart_data_bits_8 = 8
} |
| | UART data bit configuration.
|
| |
| enum | hw_uart_stop_bits_t { hw_uart_stop_bits_1 = 1,
hw_uart_stop_bits_2 = 2
} |
| | UART stop bit configuration.
|
| |
| enum | hw_uart_parity_t { hw_uart_parity_none,
hw_uart_parity_even,
hw_uart_parity_odd
} |
| | UART parity configuration.
|
| |
| enum | hw_uart_flow_control_t { hw_uart_flow_control_none,
hw_uart_flow_control_cts,
hw_uart_flow_control_rts,
hw_uart_flow_control_cts_rts
} |
| | UART hardware flow control mode.
|
| |
Universal Asynchronous Receiver/Transmitter (UART) interface for hardware platforms.
hw_uart_init() hands back a plain sys_iostream_t (picofuse/sys/io.h) - once open, a UART is just another byte stream, so reading, writing, closing, and readiness notification all go through the generic sys_iostream_read()/sys_iostream_write()/sys_iostream_close()/ sys_iostream_set_callback() rather than UART-specific equivalents. Only hw_uart_flush() remains here, for the one thing genuinely specific to a hardware serial line: waiting for the transmit FIFO to actually drain.
◆ hw_uart_flush()
Wait for UART transmission to complete.
- Parameters
-
| uart | A stream from hw_uart_init(). |
| timeout_ms | Timeout for the operation in milliseconds. Set to 0 for a non-blocking status check. |
- Return values
-
| true | All pending transmit data was sent before the timeout expired. |
| false | Transmission was still in progress when the timeout expired, or uart is invalid or not a UART stream. |
Waits until all data already accepted by sys_iostream_write() has left both the software ring buffer (see hw_uart_init()'s own doc) and the UART's own transmit shift register - something no generic sys_iostream_t operation can express, since it's about the underlying hardware's state rather than the stream's buffer. On a hw_uart_init_device() stream, this is tcdrain(2) - which has no portable non-blocking or bounded-wait form, so timeout_ms is accepted for interface consistency but not actually enforced there; it returns as soon as the OS reports the line genuinely idle.
◆ hw_uart_init()
Initialize a UART device.
- Parameters
-
| rx_pin | The GPIO pin to use for UART receive. |
| tx_pin | The GPIO pin to use for UART transmit. |
| baud_rate | The UART baud rate in bits per second. |
| config | Optional pointer to extended UART configuration. Pass NULL to use default line format and no flow control. |
- Returns
- An open stream ready for sys_iostream_read()/write(), or NULL if initialization fails. Release it with sys_iostream_close() - there is no separate hw_uart_deinit().
Readiness notification (data available to read, space available to write) is available through sys_iostream_set_callback() on the returned stream, using sys_iostream_event_read/sys_iostream_event_write, the same as any other stream - not a UART-specific event/callback type.
On the Pico backend, the hardware's hold-up-to-32-bytes FIFOs don't reliably raise their own fill-level interrupts (confirmed independently of this driver, and matched by the Pico SDK's own uart_advanced example, which disables FIFOs for the same reason), so the UART itself runs in character mode - 1 byte of hardware buffering - to make readiness callbacks fire reliably. To make up for that, hw_uart_init() backs the stream with its own software ring buffer (background-drained by a real interrupt, independent of whether a readiness callback is registered), restoring burst sys_iostream_read()/write() throughput - pass hw_uart_config_t.unbuffered to skip it and transfer directly against the 1-byte hardware register instead.
◆ hw_uart_init_device()
Initialize a UART by device path.
- Parameters
-
| device | Device path, e.g. "/dev/ttyUSB0" or "/dev/cu.usbserial-1420". |
| baud_rate | The UART baud rate in bits per second. Only standard POSIX rates are supported (50 through 230400) - anything else fails. |
| config | Optional pointer to extended UART configuration. Pass NULL to use default line format and no flow control. hw_uart_config_t's cts_pin/rts_pin/unbuffered fields are Pico-specific and ignored here; hw_uart_flow_control_cts/hw_uart_flow_control_rts alone (as opposed to hw_uart_flow_control_cts_rts or hw_uart_flow_control_none) are rejected, since termios only exposes combined RTS/CTS flow control. |
- Returns
- An open stream ready for sys_iostream_read()/write(), or NULL if initialization fails. Release it with sys_iostream_close().
Host platforms (Darwin, Linux) have no GPIO pins for a serial port - it's addressed by device path instead, mirroring hw_i2c_init_device()/ hw_spi_init_device(). hw_uart_init() is Pico-only; this is the reverse.
A background thread continuously drains the OS's own input buffer into this stream's, so sys_iostream_event_read fires and bytes aren't lost between sys_iostream_read() calls. sys_iostream_write() is a direct, blocking write(2) - sys_iostream_event_write never fires, since a POSIX serial write essentially never has to wait for "room."