EmbeddedRelated.com
Forums
Memfault Beyond the Launch

Linux serial port dropping bytes

Started by Derek Young March 31, 2008
Hi all,

I'm using an Arcom Viper PXA255 single board computer running Linux, and 
I'm trying to receive bytes over the built-in RS-422 serial port at 
921.6 kbps.  The received packets are 1500 bytes long.  The UART is a 
16C2850 (dual port version of the 16C850 with 128 byte FIFO).

Everything works fine at low speeds, but if the packet rate increases, I 
start to lose bytes.

I believe this is caused by the Linux serial port interrupt handler not 
responding fast enough.  Some testing revealed that this problem only 
occurs when other peripherals (such as the flash drive or ethernet port) 
are active.

I searched online and found a utility called IRQtune which promises to 
fix exactly this sort of problem by allowing control of ISR priorities 
in Linux.  Unfortunately, IRQtune only works for x86 processors.

Does anybody know of a simple way to modify the priorities of interrupts 
in Linux?  I don't mind recompiling the kernel, but I don't have a lot 
of expertise in that sort of thing.  (In fact, I would have preferred 
skipping the whole OS thing and implementing the entire solution on an 
FPGA/uController, but oh well... one doesn't always get to choose.)

Any advice would be greatly appreciated.  Thanks!


Derek


--
remove the .nospam and rearrange appropriately to e-mail.
Derek Young wrote:
> > I'm using an Arcom Viper PXA255 single board computer running Linux, > and I'm trying to receive bytes over the built-in RS-422 serial port > at 921.6 kbps. The received packets are 1500 bytes long. The UART > is a 16C2850 (dual port version of the 16C850 with 128 byte FIFO). > > Everything works fine at low speeds, but if the packet rate > increases, I start to lose bytes.
Your numbers indicate that you would need an interrupt roughly every 1 microsec. Not a chance. -- [mail]: Chuck F (cbfalconer at maineline dot net) [page]: <http://cbfalconer.home.att.net> Try the download section. -- Posted via a free Usenet account from http://www.teranews.com
On Mar 31, 5:37 pm, Derek Young <edu.mit...@dereky.nospam> wrote:

> I believe this is caused by the Linux serial port interrupt handler not > responding fast enough.
Or not being relieved of the packet payloads fast enough by whatever is supposed to consume them.
> Does anybody know of a simple way to modify the priorities of interrupts > in Linux? I don't mind recompiling the kernel, but I don't have a lot > of expertise in that sort of thing.
You'll want to go looking around in the processor / board specific code, and especially the serial port driver, perhaps plus whatever programs the interrupt hardware. Look in places like drivers/serial drivers/char arch/processorname/
Derek Young wrote:
>... > I'm trying to receive bytes over the built-in RS-422 serial port at > 921.6 kbps. The received packets are 1500 bytes long. The UART is a > 16C2850 (dual port version of the 16C850 with 128 byte FIFO). >
This means you have 1.388 mS to fill the FIFO - plenty of time to process it.
> Everything works fine at low speeds, but if the packet rate increases, I > start to lose bytes. > > I believe this is caused by the Linux serial port interrupt handler not > responding fast enough. Some testing revealed that this problem only > occurs when other peripherals (such as the flash drive or ethernet port) > are active.
If some of these IRQ handlers hogs the CPU for 1mS or so you will have no way out, but if they do that they will be broken anyway. I am not a wintel/linux etc person and I don't know how much can be achieved in click-and-try-this mode on your problem, you may be lucky and hit some working combination for all I know. Without luck you would want to know the worst case system IRQ latency, your UART IRQ load etc. and locate and fix the problem. Dimiter ------------------------------------------------------ Dimiter Popoff Transgalactic Instruments http://www.tgi-sci.com ------------------------------------------------------ http://www.flickr.com/photos/didi_tgi/sets/72157600228621276/ Derek Young wrote:
> Hi all, > > I'm using an Arcom Viper PXA255 single board computer running Linux, and > I'm trying to receive bytes over the built-in RS-422 serial port at > 921.6 kbps. The received packets are 1500 bytes long. The UART is a > 16C2850 (dual port version of the 16C850 with 128 byte FIFO). > > Everything works fine at low speeds, but if the packet rate increases, I > start to lose bytes. > > I believe this is caused by the Linux serial port interrupt handler not > responding fast enough. Some testing revealed that this problem only > occurs when other peripherals (such as the flash drive or ethernet port) > are active. > > I searched online and found a utility called IRQtune which promises to > fix exactly this sort of problem by allowing control of ISR priorities > in Linux. Unfortunately, IRQtune only works for x86 processors. > > Does anybody know of a simple way to modify the priorities of interrupts > in Linux? I don't mind recompiling the kernel, but I don't have a lot > of expertise in that sort of thing. (In fact, I would have preferred > skipping the whole OS thing and implementing the entire solution on an > FPGA/uController, but oh well... one doesn't always get to choose.) > > Any advice would be greatly appreciated. Thanks! > > > Derek > > > -- > remove the .nospam and rearrange appropriately to e-mail.
On 2008-03-31, CBFalconer <cbfalconer@yahoo.com> wrote:
> Derek Young wrote: >> >> I'm using an Arcom Viper PXA255 single board computer running Linux, >> and I'm trying to receive bytes over the built-in RS-422 serial port >> at 921.6 kbps. The received packets are 1500 bytes long. The UART >> is a 16C2850 (dual port version of the 16C850 with 128 byte FIFO). >> >> Everything works fine at low speeds, but if the packet rate >> increases, I start to lose bytes. > > Your numbers indicate that you would need an interrupt roughly > every 1 microsec. Not a chance.
Huh? If he sets the FIFO threshold to 64, then the interrupt frequency is 921600.0/10/64 == 1440Hz. If he sets it FIFO threshold to 96, then the interrupt frequency is 921600.0/10/96 == 960Hz. 960Hz should be no problem at all unless some of the other ISRs are running too long. -- Grant Edwards grante Yow! .. the MYSTERIANS are at in here with my CORDUROY visi.com SOAP DISH!!
cs_posting@hotmail.com wrote:
> On Mar 31, 5:37 pm, Derek Young <edu.mit...@dereky.nospam> wrote: > >> I believe this is caused by the Linux serial port interrupt handler not >> responding fast enough. > > Or not being relieved of the packet payloads fast enough by whatever > is > supposed to consume them. > >> Does anybody know of a simple way to modify the priorities of interrupts >> in Linux? I don't mind recompiling the kernel, but I don't have a lot >> of expertise in that sort of thing. > > You'll want to go looking around in the processor / board specific > code, > and especially the serial port driver, perhaps plus whatever > programs the interrupt hardware. Look in places like > > drivers/serial > drivers/char > arch/processorname/ > >
I've done some poking around through drivers/serial and drivers/char, but I couldn't find anything that looks like it would control the interrupt priority. I did see something that defines the software buffer size (I think it's supposed to be 8K). But I'll look through arch/... to see if there's anything there. Thanks... Derek
> If he sets the FIFO threshold to 64, then the interrupt > frequency is 921600.0/10/64 == 1440Hz. > > If he sets it FIFO threshold to 96, then the interrupt > frequency is 921600.0/10/96 == 960Hz. 960Hz should be no > problem at all unless some of the other ISRs are running too > long. >
Thanks everyone for all the responses so far... Yes, I feel like there should be plenty of time to handle the interrupts. But from what I understand (which isn't a whole lot mind you :P), Linux isn't strictly a real-time OS. It doesn't normally have a preemptible kernel (I've turned on the "experimental" preemptible kernel flag) and it doesn't really have a standard way to tweak interrupt priorities. Was wondering if anybody knew of a straight-forward hack. I just want the serial port ISR to get priority over the device driver ISRs. Derek
On Apr 1, 10:23 am, Derek Young <edu.mit...@dereky.nospam> wrote:

> Was wondering if anybody knew of a straight-forward hack. I just want > the serial port ISR to get priority over the device driver ISRs.
For which you need to find the code that sets up the interrupt hardware. Another thing worth doing is looking in the processor/chipset manual and figuring out what registers would have to be programmed to do what you want. Then figure out what linux calls those registers (it will be in a board-specific include file), then grep the source tree for that name...
On 2008-04-01, Derek Young <edu.mit.LL@dereky.nospam> wrote:

> Yes, I feel like there should be plenty of time to handle the > interrupts. But from what I understand (which isn't a whole > lot mind you :P), Linux isn't strictly a real-time OS. It > doesn't normally have a preemptible kernel (I've turned on the > "experimental" preemptible kernel flag) and it doesn't really > have a standard way to tweak interrupt priorities. > > Was wondering if anybody knew of a straight-forward hack. I > just want the serial port ISR to get priority over the device > driver ISRs.
Changing ISR priority isn't going to make any difference. It only determines which of two pending interrupts get serviced. It doesn't allow "higher" priority interrupts to preempt lower priority ones. If a low-priority ISR runs for a long time, it's still going to block high-priority ISRs for the whole time it's running. -- Grant Edwards grante Yow! As President I have at to go vacuum my coin visi.com collection!
Grant Edwards wrote:
> .... > Changing ISR priority isn't going to make any difference. > > It only determines which of two pending interrupts get > serviced. It doesn't allow "higher" priority interrupts to > preempt lower priority ones. If a low-priority ISR runs for a > long time, it's still going to block high-priority ISRs for the > whole time it's running.
Sadly true, except on 68k/coldfire platforms. Some newer PPC parts from Freescale offer separate mask bits for two interrupts (6809 F and I like), which is not bad either. Of course if the system has been designed properly and written properly (are they ever in commecrial land?... :-) ), every IRQ handler would reenable IRQ after a few cycles only - some of the Freescale PPC parts have a good priority encoder in front of the core IRQ input and things will then in effect be as good as in a 68k/CF. But good luck enforcing that if more than 1 person is doing the work... -). Dimiter ------------------------------------------------------ Dimiter Popoff Transgalactic Instruments http://www.tgi-sci.com ------------------------------------------------------ http://www.flickr.com/photos/didi_tgi/sets/72157600228621276/ Grant Edwards wrote:
> On 2008-04-01, Derek Young <edu.mit.LL@dereky.nospam> wrote: > > > Yes, I feel like there should be plenty of time to handle the > > interrupts. But from what I understand (which isn't a whole > > lot mind you :P), Linux isn't strictly a real-time OS. It > > doesn't normally have a preemptible kernel (I've turned on the > > "experimental" preemptible kernel flag) and it doesn't really > > have a standard way to tweak interrupt priorities. > > > > Was wondering if anybody knew of a straight-forward hack. I > > just want the serial port ISR to get priority over the device > > driver ISRs. > > Changing ISR priority isn't going to make any difference. > > It only determines which of two pending interrupts get > serviced. It doesn't allow "higher" priority interrupts to > preempt lower priority ones. If a low-priority ISR runs for a > long time, it's still going to block high-priority ISRs for the > whole time it's running. > > -- > Grant Edwards grante Yow! As President I have > at to go vacuum my coin > visi.com collection!

Memfault Beyond the Launch