I am developing a biosignals platform using Overo. I developed a driver and I want to read 4 ADC's using the SPI port. The ADC's that i am trying to use are the ADS1298 from Texas. This ADC provides a Data Ready signal to syncronize the readings. I programmed the ADCs for 1Ksps, so in each ms the signal goes low. I programmed a Interrupt by using the request_threaded_irq() to go with this Data Ready Signal, and inside the handler I am using the SPI_sync() because I need to read the data and Chip Select the ADCs progressibly. The problem that I am having is that in each (more or less) 8 interrupts, the time taken to read the ADC goes to 4 times higher. For example, I measured an aproximate time of about 245 us to read the 4 ADC's, but in each 8 interrupts the time taken is about 1 ms.
The ADC are connected in cascade mode. Is this problem related with the PREEMPT configuration? I am using 2.6.34 Kernel, with no preemption configured. I disabled the spidev, and the other drivers that use the SPI bus.
Thanks for the quick reply.
Well, i am using the spi_sync () because in each interrupt i need to chip select each adc and read the data from them. Iam using 4 gpio for chip select. So in each interrupt i chip select the adc and use the spi_sync() , and because i am using 4 adcs i am doing this 4 times before the irq handler finishes. By using the spi_async () do you think i will not have the diferent read timming problem? Spi_async() returns imediatly , but do you think the time to readback the data from the adcs in the completion handler will be more accurate?
Thanks in advance.
Here's some psuedocode, does it agree with what you think is happening?
for each adc
set gpio for this adc chip select
submits your spi operation to spi queue
sets up completion handler
your thread is put to sleep waiting on completion
... sometime later ...
spi worker thread wakes up
does any pending spi operations
spi thread signals completion
scheduler marks your thread runnable again
... sometime later ...
your thread wakes
unset gpio for this adc chip select
You don't have tight control on how long your thread will be sleeping,
since both wakeups happen when the kernel scheduler chooses.
Calling spi_async() directly won't help you because you still need to
manually toggle a gpio line outside of the spi worker thread. (Because
you need 4 CS lines and those aren't available.)
So if you really can't change the hardware situation, I'd modify the
the kernel spi driver to handle the custom gpio toggling for you.
Then you could submit all yours reads in 1 block and have only one
Take a look at omap2_mcspi_work(). That's where you would modify.
Just throwing out an idea.
I haven't seen your code and there could be something else going on.
And yes, your pseudocode reflects exactly my code.
So in your opinion I should modify the omap2_mcspi_work() in omap2_mcspi.c file, or use the omap2_mcspi_work() function? I am sorry but i am a newbie, can you please be more specific?
These are my irq handling functions. The for cycles are due to the fact I am pulling out the 2 most significant bytes from the 24 bits word of each read. when the number of interrupts achieves 1000 I copy the data to a second memory buffer that is mapped. I am using this strategy for a userspace script to access the data, copy and apply some algorithm. At this time i am stil not using the userspace script. (i am sorry about the "spike" name, and yes, i used your "Writing a Linux SPI driver" tutorial to develop my driver).
Do you think if I use a Real Time OP like xenomai, I would not have this problem?
Thanks a lot.