AnsweredAssumed Answered

BF561 SPORT question

Question asked by AlexKates on Apr 26, 2011
Latest reply on Apr 28, 2011 by PrasanthR



I am working on an application  which involves a lot of communication between a Xilinx FPGA and a BF561.  The BF is running a video decoding/MPEG encoding process (which we got  from ADI), adding timing information and passing the data to the FPGA  over SPORT. We are running on custom hardware, not a EZ-Kit.


The  SPORT communications for BF are regular (1 ms) interrupts, which  trigger both RX and TX. RX is clocked by the FPGA, and BF drives the  clock on TX. RX is 13 64-bit words, TX is 1024. FPGA sees these as 4x as  many 8-bit words.


This  works great most of the time. Occasionally, we see a strange problem:  after DMAin the SPORT RX data, it seems to arrive shifted by as many as 3  words, in a circular fashion. That is, the value I expect to find in  Words [1,2,3,4,5] would actually be the value from Words [10,11,12,  0,1].


This  has been a long-standing and mysterious source of failures -- we might  have this error a couple times an hour when running the encoder  constantly.


In  our attempts to resolve it, we have tried a few things -- one of the  most mysterious, yet effective is putting a delay loop AFTER the RX DMA  in the interrupt, before attempting to do anything else with the data.  This unquestionably and significantly reduces the error. However, we  don't understand why it works. And it's still not 100% reliable.


Does anyone have any insight into why we might be having this communications  problem or what we can do about it? It is a significant issue in our  reliablility testing.


I'm including all of the SPORT settings, timings, etc. I've checked over them  really carefully and tried a number of variations (clock rate, etc),  with no benefit. We've also tried having a resistor on the RX clock  line, or no resistor on the clock -no difference.


Again, the settings must be generally fine, because 90% of the time, we don't have this error -- until we do.







1) SPORT and DMA:


/* InitSPORT() - Rx data from FPGA @28*16bits/period (448bits) */

void InitSPORT(void)


    /* Configure SPORT0 to Rx 28 16-bits/1 kHz. 1 external FS per packet */


    /* Sport0 receive configuration */

    /* External CLK, External Frame sync, MSB first */

    /* 16bit data, late FS, FS not required for every word,

       falling clock edge */

    /* Removed RFSR (requires frame sync for every word) */

    *pSPORT0_RCR1 = RCKFE | LARFS;       

    /* enable secondary register (RXSE) however

    this doesn't work when Rx'ing data > 16-bit */

    *pSPORT0_RCR2 = 0xf | RXSE;           


    /* Sport0 transmit configuration */

    /* Internal CLK, Internal FS, early FS, MSB first,

       8-bit data, enable 2ndary port */

    *pSPORT0_TCR1 = TCKFE | ITCLK | ITFS;    

    *pSPORT0_TCR2 = 0x7 | TXSE;               

    /* Set frame sync divisor.*/

    *pSPORT0_TCLKDIV = 1; //1 for 0.548ms interrupt

    *pSPORT0_TFSDIV = 0x3fff;

//    *pSPORT0_TCLKDIV = 3; //1 for 0.548ms interrupt

//    *pSPORT0_TFSDIV = 0x1fff;   


//    *pSPORT0_TCLKDIV = 1; //1 for 0.40ms interrupt

//    *pSPORT0_TFSDIV = 0x2fff;




void EnableSPORT(void)


    volatile SINT32 s32WaitDmaFinish;   


    /* Enable SPORT Rx DMA */

    /* enable rx DMA (acknowledged during ISR) */

    *pDMA2_0_CONFIG |= DMAEN;

    /* enable tx DMA (no ISR associated) */       

    *pDMA2_1_CONFIG |= DMAEN;       


    /* wait until dma transfers for spi are finished */

    for (s32WaitDmaFinish=0; s32WaitDmaFinish<0xaff; s32WaitDmaFinish++);   


    /* Enable SPORT Rx and Tx */

    *pSPORT0_RCR1 = (*pSPORT0_RCR1 | RSPEN);

    *pSPORT0_TCR1 = (*pSPORT0_TCR1 | TSPEN);






// Function:    Init_DMA                                                    //


//                                                                            //


// Description:    Initialize DMA2_0 in autobuffer mode to receive and DMA2_1     //


//                in autobuffer mode to transmit                                //




void Init_DMA(void)




    /* Set up DMA2 channel 0 to Sport receive */


    *pDMA2_0_PERIPHERAL_MAP = 0x0000;   


    /* Configure DMA2 channel0


       16-bit transfers, Interrupt on completion, Autobuffer mode;


       Note: DMAEN is set during the Enable SPORT function */


    *pDMA2_0_CONFIG = WNR | WDSIZE_16 | DI_EN | 0x1000;    


    /* Start address of data buffer */


    *pDMA2_0_START_ADDR = (void *)gas32RxBuffer;


    /* DMA inner loop count */


    /* Number of elements to read.*/


    *pDMA2_0_X_COUNT = 26;       


    /* Inner loop address increment */


    /* Number of bytes to stride */


    *pDMA2_0_X_MODIFY = 2;       





    /* Set up DMA2 channel 1 to Sport transmit */


    *pDMA2_1_PERIPHERAL_MAP = 0x1000;


    /* Configure DMA2 channel 1


       8-bit transfers, Autobuffer mode; completion causes interrupt */


    /* DMA inner loop count */


    *pDMA2_1_X_COUNT = 4096;


    //*pDMA2_1_X_COUNT = 2048;


    /* Inner loop address increment */


    /* Number of bytes to stride */


    *pDMA2_1_X_MODIFY    = 1;   




    *pDMA2_1_NEXT_DESC_PTR = &DMA_SPORT_first;


    //*pDMA1_0_CONFIG = 0x7000 | 0x0400 | DI_EN | DMA2D | (pack32 << 3) | WNR;       


    *pDMA2_1_CONFIG = 0x7000 | 0x0400 | DI_EN |WDSIZE_8;       


    /*DMA1 Channel 0 Config Reg: Large model descriptor list flow,


      desc. size = 4, enable int, 2D, defined 32-bit DMA,


      WNR = write not read */






2) RX Interrupt:


#pragma interrupt
    volatile SINT32 s32CntVal;
    volatile SINT32   s32CntFpgaRet;
    volatile static SINT32   s32OldCntFpgaRet;
    //= for delay
    volatile SINT32 s32DelayCntr;     //= RX
    /* Contains latest command ID */
    volatile SINT32 s32CommandID = 0;
    /* Confirm Interrupt Handling */
    *pDMA2_0_IRQ_STATUS = 0x0001;
    ssync(); //= saw a recommendation to do this second ssync()


    //= =============== Delay counter: what if our settling time is too short? ================


     // s32DelayCntr = 300

    for (s32DelayCntr = 0; s32DelayCntr < gu32DelayCounter; s32DelayCntr++)

... continue with interrupt handling...


3) TX Interrupt:

#pragma interrupt
    volatile UINT32 *pu32TxBuf;
             UINT32 u32IntProtocolWord;
    //= for delay
    volatile SINT32 s32DelayCntr2;     //= TX
    volatile UINT32 u32TxBufAdr;
    /* Confirm Interrupt Handling */
    *pDMA2_1_IRQ_STATUS = 0x0001;
    ssync(); //= saw a recommendation to do this second ssync()


... continue with interrupt handling...