Hello linux-serial. I have been experiencing some strangeness using the 8250 Linux uart driver on a legacy ISA based embedded platform in an attempt to upgrade an older Linux 2.6.37 based system to a more recent kernel. A number of kernel releases has been tested including 4.6.0-rc6 (see complete list below) that all behave similarly. The hardware consist of an Axiomtek AX12260 SoM [1] on top of a custom i/o board containing three SC16C2550B [2] dual uarts. The uarts are connected to the SoM's ISA bus (via PC/104 connector) with fixed irq/io configuration (no irq sharing) as follows. Uart io irq ------------------ UART1A 0x03f8 4 UART1B 0x02f8 3 UART2A 0x03e8 7 UART2B 0x02e8 5 UART3A 0x02f0 10 UART3B 0x03e0 11 Also the uart oscillators are 3.6864MHz (double of the standard/normal 1.8432MHz). Booting the kernel six uarts are reported/detected (NR_UARTS=6, see dmesg/config below) and the first four are autoconf'ed to correct io but 2A+2B with incorrect irq consistent with defaults in asm/serial.h [3]. Correct io/irq/baud_base are set from user-space using setserial, mapping the uarts to device files ttyS0-ttyS5 in the above order and doubling baud_base to 230400. The serial ports that use device files ttyS0-4 behave as expected, but the last port (UART3B on /dev/ttyS5) does not work. Meaning I am unable to communicate with the gsm modem connected to it. This definitely has a "off-by-one" feel to it and I tried a simple CONFIG_SERIAL_8250_NR_UARTS=7 but that yields no difference. However, after much debugging and testing I have determined that by remapping io/irq on the device file using setserial I am able to bring UART3B into a functional state by accessing it through a device file other than ttyS5. And additionally, anyone of the other uarts configured to use the device file /dev/ttyS5 stops working. Below are kernel logs with the 8250 driver's DEBUG_INTR enabled [4] when attempting to communicate with the modem through UART3B configured to use device files ttyS1 and ttyS5 respectively (full kernel info below). The tests were done by writing an AT NOP command to the device using "echo at >/dev/ttyS*" and monitoring the modem's echo and "OK" response in another shell using "cat /dev/ttyS*" (the modem is by default in autobaud mode so baudrate shouldn't matter). Using ttyS1 I see the echo and response on the shell as expected but using ttyS5 nothing is received: --- interrupt test ** ttyS5 (no response) May 17 11:20:14 ax12260 user.warn kernel: serial8250_interrupt(11)...status = 60...THRE...end. May 17 11:20:14 ax12260 user.warn kernel: serial8250_interrupt(11)...status = 20...end. May 17 11:20:28 ax12260 user.warn kernel: serial8250_interrupt(11)...end. ** ttyS1 (echo + response received) May 17 11:17:40 ax12260 user.warn kernel: serial8250_interrupt(11)...status = 60...THRE...end. May 17 11:17:40 ax12260 user.warn kernel: serial8250_interrupt(11)...status = 20...end. May 17 11:17:40 ax12260 user.warn kernel: serial8250_interrupt(11)...status = 61...end. May 17 11:17:40 ax12260 user.warn kernel: serial8250_interrupt(11)...status = 60...THRE...end. May 17 11:17:40 ax12260 user.warn kernel: serial8250_interrupt(11)...status = 1...end. May 17 11:17:40 ax12260 user.warn kernel: serial8250_interrupt(11)...status = 20...THRE...end. May 17 11:18:56 ax12260 user.warn kernel: serial8250_interrupt(11)...end. --- The "status" value above refer to the contents of the LSR register in serial8250_handle_irq() [5] as described at [6], chapter 7.7, p. 22-23. Thus 0x01 is LSR[0]=Receive data ready 0x20 is LSR[5]=THR empty (THRE) 0x40 is LSR[6]=THR and TSR empty As can be seen, transmit interrupts are generated and bytes seem to be transmitted in both cases. But somehow no Receive data ready interrupts are handled by serial8250_handle_irq() at all when using ttyS5 as device file. My first thought was that receive interrupts could somehow be cancelled by generic interrupt handling before being handed over to serial8250. But writing this post also gave me a hunch that it might be caused by the baud_base not being respected when using ttyS5. As far as I can see that might create the same scenario; bytes going out (with wrong timing), and uart discarding received bytes because of seemingly incorrect timing (if the other end responds to the unexpected baudrate at all). Inspecting the baud_base values reported by setserial for ttyS0-5 there is no indication that 5 should behave differently. Anybody who can see flaws in my tests or reasoning? Or are having deeper insight than me into the serial stack to be able to confirm/reject that there could be problems with baud_base in unusual configurations like the one outline here? I think my next step will be to do some measurements on tx to test the wrong effective baud_base theory. Haven't done measurements before because signals to the gsm modem is not very accessible, but now that I am able to recreate the error on the other uarts I have a lot more options of finding accessible test points. -- Thanks & regards, Mikkel [1] http://www.axiomtek.com/Default.aspx?MenuId=Products&FunctionId=ProductView&ItemId=567 [2] http://www.nxp.com/products/interface-and-connectivity/wired-connectivity/uarts/two-channel/5-v-3.3-v-and-2.5-v-dual-uart-5-mbit-s-max.-with-16-byte-fifos:SC16C2550B [3] http://lxr.free-electrons.com/source/arch/x86/include/asm/serial.h?v=4.1 [4] http://lxr.free-electrons.com/source/drivers/tty/serial/8250/8250_core.c?v=4.1#L77 [5] http://lxr.free-electrons.com/source/drivers/tty/serial/8250/8250_core.c?v=4.1#L1631 [6] http://www.nxp.com/documents/data_sheet/SC16C2550B.pdf --- tested and failing kernels 3.19 (yocto-kernel, 3.19 (LTSI)) 4.1.22-yocto-standard (yocto-kernel, 4.1) 4.6.0-rc6-yocto-standard (yocto-kernel-dev) --- --- interrupt debug kernel information root@ax12260:~# uname -a Linux ax12260 4.1.22-yocto-standard #1 SMP PREEMPT Tue May 10 15:03:38 CEST 2016 i586 GNU/Linux root@ax12260:~# cat /var/log/dmesg |grep 8250 -A1 -B1 io scheduler cfq registered (default) Serial: 8250/16550 driver, 6 ports, IRQ sharing disabled ttyS0: autoconf (0x03f8, 0x (null)): iir1=6 iir2=6 iir=3 type=16550A serial8250: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A ttyS1: autoconf (0x02f8, 0x (null)): iir1=6 iir2=6 iir=3 type=16550A serial8250: ttyS1 at I/O 0x2f8 (irq = 3, base_baud = 115200) is a 16550A ttyS2: autoconf (0x03e8, 0x (null)): iir1=6 iir2=6 iir=3 type=16550A serial8250: ttyS2 at I/O 0x3e8 (irq = 4, base_baud = 115200) is a 16550A ttyS3: autoconf (0x02e8, 0x (null)): iir1=6 iir2=6 iir=3 type=16550A serial8250: ttyS3 at I/O 0x2e8 (irq = 3, base_baud = 115200) is a 16550A Linux agpgart interface v0.103 root@ax12260:~# zcat /proc/config.gz |grep 8250 CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y CONFIG_SERIAL_8250_PNP=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_PCI=y CONFIG_SERIAL_8250_NR_UARTS=6 CONFIG_SERIAL_8250_RUNTIME_UARTS=6 CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_MANY_PORTS=y # CONFIG_SERIAL_8250_SHARE_IRQ is not set # CONFIG_SERIAL_8250_DETECT_IRQ is not set # CONFIG_SERIAL_8250_RSA is not set # CONFIG_SERIAL_8250_DW is not set # CONFIG_SERIAL_8250_FINTEK is not set # Non-8250 serial port support ---
Attachment:
signature.asc
Description: OpenPGP digital signature