Data acquisition fails on xscale with embedded linux

Hi there, I'm starting out with embedded linux using an Arcom Viper, PC104 single board computer, running a 400MHz pxa255 CPU. Our application uses an auxiliary pc104 board to collect data in real-time from some ADC's which is then buffered in a hardware FIFO. Once the FIFO is almost full it issues an interrupt to the procesor which then reads the board and stores the data to file on compact flash. A fairly common task for embedded systems.

Our data rate averages 160KB/S and almost-full interrupts to read the FIFO occur every 45mS. It normally takes about 3.5mS to read the data from the FIFO, leaving plenty of time to get on with other processes. My problem is that at some point it takes much longer to read the FIFO, sometimes > 50mS, at which point the application fails because data is lost. The failure point is after the application has written about 5MB to compact flash. From scoping our board it is clear that, at the failure point, the CPU is reading the board but extreamly slowely.

I have written a simple device driver which blocks a read call from userland by sleeping until woken by the interrupt handler. I have included the read part from the driver here as I believe it's the meat of the code. The userland code just sits in a loop, reading the board then writing to CF.

Do you know if there is a way, other than moving to a RTOS of ensuring this code is given priority to read the hardware? I know that if I could ensure this then there would still be plenty of time for file operations and other essential processes.

Thanks for your help! Warm regards,

alex

static ssize_t syrn_read( struct file *filp, char *buf, size_t len, loff_t *ppos ) { int i,j; volatile unsigned long jifs; unsigned long flags=0; WORD dataIn, csr_read;

// clear interrupt latch on fifo board inw(io_irqclear);

jifs = jiffies; interruptible_sleep_on_timeout(&my_queue, 500); if (jiffies >= (jifs + 500)) { kfree(kbuf); spin_lock( &is_open_lock ); is_open=0; spin_unlock( &is_open_lock );

return -1; }

spin_lock_irqsave( &syrn_lock, flags );

j = 0; for (i = 0; i < (len/2); i++) {

dataIn = inw(io_base); kbuf[j]= (char) ((dataIn & 0xFF00) >> 8); kbuf[j+1]= (char) (dataIn & 0x00FF); j += 2; }

if( copy_to_user( buf, kbuf, len ) != 0 ) { return -EFAULT; }

spin_unlock_irqrestore( &syrn_lock, flags );

// clear interrupt latch on fifo board inw(io_irqclear);

return i; }

Reply to
alex p
Loading thread data ...

Have you tried dumping the file to RAM instead of the CF card as a test? We had a similar system that was streaming data to a CF at, oddly enough, a rate very close to 160 KB/s. We would see short windows of time where the reading of our data stream seemed to slow down, and one of the things we ended up figuring out was that we were seeing processing blips when data was actually getting flushed down to disk by Linux (which obviously makes sense). In our case, we were writing to a DiskOnChip module, but nonetheless, we would see a pretty large spike where the DOC driver owned all MIPS when it was actually getting data down to disk.

The DOC "daemon" that controlled the DOC actually ran at an elevated priority (equivalent to nice'ing themselves I think), which is why it starved us. You could always play games with nice to try and force certain processes to get higher priority.

Try dumping your files to a RAM disk if you have the space. This way you can be sure that the odd blips you are seeing aren't due to the flash writes.

Good Luck, John O

Reply to
jro

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.