Quantcast

Fwd: SPI driver Problem... Preempt, Maybe?

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Fwd: SPI driver Problem... Preempt, Maybe?

franciscopinho
Hello Guys,

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.

Can someone please help me on this one?


------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_feb
_______________________________________________
gumstix-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gumstix-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fwd: SPI driver Problem... Preempt, Maybe?

Scott Ellis
All spi_sync() does is hide the details of setting up a completion
handler for you. It still calls spi_async() to submit the work to
the spi queue.

Are you taking this into account?






Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fwd: SPI driver Problem... Preempt, Maybe?

franciscopinho
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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fwd: SPI driver Problem... Preempt, Maybe?

Scott Ellis
You were asking about latencies.

Here's some psuedocode, does it agree with what you think is happening?

gpio_irq()
    for each adc
        set gpio for this adc chip select
        spi_sync()
            spi_async()
                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
                spi_async() returns

        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
sleep.

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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fwd: SPI driver Problem... Preempt, Maybe?

Scott Ellis
Sorry, reread what I wrote and I screwed it up a little

Here's what I meant for the pseudo code

gpio_irq()
    for each adc
        set gpio for this adc chip select
        spi_sync()
            calls spi_async()
                submits your spi operation to spi queue
                sets up completion handler                
                spy_async returns

            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 in spi_sync() call
            spi_sync() returns

        unset gpio for this adc chip select

    end for

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Fwd: SPI driver Problem... Preempt, Maybe?

franciscopinho
In reply to this post by Scott Ellis
Thanks a lot for the quick reply,

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?

static irqreturn_t spike_thread_fn(int irq, void *dev_id)
{
spin_lock_irqsave(&spike_dev.spi_lock, flags);
        spi_message_init(&spike_ctl.msg);
        memset(spike_ctl.rx_buff, 0, SPI_BUFF_SIZE);
        spike_ctl.transfer.tx_buf = spike_ctl.tx_buff;
        spike_ctl.transfer.rx_buf = spike_ctl.rx_buff;
        spike_ctl.transfer.len = 27;
        spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg);

        if(count>=1000){
               
                spike_buf[64000]='y';
                t=0;
                count=0;
                memmove(spike_buf,data,64000);
                sclk_out_word_ret24();
               
        }
        else{
                sclk_out_word_ret24();
        }
               
 spin_unlock_irqrestore(&spike_dev.spi_lock, flags);
        return IRQ_HANDLED;
}

static int sclk_out_word_ret24(void){

gpio_set_value(CS4_PIN,1);
gpio_set_value(CS1_PIN,0);
spi_sync(spike_dev.spi_device, &spike_ctl.msg);
for(k=3;k<25;k+=3){
                data[t]=spike_ctl.rx_buff[k];
                data[t+1]=spike_ctl.rx_buff[k+1];
                t+=2;}

gpio_set_value(CS1_PIN,1);
gpio_set_value(CS2_PIN,0);
spi_sync(spike_dev.spi_device, &spike_ctl.msg);
for(k=3;k<25;k+=3){
                data[t]=spike_ctl.rx_buff[k];
                data[t+1]=spike_ctl.rx_buff[k+1];
                t+=2;}

gpio_set_value(CS2_PIN,1);
gpio_set_value(CS3_PIN,0);
spi_sync(spike_dev.spi_device, &spike_ctl.msg);
for(k=3;k<25;k+=3){
                data[t]=spike_ctl.rx_buff[k];
                data[t+1]=spike_ctl.rx_buff[k+1];
                t+=2;}

gpio_set_value(CS3_PIN,1);
gpio_set_value(CS4_PIN,0);
spi_sync(spike_dev.spi_device, &spike_ctl.msg);
                for(k=3;k<25;k+=3){
                data[t]=spike_ctl.rx_buff[k];
                data[t+1]=spike_ctl.rx_buff[k+1];
                t+=2;}
count++;
        return 0;
}

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.
Please help.
Loading...