This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM3358: LWIP lost Ethernet frames

Part Number: AM3358
Other Parts Discussed in Thread: AM3359

I have software based on the Starterware LWIP stack, but now heavily stripped down and bare metal.  I'm using the CPSW in dual-MAC mode.  All links are forced 100 Mb/s full duplex.  The software works perfectly on the ICEv2.1 boards - I can transmit and receive on both Ethernet links.

I then run it on custom hardware, where:

- Port 1 is linked to an external PHY and magnetics which connects to a Micrel KSZ8895 switch.  The PHY interface is MII.
- Port 2 is linked directly to a separate Micrel KSZ8895 switch, so the KSZ8895 acts as the PHY.  The interface is MII.
- The processor is an AM3358-EP rather than an AM3359.

When I run the software on the custom hardware, I find that port 1 transmits and receives perfectly, port 2 transmits perfectly, but port 2 does not receive correctly.

Specifically, it does not generate a receive interrupt or forward data to port 0.  However I can see the STATS registers correctly counting - it correctly counts unicast vs. broadcast and the correct frame size counters increment (for frames < 64 bytes and frames > 64 bytes).  This proves that frames are actually entering the AM335x.

The obvious place to look is the interrupt config and ALE settings.  However - I'm using the exact same interrupt config and ALE settings on both hardwares.  The stats counters do not report any errors on any ports.

Any thoughts on this?

My ALE settings are very simple:

static void cpswif_port_to_host_vlan_cfg()
{

// Byte:              1     2    3    4     5     6    7     8    9
// VLAN entries

uint8_t entry1a[12] = {0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00};
uint8_t entry2a[12] = {0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00};

// Unicast entries

uint8_t entry1b[12] = {0x00, 0x02, 0x00, 0x0A, 0x00, 0x02, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00};
uint8_t entry2b[12] = {0x01, 0x02, 0x00, 0x0A, 0x00, 0x02, 0x02, 0x30, 0x00, 0x00, 0x00, 0x00};

ALETableEntrySet((uint32_t *)entry1a);
ALETableEntrySet((uint32_t *)entry1b);
ALETableEntrySet((uint32_t *)entry2a);
ALETableEntrySet((uint32_t *)entry2b);

}

Here's the basic CPSW config:

// Initialise ALE

*(volatile uint32_t *)(CPSW0_ALE_REGS + CPSW_ALE_CONTROL) = (CPSW_ALE_CONTROL_CLEAR_TABLE

| CPSW_ALE_CONTROL_ENABLE_ALE | CPSW_ALE_CONTROL_ALE_VLAN_AWARE);

/* Set the port 0, 1 and 2 states to FORWARD */

*(volatile uint32_t *)(CPSW0_ALE_REGS + 0x40U) &= ~CPSW_ALE_PORTCTL0_PORT_STATE;

*(volatile uint32_t *)(CPSW0_ALE_REGS + 0x40U) |= CPSW_ALE_PORT_STATE_FWD;

*(volatile uint32_t *)(CPSW0_ALE_REGS + 0x44U) &= ~CPSW_ALE_PORTCTL0_PORT_STATE;

*(volatile uint32_t *)(CPSW0_ALE_REGS + 0x44U) |= CPSW_ALE_PORT_STATE_FWD;

*(volatile uint32_t *)(CPSW0_ALE_REGS + 0x48U) &= ~CPSW_ALE_PORTCTL0_PORT_STATE;

*(volatile uint32_t *)(CPSW0_ALE_REGS + 0x48U) |= CPSW_ALE_PORT_STATE_FWD;

/* Set Dual Mac Mode */

*(volatile uint32_t *)(CPSW0_PORT_0_REGS + CPSW_PORT_TX_IN_CTL) &= ~CPSW_PORT_P0_TX_IN_CTL_TX_IN_SEL;

*(volatile uint32_t *)(CPSW0_PORT_0_REGS + CPSW_PORT_TX_IN_CTL) |= CPSW_PORT_P0_TX_IN_CTL_TX_IN_DUAL_MAC;

// Initialize the buffer descriptors for CPDMA

cpswif_cpdma_init();

/* Acknowledge receive and transmit interrupts for proper interrupt pulsing*/

*(volatile uint32_t *)(CPSW0_CPDMA_REGS + CPSW_CPDMA_CPDMA_EOI_VECTOR) = CPSW_EOI_TX_PULSE;

*(volatile uint32_t *)(CPSW0_CPDMA_REGS + CPSW_CPDMA_CPDMA_EOI_VECTOR) = CPSW_EOI_RX_PULSE;

/* Enable the interrupts for channel 0 and for control core 0 (wrapper) */

*(volatile uint32_t *)(CPSW0_CPDMA_REGS + CPSW_CPDMA_TX_INTMASK_SET) |= 1;

*(volatile uint32_t *)(CPSW0_WR_REGS + 0x10u + CPSW_CORE_INT_TX_PULSE) |= 1;

*(volatile uint32_t *)(CPSW0_CPDMA_REGS + CPSW_CPDMA_RX_INTMASK_SET) |= 1;

*(volatile uint32_t *)(CPSW0_WR_REGS + 0x10u + CPSW_CORE_INT_RX_PULSE) |= 1; 

// Set up the MII interface.

*(volatile uint32_t *)(CPSW0_SLIVER_1_REGS + CPSW_SL_MACCONTROL)

|= (CPSW_SL_MACCONTROL_GMII_EN | CPSW_SL_MACCONTROL_FULL_DUPLEX);

// Set up the MII interface.

*(volatile uint32_t *)(CPSW0_SLIVER_2_REGS + CPSW_SL_MACCONTROL)

|= (CPSW_SL_MACCONTROL_GMII_EN | CPSW_SL_MACCONTROL_FULL_DUPLEX);

// Add ALE entries

cpswif_port_to_host_vlan_cfg();


  • The software team have been notified. They will respond here.
  • Mat,

    Have you tried to dump the INTC and CPSW registers and compare between ICE and your hardware? Also, have you tried to set ALE bypass bit in ALE control register so all packets received on ports 0 and 1 are sent to the host?

    Regards,
    Garrett
  • Hi Garrett,

    Thanks for your reply.  I tried setting ALE bypass and that seems to work.  Thinking about it, I don't actually need the ALE at all in my application.

    Is it a valid solution to leave the ALE bypassed and just have everything passed up to the host?  I'm running in dual MAC mode and I'm happy to do all filtering / forwarding in host software.

  • Mat,

    If you don't need ALE in you application, it's a solution to leave ALE bypassed in EMAC dual mac mode.

    Regards, Garrett

  • Ok, so my driver is nearly working now.   I've bypassed the ALE as I don't need it. The last issue seems to have been flow control.

    In my application, I have a fixed data stream of 1070 bytes every 400 microseconds.  This is about 20 Mbits/s on a 100baseT link, so the bus is busy but not full.  There will only ever be 1 such frame in the CPSW FIFOs as I process all received packets in the receive interrupt handler, which takes 14 microseconds worst-case.

    Yet I only need to send in 1 extra frame, say an ARP request, to cause frames to be lost. I have confirmed that the DMA engine never sets the EoQ flag on buffer descriptors (I check every single BD in my ISR) so frames are being dropped within the CPSW.

    Turning on both CPPI and Ethernet flow control solves the problem, but I can see from the stats registers that no pause frames are sent or received.

    Can you confirm that it is necessary to enable both types of flow control to avoid losing frames within CPSW, even if no pause frames are sent or received externally?

  • Mat,

    It seems the one extra burst frame cause frame drop. It doesn't have side effect by enabling both type of flow control regardless the presence of pause frame. Have you tried to just enable CPPI port flow control to confirm the Ethernet port flow control doesn't attribute to the frame loss as there is no pause frame in Tx/Rx?

    Regards,
    Garrett