1 8250串口类型的识别
Intel HW都使用DesignWare 8250:
drivers/mfd/intel-lpss-pci.c
drivers/tty/serial/8250/8250_dw.c
IIR寄存器的高2位bit7、bit6用来识别8250串口的类型:
0 - 8250,无FIFO
0 - 并且存在SCR(Scratch register)寄存器,16450,无FIFO
2 - 16550
3 - 16550A
Figure 1-1 UART register to port conversion table
其中DLAB是LCR寄存器的bit7。
2 16450
串口的5、6、7(三菱PLC是7位数据位)、8位数据长度:表示只取每个字节对应的低5、6、7、8位,剩余的高位bit丢弃
UART8250/UART16450:164 = 82 x 2,16450是8250的增强版本
USB VCP波特率可以任意设置,传输速率受限于USB速率;如果VCP的另一端是真实的物理串口,那就必须设置波特率。
16450驱动:
QNX: devc-serpci
Linux:drivers/tty/serial/8250/8250_dw.c
3 16550A
3.1 基本特征
1)16550A - 2个16字节FIFO,一个发送,一个接收
2)RX支持1、4、8、14共4个FIFO触发级别
3)TTY_BUFFER_PAGE -> 对应到tty_buffer
4)#define N_TTY_BUF_SIZE 4096 -> 对应到ldisc的read_buf
3.2 UART 16550 core
UART 16550 core
https://opencores.org/projects/uart16550
4 uart_port
4.1 基本概念
uart_port类比成是usb hub的port,只不过每个uart_port都会有一个驱动;而usb hub的port是公用一个hub驱动。
4.2 PCI工业通信卡
drivers/tty/serial/8250/8250_pci.c
一个PCI卡上有多个8250串口,如何找到每个串口的基地址:
- PCI的BAR0到BAR3的分别对应ttyS0到ttyS3,一般用在第三方做的PCI串口卡
- PCI实现multi-func,每个功能对应一个串口;Intel默认
- PCI总线一般只有INTA#到INTD#的4个中断引脚,所以PCI多功能设备的func一般不会超过4个,但是共享中断除外
4.3 TL16C554A
C表示CMOS工艺,最后数字4表示4端口,基于16550A的4端口
5 中断处理
5.1 串口中断号自动探测
probe_irq_on()
probe_irq_off()
5.2 idle和break中断
idle和break中断:空闲中断是接受数据后出现一个byte的高电平(空闲)状态,就会触发空闲中断。并不是空闲就会一直中断,准确的说应该是上升沿(停止位)后一个byte,如果一直是低电平是不会触发空闲中断的,会触发break中断。
6 FIFO和DMA
6.1 8250 RX FIFO触发level
16550A and Tegra:1, 4, 8, or 14 bytes
16650V2:8, 16, 24, or 28 bytes
16654:8, 16, 56, or 60 bytes
16750:1, 16, 32, or 56 bytes
echo 4 > /sys/class/tty/ttyS0/rx_trig_bytes
6.2 查看RX溢出
cat /proc/tty/driver/serial
6.3 8250 DMA
接收不定长数据超时中断:UART_IIR_RX_TIMEOUT
6.4 URLs
serial: 8250: Avoid "too much work" from bogus rx timeout interrupt
https://lore.kernel.org/patchwork/patch/744611/
7 Tools
7.1 控制串口的各种属性
busybox stty -F /dev/ttyS0 -a
busybox setserial -a /dev/ttyS0
busybox
https://busybox.net/downloads/binaries/1.28.1-defconfig-multiarch/
8N1中间的N表示None,无校验。
7.2 strace
lsof | grep /dev/ttyS0
busybox fuser /dev/ttyS0
ls -l /proc/2848/fd | grep /dev/ttyS0
捕获物理串口的read()数据,strace必须带-f参数,否则捕获不到read()数据。
strace -p $PID -x -tt -T -f -e trace=read -e read=$FD
docker容器使能strace
docker run --cap-add=SYS_PTRACE ...
8 UART数据位的位数为何为5~8位可选
8.1 历史来源
在电传打字机上,当时只为传26个字母,这只要有5位二进制码就可传到32个字符了,所以五位就够了;再后要分大小写就六位了;上计算机后用ASCII码就要用到七位了。因串行通信的位数越多越要时间,电传打字机时波特率是很低的,所以能少一位就会传的更快一点的。
8.2 1与0,MARK与SPACE
电传打字机发明的时候还没有阴极射线管,更别提有电脑了,那时候要发送电文,是先用打孔机在纸带上打孔,数据的1就打孔,称为MARK,0则不打孔,称为SPACE,然后用读纸带机将信号发出去。接收方收到信号后也是先在纸带上打孔,接着纸带进入解码机,使打字机印出相关的字来。
9 serial over network TCP
socat pty,link=/dev/virtualcom0,raw tcp:192.168.0.10:8080 &
10 Abbreviations
DLAB:Divisor Latch Access Bit
RDI:OMAP 8250 Receive Data Interrupt
RTS:Request to Send
CTS:Clear to Send,这里的Clear不是清除的意思,而是表示通道空闲,可以发送
USB BH reset:Bigger Hammer or Brad Hosler,表示warm reset;you may be confused why the USB 3.0 spec calls the same type of reset "warm reset" in some places and "BH reset" in other places. "BH" reset is supposed to stand for "Big Hammer" reset, but it also stands for "Brad Hosler". Brad died shortly after the USB 3.0 bus specification was started, and they decided to name the reset after him. The suggestion was made shortly before the spec was finalized, so the wording is a bit inconsistent
WHL:Python Wheel Package
Zadig:an Automated Driver Installer GUI application for WinUSB, libusb-win32 and libusbK