Post Go back to editing

SPORT API operations

Category: Hardware

I have been able to get the SPORT loopback example running on the 408-EZKIT. In that example, the 1/2 SPORTs are opened, TX RX channels configured, Buffers submitted, TX RX channels enabled. The data is sent and received and the TX RX channels are disabled. All is well and good for a single transmission. I wanted to do more than a single transmission so I modified the code to operate as follows:

The 1/2 SPORTs are opened, TX RX channels configured, Buffers submitted, TX RX channels enabled and data is sent and received. I don't disable the TX RX channels and simply loop back to buffer submission and data sending. That loop operates correctly for 3 iterations and then fails buffer submission. Experimenting I found that I have to disable the TX RX channels before buffer submission. Is that correct behavior? Meaning a channel has to be closed before any subsequent buffer submission????

  • Hi,

    Our sincere apologies for the delay in response. Please find the details for your queries here

    >>>Meaning a channel has to be closed before any subsequent buffer submission????

    No, it is not necessary to close the particular SPORT before performing subsequent transactions.

    Please refer to the below snippet. Inside SPORT TX callback the processed buffers are submitted again to perform a continuous transaction. Please note that two TX buffers are used to transfer the data using adi_sport_SubmitBuffer() before enabling SPORT. So, once the first buffer is transferred, inside the callback, the same buffer will be submitted again using *pARG (which provides the processed buffer's address).

    static void TX_Callback(void *pCBParam, uint32_t Event, void *pArg)
    {
    switch(Event) {
    case ADI_SPORT_EVENT_TX_BUFFER_PROCESSED:
    adi_sport_SubmitBuffer(hSport_TX, pArg, Buffer_Size);
    break;
    default:
    break;
    }
    }

    Hope this helps.

    Best Regards,
    Santhakumari.K

  • That is exactly what I am doing but on the 3rd loop iteration, buffer submission fails.

    if((result = adi_sport_SubmitBuffer(hDeviceRx, nBufferRx0, SIZE_OF_RX_BUFFER*ALIGNMENT))!= ADI_SPORT_SUCCESS)
    {
            debugPrint("%s: Failed to submit the buffer for Rx channel: %d\r\n",__FUNCTION__, result);
    }
    else if((result = adi_sport_SubmitBuffer(hDeviceTx, nBufferTx0, SIZE_OF_TX_BUFFER*ALIGNMENT))!= ADI_SPORT_SUCCESS)
    {
            debugPrint("%s: Failed to submit the buffer for Tx channel: %d\r\n", __FUNCTION__, result);
    }

    else if((result = adi_sport_Enable(hDeviceRx,true))!= ADI_SPORT_SUCCESS)
    {
             debugPrint("%s: Failed to enable the Rx: %d\r\n", __FUNCTION__, result);
    }
    /* Enable the Data flow for Tx */
    else if((result = adi_sport_Enable(hDeviceTx,true))!= ADI_SPORT_SUCCESS)
    {
            debugPrint("%s: Failed to enable the Tx: %d\r\n", __FUNCTION__,result);
    }

    while(1)

    {

         while(nRxCallbackCounter == 0);

        if((result = adi_sport_SubmitBuffer(hDeviceRx, nBufferRx0,     SIZE_OF_RX_BUFFER*ALIGNMENT))!= ADI_SPORT_SUCCESS)
        {
            debugPrint("%s: Failed to submit the buffer for Rx channel: %d\r\n",__FUNCTION__, result);
        }

        if((result = adi_sport_SubmitBuffer(hDeviceTx, nBufferTx0, SIZE_OF_TX_BUFFER*ALIGNMENT))!= ADI_SPORT_SUCCESS)
        {
            debugPrint("%s: Failed to submit the buffer for Tx channel: %d\r\n", __FUNCTION__, result);
        }

    }

  • Hi,

    Can you please explain your application code flow. We suspect that sport is being enabled and continuously looking for the data. That could be the reason for getting an overflow and underflow error. Can you please try the below snippet and let us know how you are getting on. Here we are submitting buffers in a ping pong manner.

    volatile void *pGet_TX = NULL;
    volatile void *pGet_RX = NULL;

    static void TX_Callback(void *pCBParam, uint32_t Event, void *pArg)
    {
    switch(Event) {
    case ADI_SPORT_EVENT_TX_BUFFER_PROCESSED:

    pGet_TX = pArg;

    break;
    default:
    //Event
    break;
    }
    }

    static void RX_Callback(void *pCBParam, uint32_t Event, void *pArg)
    {
    switch(Event) {
    case ADI_SPORT_EVENT_RX_BUFFER_PROCESSED:

    pGet_RX = pArg;

    break;
    default:
    //Event
    break;
    }

    }

    int main()
    {

    // SPU Initialization
    // SPORT Initialization

    adi_sport_SubmitBuffer(hSport_TX, TX_BufferA, Size);
    adi_sport_SubmitBuffer(hSport_TX, TX_BufferB, Size);
    adi_sport_SubmitBuffer(hSport_RX, RX_BufferA, Size);

    adi_sport_SubmitBuffer(hSport_RX, RX_BufferB, Size);

    adi_sport_Enable(hSport_RX, true);
    adi_sport_Enable(hSport_TX, true);
    while(1)
    {
    void *pTX;
    void *pRX;

    if(pGet_TX != NULL)
    {
    pTX = (void *)pGet_TX;
    /* re-submit the TX buffer */
    adi_sport_SubmitBuffer(hSport_TX, (void *)pTX, Size;


    pGet_TX = NULL;
    }

    if (pGet_RX != NULL)
    {
    pRX = (void *)pGet_RX;
    /* re-submit the RX buffer */
    adi_sport_SubmitBuffer(hSport_RX, (void *)pRX, Size);

    pGet_RX = NULL;
    }
    };
    }

    Best Regards,
    Santhakumari.K

  • Hi,

    There really is no code flow to speak of. I am trying to understand how the APIs work with the sport interface. Our application will eventually be as follows:

    Format a packet of bytes anywhere between 64 to 1056. Send them out the sport interface. Do the same thing again, over and over. So, to test that scenario I send bytes out the transmit and externally loopback the SPORT interface. The XMT side is DMA mode and the receive side is interrupt mode. As the code snippet I submitted shows, XMT and RCV buffers are submitted, and the respective interfaces enabled. As soon as the XMT is enabled, data exits the SPORT interface which I verified with an oscilloscope.  Next iteration data is sent, 3rd iteration XMT buffer submission fails with error code 6 (ADI_SPORT_BUFFERS_NOT_SUBMITTED). It appears that I need to do something to free DMA descriptors. My assumption is that the DMA driver would free the descriptor once the data has been sent.

  • Hi,

    The internal architecture is the SPORT driver will clear the descriptor once the transfer is being completed. The adi_sport_SubmitBuffer() API will return ADI_SPORT_BUFFERS_NOT_SUBMITTED in two scenarios: if the API is called before the transfer is finished or if it is called more than twice for the same TX or RX buffers before enabling SPORTs. Please ensure that adi_sport_SubmitBuffer() API is being called once the transfer is completed successfully. This applies for both TX and RX buffer submissions.

    If you use only one adi_sport_SubmitBuffer() and resubmit it after the callback occurred then SPORT overflow or underflow event may occur due to the delay between completion of the SPORT transfers and resubmission. So, for continuous transactions in SPORT, the convenient way is to use adi_sport_SubmitBuffer() API maximum two times before enabling it. This will be working as a queue: once the transfer of the first buffer is completed, then the next buffer in the queue will start transferring the data. During this time, you can resubmit the transferred buffer using adi_sport_SubmitBuffer() API to maintain the continuous transaction. The same approach is followed in the snippet that we shared earlier. Could you please try to submit buffers as per our earlier mail.

    Hope this helps.

    Best Regards,
    Santhakumari.K

  • Remember I am using DMA to transmit. So I call adi_sport_SubmitBuffer() which sends data out the SPORT. I then delay 4 seconds call adi_sport_SubmitBuffer() delay 4 seconds and call adi_sport_SubmitBuffer() again but it fails with ADI_SPORT_BUFFERS_NOT_SUBMITTED . If I add a call to adi_sport_GetBuffer() before I delay, all is good. 

    Your code above uses callback for TX but that can't be used when DMA is active. So the question is, how do I know when the DMA transfer has completed?

  • Hi,

    Good to know that adi_sport_GetBuffer() works perfectly in your application. adi_xxx_SubmitBuffer API will return back to application and data transfer happens in the background.

    Application can optionally block by calling adi_xxx_GetBuffer API. This is a blocking function and wait till processed buffer is available. So, in your application, this API will return the processed buffer after the transfer has been completed.

    Please note that callbacks can also be registered for DMA mode transfers. You can use a callback function to determine when a SPORT DMA transfer has completed.

    The callback and adi_sport_GetBuffer() API cannot be used together. This API returns an error if a callback function is registered. Therefore, only one of this method can be used to determine when a SPORT DMA transfer has completed. Hope this helps.

    Best Regards,
    Santhakumari.V

  • Things are working well, thanks for your help. In our application we will be transmitting different size data lengths. I have the word size at 32, TX DMA and have noticed that complete data is only possible if the data size is a multiple of 4. Can we transmit data sizes that are NOT multiples of 4?

  • Hi,

    Glad to know that your application works fine now.

    Regarding data size, can you please let me know what value you are passing in "ALIGNMENT" Macro.

    if((result = adi_sport_SubmitBuffer(hDeviceRx, nBufferRx0, SIZE_OF_RX_BUFFER*ALIGNMENT))!= ADI_SPORT_SUCCESS)
    {
    debugPrint("%s: Failed to submit the buffer for Rx channel: %d\r\n",__FUNCTION__, result);
    }

    It is not mandatory that data size should be multiple of four.

    Because during transmission, call back will be hit when complete data has been drained out from DMA FIFO. For Ex: if the current data size is sixty seven 32bit data means, 67 data transactions will be happened and callback will be hit when xcount current register will become zero. Hope this helps.

    Best Regards,
    Santhakumari.K