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.

BIOSPSP SPI 8-bit Write Blocks Forever

Other Parts Discussed in Thread: SYSBIOS

I have a SPI in DMA mode setup to communicate to an ADC in 8 bit mode. My problem is that a call made to GIO_write is blocking my task forever. The blocking would occur almost immediately or after a minute of runtime. I have not noticed or try to pinpoint if GIO_read also causes the block. I am about 90% certain that it is hanging because a callback function is never called to signal the write to end. However, I checked the EDMA EMCR register to see if an event was missed for some reason, but I do not see any bits set. 

I have suspicion that there is some sort of timing issue because the blocking occurs less often when I change several optimization settings with my BIOS/SPI libraries or added Log statements. For example, I tried compiling my SYSBIOS with no optimization "-Ooff" and got rid of the "--optimize_with_debug" as well. The SPI was able to run throughout a whole night without problems. 

I also recompiled my SPI lib with some Log statements to attempt to debug this problem, but the blocking would occur less often again (maybe once every 45 minutes). This made it much harder to diagnose since the more I wanted to see what was wrong, the less the problem would appear.

I do not suspect that the initialization or the use of the SPI is incorrect because this was all fully functional when we were running in DSPBIOS

I am currently trying to rollback my SPI src files to vanilla and continually add bug fixes to see if it somehow broke 8-bit transfers. Then I will try to go to the newest SYSBIOS version (although I did not see any relevant fixes in the release notes). 

Anyone have any ideas as to what could cause my GIO_write never getting the signal to exit? Any help is greatly appreciated!

=================================================================================================

Here are the versions of libs I am currently using---

DSP: C6748
SYSBIOS: 6_34_04_22

BIOSPSP: 3_001_01_00

EDMA: 2_11_06_01

Current spi src files I'm building the lib from:

 8255.Spi.c

3264.Spi_edma.c

Spi.c and spi_edma.c has been modified from the vanilla version to include bug fixes found in other posts to make 12 and 16 bit transfers to work.

----------------------------------------------------------------------------

Here is the configuration---

Spi0Params = Spi_PARAMS;

Spi0Params.hwiNumber = 8;
Spi0Params.spiHWCfgData.intrLevel = FALSE;
Spi0Params.opMode = Spi_OpMode_DMAINTERRUPT;

Spi0Params.outputClkFreq = 2000000; //??
Spi0Params.loopbackEnabled = FALSE;
Spi0Params.edmaHandle = NULL;

Spi0Params.enableCache = true;
Spi0Params.spiHWCfgData.pinOpModes = Spi_PinOpMode_SPISCS_4PIN;
//Spi0Params.spiHWCfgData.pinOpModes = Spi_PinOpMode_3PIN;

Spi0Params.spiHWCfgData.configDatafmt[0].charLength = 8;//
Spi0Params.spiHWCfgData.configDatafmt[0].clkHigh = FALSE ;// polarity = 0
Spi0Params.spiHWCfgData.configDatafmt[0].lsbFirst = FALSE;//
Spi0Params.spiHWCfgData.configDatafmt[0].oddParity = FALSE;
Spi0Params.spiHWCfgData.configDatafmt[0].parityEnable = FALSE ;
Spi0Params.spiHWCfgData.configDatafmt[0].phaseIn = FALSE;//TRUE ;// phase = 1
Spi0Params.spiHWCfgData.configDatafmt[0].waitEnable = FALSE;
Spi0Params.spiHWCfgData.configDatafmt[0].wDelay = 0;

  • I have tried rolling back my SPI src files and recompiling, but that did not work. Another thing is that I thought this was causing this was the 8-bit mode, but I noticed that another part of my application also uses SPI in 8-bit mode to write to a DAC and it works fine. The only difference between the two devices is that the broken one uses a GPIO line for chip select and the phasein flag is false.

  • Hi Joe,

    As you know, the Spi driver is designed to enable Rx/Tx EDMA even thought app does not submit GIO with valid in/out buffer (via Spi_DataParam).
    For write case, app sets Spi_DataParam.inBuffer with NULL, but the driver enable Rx EDMA channel with his local buffer.
    Driver posts GIO related semaphore only when both Rx and Tx transfers have been completed.
    Even though EDMA had something errors during the transfers, I think EDMA callbacks (Spi_localCallbackTransmit/Spi_localCallbackReceive) would happen
    with error state in edmaStatus and then driver would post GIO related semaphore. So, GIO_write should return with error in this case. 

    My suspicion here is missing interrupt itself. You may be able to confirm this by checking EVT96 status.
    Please check the following manual.
    http://www.ti.com/lit/ug/sprufk5a/sprufk5a.pdf
     
    7.2.3.2 Interrupt Error Event 

    Also, you may be able to get success if you assign rx/tx app buffers to internal memory. 

    Lastly, you are using 8bit SPI with EDMA, so if you configured Spi_DataParam.bufLen with very small value, DMA mode may be too much.
    POLLING mode may be a one of solutions.

    Kawada 

  • Hi Naoki,

       Thank you for the suggestions, but it did not work. There are no missing interrupts when this block happens. I cannot set it to POLLING mode because the app does not have enough time to dedicate to it. 

       I hooked up an o-scope to the Data transmit line and I can see the data is transmitted successfully when the blocking happens, but the CS line is never reset to HIGH. 

       From what I see in the Spi_localCallbackTransmit, a blocking case could happen if the channel handle is NULL or edma status is INCOMPLETE and/or Spi_RX_EDMA_CALLBACK_OCCURED is false. Those two cases would mean my GIO callback function is never called and ends up blocking. This also means that my GPIO CS line stays low, which is also what I see on the o-scope. 

       What I found is that there is some amount of delay I must have between each GIO_write or the blocking would occur. I am currently going with this workaround using Task_sleep(), but it would be nice to know what is causing this.

  • Hi Joe,

    I read a bit more about Spi driver code and I found that GIO write would not return if something EDMA errors happen.
    My assumption was incorrect. Sorry for that.

    As I mentioned before, Spi driver is always using both Rx ad Tx EDMA transfers even though app is using only Tx (GIO_write)
    And GIO_write would return only if both Rx and Tx EDMA transfers were completed without errors.

    Please take a look in Spi_localCallbackTransmit. This would complete IO (spi_localCompleteIOedmaCallback) only if (Spi_RX_EDMA_CALLBACK_OCCURED == instHandle->edmaCbCheck).
    Also, please take a look in Spi_localCallbackReceive. This would do that only if (Spi_TX_EDMA_CALLBACK_OCCURED == instHandle->edmaCbCheck).

    This means Spi driver completes IO from it's one of ISRs only when another side transfer (If Rx ISR, another side is TX ISR, and vice versa) has been completed successfully.
    So, who sets instHandle->edmaCbCheck to "CALLBACK OCCURED" state ? The answer is these ISRs but this is done only when edmaStatus is EDMA3_RM_XFER_COMPLETE. If you have something EDMA errors, EDMA LLD would pass edmaStatus without EDMA3_RM_XFER_COMPLETE via TCC callbacks (Spi_localCallbackTransmit / Spi_localCallbackReceive).

    So, I wonder if you had something EDMA errors during the transfer. Please note, just after the issue happened,
    EDMA errors might not be seen on EDMA error related registers via CCS. This is because EDMA LLD error interrupt
    had been handled and error bits on registers had been cleared.
    You can check if any errors are seen in edmaStatus in Spi callbacks, or check if the control comes to EDMA error
    callback (edma3CCErrHandler() in edma3resmgr.c from EDMA LLD package) 

    Kawada