Purpose: A common question that many people have who have been playing with serial ports under Linux is to detect serial overrun errors while debugging/testing their serial ports. Unfortunately, there is no utility that I know off which lets you measure the overrun error in real time. However this ability is in-built into the Linux kernel itself! In this blog post, we will see exactly how to use that.

Assumptions:

Linux kernel – 2.6.30

Linux OS – Debian Lenny

Generally serial overrun error occur when your FIFO (First In First Out) buffer is full. In this case, Linux kernel is not able to service interrupts fast enough and hence data is lost. However, mind you that this does not mean that the Linux kernel is buggy. A serial overrun could mean that a lot of things could be going wrong like BIOS, firmware, System Management Mode (SMM), in correct Linux kernel setting, etc.

So let’s see how to detect serial overrun errors…

While you are transferring data over serial port on your Linux machine you can give the following command:

debian:~# cat /proc/tty/driver/serial
serinfo:1.0 driver revision:
0: uart:16550A port:000003F8 irq:4 tx:433 rx:210464 fe:32 brk:153328 oe: 5 RTS|DTR
debian-server:~#

There is your culprit in the red. The field “oe”, which I think stands for “overrun error“, tells you the number of times your UART encountered overrun errors while transmitting data over serial port.

When you reboot your system, you should not be able to see any “oe” field upon giving the above command. This way you can measure your overrun errors from scratch for a particular serial transfer.

Also the there is another field called “buf_overrun” in the Linux kernel source code, however the above command does not prints out the output for that. I am not sure what is the difference between “overrun” and “buffer overrun”. However if you want to Linux kernel to print the value of this field, you need to edit the following file in the Linux kernel source:

# nano /usr/src/linux-source-2.6.30/drivers/serial/serial_core.c

and add the following line:

if (port->icount.overrun)
seq_printf(m, " bo:%d", port->icount.buf_overrun);

just after the following line:

if (port->icount.overrun)
seq_printf(m, " oe:%d",  port->icount.overrun);

Now you can re-compile your kernel and see if the Linux kernel prints the “bo” field. You can name the field whatever you want.

Please note that I have not tried the above. So please use at your own risk. Also if you had success with the above modifications please let us know by posting a comment.

That’s it!

Happy Overrun’ing!

Be Sociable, Share!