MPC5777C FEC - Transmit Buffer Descriptor & FEC DMA setting

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MPC5777C FEC - Transmit Buffer Descriptor & FEC DMA setting

2,539 Views
taekyoungkim
Contributor II

Hi. 

 

I have problem with transmission of Ethernet frame.

When I captured a transmitted Ethernet frame at the other monitoring system, it looked like the Ethernet frame data was disordered.

176348_176348.pngpastedImage_1.png

I have set the source MAC address like a 0x11, 0x22, 0x33, 0x44, 0x55, 0x66

The captured packet showed disordered MAC address and wrong data length.(I set the frame length '18')

I'm considering that this problem caused by miss configuration of FEC DMA or Transmit Buffer Descriptor.

 

The Ethernet frame setting function likes below... (I referred MPC5646C FEC sample code)

 

void setupGlobalFrame()
{
   int i;
   frame = (void *) txBuf;

   // Setup broadcast as destination
   for (i = 0; i < 6; i++)
   {
      frame->destination[i] = broadcast[i];
   }

   // Setup source address
   for (i = 0; i < 6; i++)
   {
   frame->source[i] = mac[i];
   }

   // Set length (static at 4 for the 32-bit data payload)
   frame->length = 4;

   // Setup txDesc for the (2x6-byte address + 2byte length + 4byte data) 18-byte frame
   txDesc[0].length = 18;
   txDesc[1].length = 18;
}

 

Also TBD settings are below

 

.....

   for (i = 0; i < 2; i++)
   {
      // Init tx and rx descriptors
      txDesc[i].status = 0x2C00; // Last and transmit CRC
      txDesc[i].length = 0;
      txDesc[i].bufferPointer = txBuf;

      markRxDescEmpty(&rxDesc[i]);
      rxDesc[i].bufferPointer = rxBuf[i];
   }

....

FEC.ETDSR.R = (unsigned long) &txDesc;

 

In short, my questions are below

1. Is there any configuration for FEC DMA?

2. Possible miss-configuration of Transmit Buffer Descriptor? Any guesses?

 

Thank you.

Taekyoung Kim

Labels (1)
6 Replies

1,920 Views
martin_kovar
NXP Employee
NXP Employee

Hello,

could you please share your project? I will check it on my side.

Regards,

Martin

0 Kudos
Reply

1,920 Views
taekyoungkim
Contributor II

I found the similar issue from FEC CodeWarrior MPC56xx - Tx repeting bytes 

From that issue,

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

This is very hard to explain if you have 32-bit memory and the FEC is reading 32 bits at a time, as it would require some intermediate "byte-lane changing hardware" to be doing something stupid.

 

It would be easier to understand if you've got 16-bit RAM, or a 16-bit pathway between the FEC and the RAM. the "pathway" is unlikely as the FEC is a master on the Crossbar.

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

You can see that the transmitted Ethernet frame was duplicated 16 bit words. 

ex) 11 22 11 22 11 22 11 22 11 22

pastedImage_2.png

Is this because Crossbar setting? or system clock?

I'm afraid not to share the project files for the security policy, but here are some functions related to FEC configuration.

#define OBE          0x0200
#define IBE            0x0100
#define ODE          0x0020
#define SRC          0x0004
#define WPE          0x0002
#define WPS          0x0001

#define PA_GPIO    0x0000
#define PA_PRIM    0x0400
#define PA_ALT1    0x0800
#define PA_ALT2    0x0C00
#define PA_ALT3    0x1000

#define SIU_SYSDIV_PERCLKSEL_NON_FM_CLOCK    0x1000000
#define SIU_SYSDIV_PERDIV_DIVIDE_BY_2                   0x0000000

...

// initFecIo - initialise pads for FEC use in the SIU
void initFecIo(void)
{
  // MPC5777C - FEC MII-Lite mode IO setting
  SIU.PCR[PCR99_FEC_MDIO_ALT2].R            = PA_ALT2 | OBE | IBE | SRC | WPE;     //FEC_MDIO
  SIU.PCR[PCR109_FEC_MDC_ALT3].R           = PA_ALT3 | OBE | WPE;                         //FEC_MDC

  SIU.PCR[PCR252_FEC_TX_EN_PRIM].R       = PA_PRIM | OBE | SRC;                         //FEC_TX_EN
  SIU.PCR[PCR248_FEC_TXD0_PRIM].R          = PA_PRIM | OBE | SRC;                         //FEC_TXD0
  SIU.PCR[PCR251_FEC_TXD1_PRIM].R          = PA_PRIM | OBE | SRC;                        //FEC_TXD1
  SIU.PCR[PCR98_FEC_TXD2_ALT2].R             = PA_ALT2 | OBE | SRC;                         //FEC_TXD2
  SIU.PCR[PCR101_FEC_TXD3_ALT3].R           = PA_ALT3 | OBE | SRC;                         //FEC_TXD3
  SIU.PCR[PCR474_FEC_TX_CLK_PRIM].R      = PA_PRIM | IBE | WPE;                         //FEC_TX_CLK

  SIU.PCR[PCR100_FEC_RX_CLK_ALT3].R      = PA_ALT3 | IBE | SRC | WPE;                //FEC_RX_CLK
  SIU.PCR[PCR249_FEC_RX_DV_PRIM].R       = PA_PRIM | IBE | WPE;                          //FEC_RX_DV
  SIU.PCR[PCR250_FEC_RXD0_PRIM].R          = PA_PRIM | IBE | SRC | WPE;              //FEC_RXD0
  SIU.PCR[PCR253_FEC_RXD1_PRIM].R          = PA_PRIM | IBE | SRC | WPE;              //FEC_RXD1
  SIU.PCR[PCR101_FEC_RXD2_ALT3].R           = PA_ALT3 | IBE | SRC | WPE;              //FEC_RXD2
  SIU.PCR[PCR107_FEC_RXD3_ALT3].R           = PA_ALT3 | IBE | SRC | WPE;              //FEC_RXD3

 

  //Input Multiplexing Register0(SIU_IMUX0) setting for FEC input pins
  SIU.IMUX0.R = IMUX0_MUXSEL6_FEC_TXCLK | IMUX0_MUXSEL1_FEC_RXDV | IMUX0_MUXSEL2_FEC_RXD0 | \
                   IMUX0_MUXSEL5_FEC_RXD1 | IMUX0_MUXSEL11_FEC_RXD2 | IMUX0_MUXSEL8_FEC_RXD3;

   

   //Peripheral Clock Setting
   SIU.SYSDIV.R = SIU_SYSDIV_PERCLKSEL_NON_FM_CLOCK | SIU_SYSDIV_PERDIV_DIVIDE_BY_2;

}

static int initFec(void)
{
   int result = 1;
   int i;

   initFecIo();

   FEC.ECR.R = 0x1;
   while (FEC.ECR.B.RESET) { } ; // Wait for reset to complete

   FEC.EIMR.R = 0; // Disable interrupts
   FEC.EIR.R = 0xFFFFFFFF; // Clear any interrupts

  

   for (i = 0; i < 2; i++)
   {
      // Init tx and rx descriptors
      txDesc[i].status = 0x2C00; // Last and transmit CRC
      txDesc[i].length = 0;
      txDesc[i].bufferPointer = txBuf;

      markRxDescEmpty(&rxDesc[i]);
      rxDesc[i].bufferPointer = rxBuf[i];
   }

   // Reset multicast fields
   FEC.GAUR.R = 0;
   FEC.GALR.R = 0;
   FEC.IAUR.R = 0;
   FEC.IALR.R = 0;

  

 // Set rx buf size
   FEC.EMRBR.R = 1536;

   // Point FEC to our (single) tx and rx descriptors
   FEC.ETDSR.R = (unsigned long) &txDesc;
   FEC.ERDSR.R = (unsigned long) &rxDesc;

   

   // Enable full duplex
   FEC.TCR.R = 0x00000004; //full duplex enable

   // Set in MII mode with full frame size
   FEC.RCR.R = 0x05EE0004;

   // Set MII speed - assume operation at 64Mhz
   FEC.MSCR.B.MII_SPEED = 0x5; // 50MHz(Internal bus clock) / 2 => 25 MHz

   // Enable interrupt
   FEC.EIMR.R = 0x02000000;

   // Enable module
   FEC.ECR.R = 0x2;

   // Configure a MAC address
   FEC.PALR.R = (unsigned long)((mac[0] <<24)|(mac[1] <<16)|(mac[2] <<8)|(mac[3] <<0));
   FEC.PAUR.R = (unsigned long)(mac[4] <<24)|(mac[5] <<16);

   

   initFecPhy();

   // Flag descriptors available to allow reception
   FEC.RDAR.R = 0x0100000;

   return result;
}


int main(void)
{
   volatile int counter = 0;
   volatile int loop = 0;

   STM_A.CR.R = 1; //System Timer Module
   disableWatchdog();
   xcptn_xmpl (); /* Configure and Enable Interrupts */
   HW_init();
   setMacAddr();
   initFec();
   setupGlobalFrame();

   SIU.GPDO[LED1_pin].R = 0;

   while(!isConnected());

   /* Loop forever */
   for(;;) {

      while(loop <= 10000)
      {
         loop++;
      }

      SIU.GPDO[LED1_pin].R ^= 1;
      txEthernetFrame();
      loop = 0;
      counter++;
   }
}

Thank you. 

0 Kudos
Reply

1,920 Views
martin_kovar
NXP Employee
NXP Employee

Hello,

1) Please check if you have correctly aligned Buffer Descriptors and tx/rs buffers? Please see code below:

pastedImage_1.png

2) I am not sure about your MII_SPEED settings. FEC module is clocked from FM_PER_CLK. What is the value of your FM_PER_CLK?

MII Speed calculation is following   FM_PER_CLK * ( 1/ (MSCR[MII_SPEED]*2)) <= 2.5MHz

Example:

FM_PER_CLK = 64MHz

Calculation:  64MHz * 1 / MSCR[MII_SPEED] * 2 <= 2.5MHz

Result:  MSCR[MII_SPEED] = 13 (0xD)

Regards,

Martin

0 Kudos
Reply

1,920 Views
taekyoungkim
Contributor II

I have set SIU.SYSDIVE register like this

pastedImage_1.png

So FM_PER_CLK = 8MHz

- SYSCLKSEL : 0 (16MHz IRC)

- SYSCLKDIV : 0x4 (Divide by 1)  -> 16MHz / 1 = 16MHz

- FMPERDIV : 0 (Divide by 2) -> 16MHz / 2 = 8MHz

FEC.MSCR.B.MII_SPEED = 0x2; // 8MHz x ( 1 / ( 2 x 2)) = 2MHz <= 2.5MHz 

Is it correct?

 

Nevertheless, the result of transmitted Ethernet frame was same. (You can still see the duplicated data, 01 02 01 02...)

pastedImage_4.png

 

Please give me a feedback about my clock setting.

Thank you for your patience.

Regards

Taekyoung Kim

0 Kudos
Reply

1,920 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

Seems I was wrong last time, the FEC is actually clocked from FM_PER_CLK and so the MDC clock must be calculated from this FM_PER_CLK. Note this clock must be at least 50MHz so full duplex is supported.

 

If the MII-lite is used the following jumper setting must be done on minimodule and PHY on motherboard must be clocked from 25MHz crystal.

pastedImage_1.png

BR, Petr

1,920 Views
taekyoungkim
Contributor II

I forgot to mention the development environment.

 - MPC5777C-EVB Rev.C 516DS

 - S32DS IDE  

I would like to use MII-Lite interface.

1) I have same declaration for the Buffer Descriptors.

// Min 2 descriptors needed to prevent resending
BufferDescriptor txDesc[2] __attribute__ ((aligned (16)));
BufferDescriptor rxDesc[2] __attribute__ ((aligned (16)));

// We need 1518 bytes... but 1536 is evenly divisible by 16
uint8_t txBuf[1536] __attribute__ ((aligned (16)));
uint8_t rxBuf[2][1536] __attribute__ ((aligned (16)));

2) I had configured clock setting as you told, but same problem was occurred.

 - My SIU.SYSDIV setting is below

pastedImage_1.png

 - System clock setting 

#define SIU_SYSDIV_SYSCLKSEL_FM_PLL1         0x00002000
#define SIU_SYSDIV_FMPERDIV_DIVIDE_BY_2    0x00000000

...  

SIU.SYSDIV.R = SIU_SYSDIV_SYSCLKSEL_FM_PLL1 | SIU_SYSDIV_FMPERDIV_DIVIDE_BY_2;

 - MII Speed setting 

  FEC.MSCR.B.MII_SPEED = 0xD;

According to the 'MPC5777C EVB user guide' (document number MPC5777CEVBUG, Rev0/2015)'

with that jumper setting, it enables FEC 50MHz clock. That's why I configured 'MII_SPEED' like

 - on board 50MHz FEC clock / Divided by 2  ->  (50MHz / 2) = 25MHz (Internal bus clock)

 - FEC.MSCR.B.MII_SPEED = 0x5;  // 25MHz(Internal bus clock) x (1 / (5 x 2)) =< 2.5 MHz

And 'Petr Stancik' told me in the previous question that (Questions of MPC5777C FEC setting)

'The MDC frequency is calculated from the internal bus clock, in this case it should be PER_CLK selected by SIU_SYSDIV.PERDIV'

Which register should I set for the FEC clock setting(MII-Lite interface)? PERCLKSEL or SYSCLKSEL?

I'm confused about FEC clock setting, please explain more detail about it.

(It would be a great help, if you list up all the registers to configure FEC clock)

pastedImage_14.png

pastedImage_2.png

0 Kudos
Reply