You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Serial UART devices (e.g., 16550A) trigger RX interrupts only when their FIFO reaches a certain threshold (often more than 8 bytes). However, many communication protocols or sensor controls require immediate response to each individual byte received. Delayed interrupts leads to unacceptable latency, breaking protocols that expect immediate responses. The ability to set serial FIFO levels is commonly available on modern chipsets. To improve availability of low latency protocols in the linux kernel, it would be beneficial to have a universal API for configuring serial FIFO options/
For example:
The LIN protocol is a low-speed serial communication protocl meant to augment CAN protocol in automotive applications, which uses UART hardware. While initial work to implement the protocol into Linux was completed years ago, the work stalled out due to a need for near immediate response to single bytes received. This is due to the way the LIN protocol operates as a master-slave network. Slaves are expected to respond immediately to a header from the master when the master is requesting data from the slave. As such, slave response mode was never fully implemented and thus the protocol cannot be mainlined into the kernel.
A discussion on lin-bus implementation in linux highlights the requirents:
“It is necessary to set UART into mode where Rx FIFO is disabled or Rx threshold is set to one. Unfortunately, there is no unified API for this parameter or even its availability which is supported across multiple/all UART drivers implementations.”
Current Userspace Implementation for Fifo Size Control via sysfs on 16550 Devices
Yoshihiro Yunomae implemented a user-space interface (ie. /sys/class/tty/ttyS*/rx_trig_bytes) to adjust the RX trigger level in serial devices, enabling selecting values like 1, 4, 8, or 14 bytes. While this approach successfully implements userspace fifo level control in 16550A-like devices, implementation in related devices (eg. 16650, 16750) is limited to controlling the 16550A based 'FCR' register, which limits the number of levels available on more modern devices. The current implementation takes advantage of the fact that nearly every 8250-based device after the 16550 uses bits 6 and 7 of the same 'FCR' register to set the Rx FIFO trigger level to one of 4 predefine values, in order to offer some degree of programmability to rx fifo levels. However, many devices offer further configuration options available with other registers. For example, in addition to the legacy 16550 compatible rx trigger levels, the 16750 also offers an enhanced 64 byte FIFO mode, which requires setting an additional flag in the FCR[5] as well as the DLAB bit from the LCR[7]. The diversity of devices represented within the 8250 serial driver core warrants a more flexible approach to FIFO configuration within the tty subsystem. I propose
implementing a universal fifo_control callback in the uart_ops to hook into device-specific fifo control functions for each port type which supports . It may be desirable to implement a series of device-specific functions within the tty subsystem to enable setting fifo configuration. Additionally, it may be desirable to disable the FIFO completely (ie. 16450 mode), change the DMA transfer mode to single byte, or set the FIFO timeout where available. Furthermore, many modern pcie serial devices, such as 16850 are unsupported by the current sysfs interface despite having very flexible fully programmable FIFO config options, because they use registers other than the 16550A-like FCR register (ie. 'TRG'). The current sysfs serial fifo trigger level configuration interface only supports a limited range of 16550A-like serial devices. Furthermore, many modern serial devices which do contain completely programmable FIFOs (eg. the PCI-based WCH384), are currently unsupported in the current sysfs implementation because they are configured as 16850 ports.
FIFO Control Scheme Variance
There are considerable implementation differences between how different 16550A-based serial devices implement FIFO control.
UART Model
FIFO Size (max)
RX Trigger Levels
TX Trigger Levels
Registers Used for FIFO Control
Notes
8250
None
N/A
N/A
N/A
No FIFO support
16450
None
N/A
N/A
N/A
No FIFO support
16550
16 (buggy)
N/A
N/A
FCR exists but doesn't function
FIFO is broken - not widely used
16550A
16
1, 4, 8, 14 bytes
N/A
FCR[7:6]
FCR controls FIFO
16650
32
8, 16, 24, 28 bytes
16, 8, 24, 30
FCR
Tx and Rx programmable FIFOs
16750
64
1, 4, 8, 14 (legacy) 1, 16, 32, 56 (enhanced)
N/A
FCR[7:6:5] LCR[7]
Supports legacy 16 byte FIFO and enhanced 64 byte mode via FCR[5] NOTE: LCR[7] MUST = 1 to enable FCR[5]
16850/16950
128
Fully programmable (1–127 bytes)
Fully programmable (1–127 bytes)
FCR FCTR TRG
FCTR to select the trigger table TRG to program the FIFO in 'table D'
Userspace Interface Considerations
Current serial settings such as baudrate, parity, etc, are sent from userspace to the serial subsystem via IOCTL and a termios data struct. However, to avoid implementing a termios3, and to maintain compatability with the current rx_trig_bytes API, we'll implement a series of new sysfs entries, but we'll move everything to the serial_core to keep consistency with other serial sysfs entries.
Reference Documentation
This patch series was designed to work universally, with ANY linux serial device. However, the following datasheets have been specifically used and referenced throughout the design and development of this patch series.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Kernel level uart fifo control
Background & Motivation
Low-Latency RX Needed for Real-Time Protocols
Serial UART devices (e.g., 16550A) trigger RX interrupts only when their FIFO reaches a certain threshold (often more than 8 bytes). However, many communication protocols or sensor controls require immediate response to each individual byte received. Delayed interrupts leads to unacceptable latency, breaking protocols that expect immediate responses. The ability to set serial FIFO levels is commonly available on modern chipsets. To improve availability of low latency protocols in the linux kernel, it would be beneficial to have a universal API for configuring serial FIFO options/
For example:
The LIN protocol is a low-speed serial communication protocl meant to augment CAN protocol in automotive applications, which uses UART hardware. While initial work to implement the protocol into Linux was completed years ago, the work stalled out due to a need for near immediate response to single bytes received. This is due to the way the LIN protocol operates as a master-slave network. Slaves are expected to respond immediately to a header from the master when the master is requesting data from the slave. As such, slave response mode was never fully implemented and thus the protocol cannot be mainlined into the kernel.
A discussion on lin-bus implementation in linux highlights the requirents:
Current Userspace Implementation for Fifo Size Control via sysfs on 16550 Devices
Yoshihiro Yunomae implemented a user-space interface (ie. /sys/class/tty/ttyS*/rx_trig_bytes) to adjust the RX trigger level in serial devices, enabling selecting values like 1, 4, 8, or 14 bytes. While this approach successfully implements userspace fifo level control in 16550A-like devices, implementation in related devices (eg. 16650, 16750) is limited to controlling the 16550A based 'FCR' register, which limits the number of levels available on more modern devices. The current implementation takes advantage of the fact that nearly every 8250-based device after the 16550 uses bits 6 and 7 of the same 'FCR' register to set the Rx FIFO trigger level to one of 4 predefine values, in order to offer some degree of programmability to rx fifo levels. However, many devices offer further configuration options available with other registers. For example, in addition to the legacy 16550 compatible rx trigger levels, the 16750 also offers an enhanced 64 byte FIFO mode, which requires setting an additional flag in the FCR[5] as well as the DLAB bit from the LCR[7]. The diversity of devices represented within the 8250 serial driver core warrants a more flexible approach to FIFO configuration within the tty subsystem. I propose
implementing a universal fifo_control callback in the uart_ops to hook into device-specific fifo control functions for each port type which supports . It may be desirable to implement a series of device-specific functions within the tty subsystem to enable setting fifo configuration. Additionally, it may be desirable to disable the FIFO completely (ie. 16450 mode), change the DMA transfer mode to single byte, or set the FIFO timeout where available. Furthermore, many modern pcie serial devices, such as 16850 are unsupported by the current sysfs interface despite having very flexible fully programmable FIFO config options, because they use registers other than the 16550A-like FCR register (ie. 'TRG'). The current sysfs serial fifo trigger level configuration interface only supports a limited range of 16550A-like serial devices. Furthermore, many modern serial devices which do contain completely programmable FIFOs (eg. the PCI-based WCH384), are currently unsupported in the current sysfs implementation because they are configured as 16850 ports.
FIFO Control Scheme Variance
There are considerable implementation differences between how different 16550A-based serial devices implement FIFO control.
FCRexists but doesn't functionFCR[7:6]FCR1, 16, 32, 56 (enhanced)
FCR[7:6:5]LCR[7]
NOTE:
LCR[7]MUST = 1 to enableFCR[5]FCRFCTRTRGFCTRto select the trigger tableTRGto program the FIFO in 'table D'Userspace Interface Considerations
Current serial settings such as baudrate, parity, etc, are sent from userspace to the serial subsystem via IOCTL and a termios data struct. However, to avoid implementing a termios3, and to maintain compatability with the current rx_trig_bytes API, we'll implement a series of new sysfs entries, but we'll move everything to the serial_core to keep consistency with other serial sysfs entries.
Reference Documentation
This patch series was designed to work universally, with ANY linux serial device. However, the following datasheets have been specifically used and referenced throughout the design and development of this patch series.
Beta Was this translation helpful? Give feedback.
All reactions