From: Kyle S. <ksc...@fo...> - 2008-06-05 20:01:22
|
Hello again Dave. My comments are interspersed below. Thanks for all of your help so far! On Thu, 2008-06-05 at 12:09 -0700, Dave Hylands wrote: > Hi Kyle, > > > irqreturn_t _i2s_svc_rx_int(int irq, void *dev_id) { > > > > // make sure we aren't interrupted while servicing the previous int > > _saimr_rx_int_disable(); > > > > int i = 0; > > unsigned int sample; > > > > // get the number of samples in the hardware fifo > > unsigned int sample_count = _sasr_get_rx_level(); > > How does _sasr_get_rx_level work? Is this talking to an external > device? Using i2c or SPI? It's simply a read from the SASR0 register where bits 15:12 hold the number of samples in the I2S hardware FIFO (there's actually a bit more to it than that because 0 can mean either empty or full). The full function is below at the end. > If it's doing bit-banged I/O then it probably has busy-wait delays, > which would be bad. No bit-banging since I'm using I2S (not to be confused with I2C), which has hardware support on the PXA270. The ISR should only be called when the hardware FIFO passes a certain level. The interrupt is generated by hardware. > If this is the case, you may want to launch a kernel thread which just > waits on a semaphore and does the real work. The isr would then just > signal the semaphore and nothing else. > > No context switches take place while the ISR is running, so if the ISR > was consuming 100% of the CPU, then it would behave the way you > describe. Is there a good method to 'step through' an ISR to find out where it could be hanging? I'm sampling at ~22kHz, so printk is of little use. The ISR and the implementation of read are really the only two complex functions in my driver so if things are going wrong, I suspect them first. I've included i2s_read below as well. Thanks for taking time out of your day to look at my buggy code :) Here's the full listing of the _sasr_get_rx_level function: short _sasr_get_rx_level(void) { unsigned int sasr0; short rfl; sasr0 = SASR0; rfl = (sasr0 & 0x0000f000) >> 12; if(rfl == 0) { if(sasr0 & 0x00000002) { // SASR0_RNE return 16; } } return rfl; } And here's the implementation of i2s_read: ssize_t i2s_read(struct file *filep, char __user *buf, size_t count, loff_t *offp) { int sz; // block while there is no data available to read if( !(filep->f_flags & O_NONBLOCK) ) { while( kfifo_len(fifo) < (sizeof(unsigned int) * count) ) { if( wait_event_interruptible(i2s_data_q, kfifo_len(fifo) >= (sizeof(unsigned int) * count)) ) { return -ERESTARTSYS; } } } // at this point there is data in the fifo b/c we're the only reader // copy data from fifo to user space // I added the __kfifo_get_user to avoid a unnecessary separate copy sz = __kfifo_get_user(fifo, buf, count * sizeof(unsigned int)); return sz; } Thanks again for your help! -- kyle |