Post Go back to editing

SPI Callback Question

Hi,

I'm trying to use the Blackfin SPI interface to feed data to an AD5066 DAC. I have SPI set up in interrupt mode with a callback function set. My expectation is that for every transceiver submitted via adi_spi_SubmitBuffer(), my callback function will be called with pArg pointing at a transceiver that has completed.

Usually, if I submit a second transceiver before the callback for the previously submitted transceiver, I get two callbacks; one for each transceiver submitted.

Occasionally, however, if I submit a second transceiver before the first one has completed, I see no callback for the second transceiver. I always (so far at least) see a callback for the first transceiver.

Is this normal? If it's normal, how do I know when transmission of the second transceiver has completed?

Thanks.

  • Hello,

    To breakdown the issue,please follow the below debugging steps.

    Kindly verify whether the second transceiver is submitted successfully or not by debugging the statement in submit buffer API() inside adi_spi_bf6xx.c file
    Result = pDevice->pDevData->FuncTable.pfSpiSubmitBuffer(pDevice, pTransceiver);

    Because adi_spi_SubmitBuffer API doesn't return a kind of enumeration return code like 'buffer not Submitted'.

    Callback function will be called even if error occurs during transaction. But without submission ,we are not able to receive callback.So we need to debug inside adi_spi_SubmitBuffer API whether our transceiver is properly submitted or not.

    Usually to avoid this kind of situation,second transceiver should be submitted after callback is occurred for previous transceiver submission which will free up the transceivers in API.

    Kindly refer spi_flashreadback BSP example in below path which involves the submission of two transceivers using Callback mode.
    <Installation path>\Analog Devices\ADSP-BF707_EZ-Board-Rel1.0.1\BF707_EZ-Board\Blackfin\Examples\drivers\spi

    If you are still facing the problem,please provide us code flow or snippet which helps us to look on your SPI transceiver configurations.

    This information will be helpful for us to assist you better

    Best Regards,
    Santha kumari.K

  • After the problem occurs, I see the following:

    pDevice->pDevData->pActiveTransceiver == NULL

    pDevice->pDevData->pPrimaryTransceiver == NULL

    pDevice->pDevData->bPrimaryProcessed == false

    pDevice->pDevData->pSecondaryTransceiver == the address of the transceiver for which I never received a callback

    pDevice->pDevData->bSecondaryProcessed == false

    This is the state several successful transceiver submissions and callbacks *after* the failed secondary callback. Any thoughts?

    Question: does the fact that pSecondaryTransceiver is set to the address of the submitted-but-failed-callback transceiver mean that the transceiver submission was successful? I'm not getting any error from adi_spi_SubmitBuffer() but it sounds like you're telling me that no error is expected even when the submission fails!

    I'll take a look at your sample code and see if I can figure it out, or send a sample program of my own demonstrating the problem.

    Thanks for your help.

    -David Shanks

  • In your sample code, it looks like you're never submitting a second transceiver before the first transceiver completes. From spi_flashreadback.c, in CallbackTest() lines 324-339:

    if(Result == 0u)
    {
    /* non-blocking mode submission */
    Result = (uint32_t)adi_spi_SubmitBuffer(phSPI, pTestArray[TestIndex]);
    }
    if(Result != 0u)
    {
    /* set flag as if test has completed */
    CallbackTestEndFlag = true;
    }
    /* wait here until callback detects a transceiver processed */
    while(CallbackFlag != true)
    {
    /* MISRA compliance */
    Result = 0u;
    }


    If I'm reading that correctly, you submit a buffer and then busy-wait in the while loop for the received data to arrive. Yes? You never submit a second buffer before the first one has been processed.

    In my application, I have a FIFO of data to be transmitted via the SPI (transmit only, no SPI receive or prolog). A routine called from the main loop pulls data from the FIFO, sets up a transceiver for the data, and calls adi_spi_SubmitBuffer(). It does this repeatedly until the FIFO is empty or it sees a non-zero return value from adi_spi_SubmitBuffer().

    QUESTION: You say "adi_spi_SubmitBuffer API doesn't return a kind of enumeration return code like 'buffer not Submitted'." I thought a return value of ADI_SPI_QUEUE_FULL means "buffer not Submitted." Am I wrong? What does a return of ADI_SPI_QUEUE_FULL mean? I never see a non-zero return value from adi_spi_SubmitBuffer(). On the other hand, I have instrumented my code and know that it never tries to submit more than two transceivers to the SPI driver via adi_spi_SubmitBuffer().

    Thanks again,

    -David Shanks

  • Hello David,

    We have tried to implement your application scenario where we are submitting tranceivers(contains only Tx) before callback occured.

    Whenever data transaction is completed,it will rise data handler which will further call the UpdateQueue API.

    UpdateQueue API free up the processed tranceivers that we submitted.In case of failure of rising handler or submitting tranceiver before rising callback,we are not able to free up the previous submitted tranceivers.

    Now in this situation when we try to submit a new tranceiver before the callback processing,adi_spi_SubmitBuffer API returns ADI_SPI_QUEUE_FULL.

    It means that primary and secondary tranceivers are not Null.There is no space to hold the upcoming tranceiver until they are free.

    Kindly find the attached screenshots and example project for your reference. Please try and let us know how you are getting on

    Regards,
    Santha kumari.K

    Ezone_thread_-_SPI_Callback_Question.zip

  • I am unsure of root cause, but I believe I have resolved the problem by disabling interrupts before calling adi_spi_submitBuffer(), re-enabling after.

    I also noted your response to another engineer in which you said that submitBuffer should not be called from within the callback, though I think that thread was about SPORT, not SPI. Is that a limitation? Can I not call adi_spi_submitBuffer() from inside the SPI callback? If yes, it is a limitation from all callbacks? For example, could I call adi_spi_submitBuffer() from inside a timer callback?

    Thank you for your help,

    -David Shanks

  • Hello David,

    Kindly find the attached code which will help you to understand the buffer submission in SPI callback.
    You can able to submit SPI buffer in other peripheral/services(Timer) callbacks but we need to take care of how we free up the submitted SPI tranceivers.

    Please note that blocking mode APIs are not allowed inside any callbacks.So in your scenario,freeing of transceivers has to be done by registering a SPI callback. Then you can able to submit SPI transceivers inside in any other callbacks which will be free by SPI callback.

    kindly ensure that SPI callback must have high priority than current executing callback,otherwise SPI callback would not be able to call(In case of current callback is executing very often) and hence transceivers will not get freed.

    Kindly refer below CCES help path for further information about Callback mode.
    CrossCore® Embedded Studio 2.8.3 > System Run-Time Documentation > Device Drivers User Guide > Low-Level Driver API Reference > Using Callback mode.

    If you face any issue,please provide us code which will replicate issue.

    Regards,
    Santha kumari.K

    submission in callback.zip