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; }