This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Too much overhead on back-to-back SPI data reads

I am using pspdrivers_01_30_01 drivers  to communicate over the SPI to 4 other devices. I am using four of the chip select outputs. I need to read 32 bytes of data from each device in a quick sequence. Running the SPI port at 10MHz, the actual data read is approximately 27 micro seconds. but the total time from the start of one read to the next is over 188 micro seconds. What could be causing this much overhead? I do not have any other processes interrupting between the reads. The PSP example code I started with uses the GIO_write() to execute the data transfer. The code sequence is simply:

    dataparam->inBuffer     = loopRead1;
    dataparam->outBuffer    = loopWrite;
    dataparam->bufLen       = 32u;
    dataparam->dataFormat   = Spi_DataFormat_0;
    dataparam->flags        = Spi_CSHOLD;
    dataparam->chipSelect   = CHIPSELECT_1;
    GIO_write (spiHandle, dataparam, &size);
    dataparam->chipSelect   = CHIPSELECT_2;
    dataparam->inBuffer     = loopRead2;
    GIO_write (spiHandle, dataparam, &size);
    dataparam->chipSelect   = CHIPSELECT_3;
    dataparam->inBuffer     = loopRead3;
    GIO_write (spiHandle, dataparam, &size);
    dataparam->chipSelect   = CHIPSELECT_4;
    dataparam->inBuffer     = loopRead4;
    GIO_write (spiHandle, dataparam, &size);

This does correctly read all four devices - but it is too slow. If the overhead was 30 micro seconds or less instead of 161 micro seconds than my application would work. The code is running on an OMAP L-138, 300Mhz, CCS3.3.81.6, CGT 6.1.7, DSPBios 5.33.03

The SPI Delay register is set to all zeros. The WDELAY is also set to zero.

We are using the 4-pin with CS mode.

Can you help explain the overhead of using the GIO_write driver for the SPI transfer? 

  • Hi,

    The overhead of waiting for each GIO_Write() to complete can be minimized by requesting data read for all the four devices using GIO_submit() with the specified call back structure, Since the GIO_submit() with the callback structure is an asynchronous call. This will make all the four request to be queued in the driver and GIO_write() overhead will be minimized to a certain extent.

    A template would look like:-

      

    /* Declare four callbacks for four requests  - refer to ti/bios/include/gio.h for type definitions*/

    struct GIO_AppCallback spiCallback1;

    struct GIO_AppCallback spiCallback2;

    struct GIO_AppCallback spiCallback3;

    struct GIO_AppCallback spiCallback4;

     

    spiCallback1.fxn = &callback_fxn1;

    spiCallback1.arg = &callback_arg1; /* note that this is a pointer to a user (reference) variable */

    spiCallback2.fxn = &callback_fxn2;

    spiCallback2.arg = &callback_arg2; /* note that this is a pointer to a user (reference) variable */

    spiCallback3.fxn = &callback_fxn3;

    spiCallback3.arg = &callback_arg3; /* note that this is a pointer to a user (reference) variable */

    spiCallback4.fxn = &callback_fxn4;

    spiCallback4.arg = &callback_arg4; /* note that this is a pointer to a user (reference) variable */

     

    #define GIO_SPI_CMD IOM_WRITE

        Dataparam1->inBuffer       = loopRead1;

        Dataparam1->outBuffer    = loopWrite;

        Dataparam1->bufLen         = 32u;

        Dataparam1->dataFormat= Spi_DataFormat_0;

        Dataparam1->flags              = Spi_CSHOLD;

       

        Dataparam1->chipSelect   = CHIPSELECT_1;

        GIO_submit (spiHandle, GIO_SPI_CMD, dataparam1, &size, &spiCallback1 );      /* This would return IOM_PENDING/IOM_COMPLETED and hence check for anything else which indicates error. The actual status of the transaction comes up in the callback */

      Dataparam2->chipSelect   = CHIPSELECT_2;

       Dataparam2->inBuffer     = loopRead2;   

       GIO_submit (spiHandle, GIO_SPI_CMD, dataparam2, &size, &spiCallback2 );         /* This would return IOM_PENDING/IOM_COMPLETED and hence check for anything else which indicates error. The actual status of the transaction comes up in the callback */

     

       Dataparam3->chipSelect   = CHIPSELECT_3;

       dataparam3->inBuffer     = loopRead3;

       GIO_submit (spiHandle, GIO_SPI_CMD, dataparam3, &size, &spiCallback3 );     /* This would return IOM_PENDING/IOM_COMPLETED and hence check for anything else which indicates error. The actual status of the transaction comes up in the callback */

     

       Dataparam4->chipSelect   = CHIPSELECT_4;

       Dataparam4->inBuffer     = loopRead4;

       GIO_submit (spiHandle, GIO_SPI_CMD, dataparam4, &size, &spiCallback4 );     /* This would return IOM_PENDING/IOM_COMPLETED and hence check for anything else which indicates error. The actual status of the transaction comes up in the callback */

     

    Please also, not that since these are asynchrounous calls, which means that they just queue the packet to the driver and return (the actual end of transaction indicated in the callback), the user needs to provide separate buffer related arguments in the GIO_submit(). Else the packet may get corrupted.

     

    This way, since the driver is pre-queued with requests the loading of these buffers happens faster in the driver layers and there is no need to wait in the application for completion of each single packet and then queueing the next.

    Regards,

    Sandeep Krishnaswamy

  • Thank you for your suggestion, but this does not reduce the overhead enough for our application. The total time for each packet read was still over 170 micro seconds (original time was 188 micro seconds).

    I was only able to execute two GIO_submit() before getting an error return condition (-1).  It does not appear that it is worth the effort to determine the cause of these error since this appraoch did not provide the increase inresponse time that is needed.

    If you are anyone else has other suggestions to siginificantly reduce the over head, please let me know.

    Our plan now is to throw away the PSP platform and build our own SPI/EDMA driver driving the SPIDAT1 register directly from a 32-bit data transfer.