AnsweredAssumed Answered

BF536 MAC DMA acting "funny"

Question asked by mike.mandeville on May 28, 2015
Latest reply on Sep 4, 2015 by VineethaThomas

         We are using Blackfin CPU ADSP-BF536BBCZ-4B rev 0.3 and we are having problem with MAC DMA. For certain packets the EMAC_RX_STAT register has the following value (after the packet is received):

0x82041000 which means that packet length is 0, the frame fragment flag is set. But the actual Ethernet frame is received correctly. The Ethernet header indicates that packet size is 73 bytes therefore I don't understand why frame fragment flag is set and status register indicates

0 packet length?

Please let me know if it's a problem with MAC hardware or something else? It only happens with certain packets. The packet that causes this is provided below:

 

0000 FF FF FF FF FF FF 40 18 B1 02 1C C0 00 49 AA AA

0010 03 00 19 77 00 07 F3 E9 5A 00 3F C2 00 00 66 41

0020 00 01 78 DF 1A FC 30 F0 9F 00 0A F0 A9 BD 83 4B

0030 4F BE 01 EB F1 3C 06 C4 25 45 A7 7A 33 DD 94 B2

0040 2C 54 38 3F 36 3D 27 AA 97 F3 7F 17 8E B5 83 71

0050 7A 3D 3C 1F 90 01 EF 28 F2 0E 77

 

In the attachment you can also see the decoding of this packet using Wireshark.

 

The DMA is configured in chained mode. The config code is taken from an ADI driver example and provided below:

 

 

ADI_ETHER_BUFFER *SetupRxBuffer(bool chksum) {

ADI_ETHER_FRAME_BUFFER *frmbuf;

ADI_ETHER_BUFFER *buf;

        int i;

        int nobytes_buffer = sizeof(ADI_ETHER_BUFFER[2])/2;     //

ensure a mult. of 4

 

        // setup a frame of datasize bytes + 14 byte ethernet header

        buf = (ADI_ETHER_BUFFER

*)malloc(nobytes_buffer+sizeof(ADI_ETHER_FRAME_BUFFER)+RCVE_BUFSIZE);

        if (buf==NULL) MemFailure();

        frmbuf = (ADI_ETHER_FRAME_BUFFER *)(((char *)buf) + nobytes_buffer);

 

        // set up the buffer

memset(buf,0,nobytes_buffer);   // clear ether buf

buf->Data = frmbuf;

memset(frmbuf, 0xfe, RCVE_BUFSIZE); // background pattern

for data buf

 

        //set up first desc to point to receive frame buffer

buf->Dma[0].NEXT_DESC_PTR = &(buf->Dma[1]);

buf->Dma[0].START_ADDR = (unsigned int)buf->Data;

        // config files alrady zero, so

        // linear,  retain fifo data, interrupt after whole buffer,

        // dma interrupt disabled

buf->Dma[0].CONFIG.b_DMA_EN = 1;                // enabled

buf->Dma[0].CONFIG.b_WNR    = 1;                // write to

memory

buf->Dma[0].CONFIG.b_WDSIZE = 2;                // wordsize is

32 bits

buf->Dma[0].CONFIG.b_NDSIZE = 5;                // 5 half words

is desc size.

buf->Dma[0].CONFIG.b_FLOW   = 7;                // large desc

flow

 

 

        //set up second desc to point to status word

buf->Dma[1].NEXT_DESC_PTR = (DMA_REGISTERS*)NULL;

        if (chksum) {

buf->Dma[1].START_ADDR = (unsigned int)&buf->IPHdrChksum;

        } else {

buf->Dma[1].START_ADDR = (unsigned int)&buf->StatusWord;

        }

        // config files already zero, so

        // linear,  retain fifo data, interrupt after whole buffer,

        // dma interrupt disabled, and zero size next desc

        buf->Dma[1].CONFIG.b_DMA_EN = 1;                // enabled

buf->Dma[1].CONFIG.b_WNR    = 1;                // write to

memory

buf->Dma[1].CONFIG.b_WDSIZE = 2;                // wordsize is

32 bits

buf->Dma[1].CONFIG.b_FLOW   = 0;                // stop

 

 

        return buf;

 

}

 

 

 

 

void ethernet_rx_dma_setup(void)

 

{

    int ib;

 

        // initialize the RX DMA channel registers

*pDMA1_X_COUNT  = 0;

*pDMA1_X_MODIFY = 4;

 

 

 

        // set up a receive frames and form a chain of them

        rxlst = NULL;

        rxfst = NULL;

        for (ib=0;ib<NO_RX_BUFS;ib++)

          {

rxbuf = SetupRxBuffer(Eth_Cfg.eth_ip_chksum);

                if (rxfst==NULL) rxfst = rxbuf;

                if (rxlst != NULL)

                  {

// chain this buffer on

rxlst->pNext = rxbuf;

// chain the descriptors

rxlst->Dma[1].NEXT_DESC_PTR = &rxbuf->Dma[0];

// set flow mode

rxlst->Dma[1].CONFIG.b_NDSIZE = 5; // five elements

rxlst->Dma[1].CONFIG.b_FLOW   = 7;

// large descriptors

                  }

 

 

                rxlst = rxbuf;

 

//RxStsHistory[ib] = 0;

          }

        // loop the receive chain

        if (LOOP_RX)

          {

rxlst->Dma[1].NEXT_DESC_PTR = &rxfst->Dma[0];

                // set flow mode

rxlst->Dma[1].CONFIG.b_NDSIZE = 5; // five elements

rxlst->Dma[1].CONFIG.b_FLOW   = 7;

// large descriptors

rxlst->pNext = rxfst;

          }

 

        // start the RX DMA channel before enabling the MAC

        rxbuf = rxfst;

        if (rxfst != NULL)

          {

*pDMA1_NEXT_DESC_PTR = &rxfst->Dma[0];

*pDMA1_CONFIG = *((unsigned short *)&rxfst->Dma[0].CONFIG);

          }

}

Outcomes