Quantcast
Channel: Processors
Viewing all articles
Browse latest Browse all 149015

Forum Post: RE: AM335x Industrial SDK 1.1.0.1 CPSW Driver Issue

$
0
0

Vinesh,


An update on what I have done.  I have tried  a couple more workarounds.  A terrible hack that prevents the problem is a delay (busy wait) in the function CPSW_TxServiceCheck (found in cpsw_impl.c) before the call to read the completion pointer register.  I put a simple for loop delay before this line:

Desc = CPSWCPDMATxCPGet(pd->Config.baseConfig.cpdma_base, i);

With the delay in place, the read of the register always comes back correct.  The seems to indicate that the either 1) somehow the ISR is being called before the CPSW is done or 2) the CPSW peripheral is interrupting before it has properly set the completion pointer register value.

As a less bad workaround, I updated the function emacDequeueTx (also found in cpsw_impl.c) to check for the error condition.  It ensures the pdc->DescCount is greater than or equal to the calculated descriptor count (which the function stores in the variable i).  If that condition is not met, the second half of the function is skipped.  The comment in the code explains why the workaround works.  Code is: 


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

    /* Turn i into a descriptor count */
    if( j < i )
        i = (i-j)/sizeof(CPSW_Desc);
    else
        i = pdc->DescMax - ((j-i)/sizeof(CPSW_Desc));

   /************ Addition - Josh Warr ***************************/
    /* If DescCount is not greater than or equal to the number of descriptors
       being acked, we must be looking at an old ack (t has been observed that
       the Tx ISR is sometimes called before the Tx CP register reads
       correctly). In this situation, we don't want to adjust DescCount, free
       the buffers, or start any outstanding descriptors. Since in this condition the CP ack will be
       different than what the port has written, per the spec the interrupt
       will remain asserted, and we will recover in a future call to the
       interrupt handler.*/
    if (pdc->DescCount >= i)
    {

   /************ End Addition - Josh Warr ***************************/

      if (pdc->DescCount == 0)
        i = 0;
      else
        pdc->DescCount -= i;    
        /* Pop & \nFree Buffers 'till the last Descriptor */
        while (((int)(i--)) > 0)
        {
            /* Recover the buffer and free it */
            pPkt = pqPop(&pdc->DescQueue);
            if (pPkt)
                (*localDev.Config.pfcbFreePacket)(pdc->pd->hApplication,pPkt);
        }

        /* If the transmitter stopped and we have more descriptors, then restart */
        if ((PktFlgLen & CPDMA_BUF_DESC_EOQ) && pdc->DescCount)
        {
            CPSWCPDMATxHdrDescPtrWrite(localDev.Config.baseConfig.cpdma_base, CPU_TO_HW(((Uint32)pdc->pDescRead)), pdc->chInfo->chNum);
        }

        /* Try to post any waiting TX packets */
        if (pdc->WaitQueue.Count)
            emacEnqueueTx(pdc);

   /************ Addition - Josh Warr ***************************/

    }

    else
    {
      gl_retry_count++;
    }

   /************ End Addition - Josh Warr ***************************/


}

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

You can see that I added the global variable gl_retry_count to verify that the if condition is indeed preventing execution of those lines.  As I run my application, gl_retry_count continually increases.

Any luck duplicating this issue on your end?  Any suggestions for a cleaner workaround?

Thanks

--Josh


Viewing all articles
Browse latest Browse all 149015

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>