MSP432E401Y: Phenomenon that Ethernet cannot be received.

Expert 1685 points
Part Number: MSP432E401Y
Other Parts Discussed in Thread: EK-TM4C1294XL

Hi,

There is a phenomenon that Ethernet cannot be received.

 

When it cannot be received normally

-RDES0 register OWN bit remains 1

-EMACDMARIS_RI bit remains 0

-EMACDMARIS_RS bit remains 0x03

 

The above phenomenon does not always occur, and if I change the source code in a place unrelated to the MAC settings and compile it, it will work normally.

(Perhaps it seems that the memory allocation shifts due to compilation and the timing change is related.)

Please let me know if you have any ideas.

Thanks,

Koki

  • Hi Koki,

    This may be difficult to track down.  When you "change" the code in an unrelated section, do you do something like add additional lines of instructions (like calling a function or maybe create a new function, or perform some math operation) or are you adding new variables.  I'm trying to get a sense if it is RAM vs FLASH related.

  • Hi, Dennis

    In most cases, it works normally, but in rare cases it cannot be received.

    When one of the following methods was executed when reception was not possible, it worked normally.

    If it can be received once, the subsequent reception will operate normally

     

    Techniques when it doesn't work

    - When I created a variable with int, the memory allocation changed and it worked normally

    - It worked normally if I put a stop or step execution in the middle of the initialization process with the debugger.

    - Works by calling EMAC reset () x 2 time

      

    Just in case, I describe the code of initialization.

    emac_init.c
    
    
    void emac_init(DWORD ui32SysClkHz, const BYTE *macAddrArray)
    {
        // -- Enable the ethernet peripheral. --
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0);
    	//-- Reset Ethernet controller --
        MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_EMAC0);
        
    	if(!MAP_SysCtlPeripheralPresent(SYSCTL_PERIPH_EPHY0)){ //internal PHY.  Is it present?
    		//-- Internal PHY is not present on this part so hang here. --
    		while(1) { }
    	}
    
    	// --  enable and reset it. --
    	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0);
    	MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0);
    	//-- Wait for the reset to complete --
    	//while(!SysCtlPeripheralReady(SYSCTL_PERIPH_EPHY0));
    
        //-- Wait for the reset to complete --
        while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0)) { }
    
        //-- LED Polarity Control --
        HWREG(EMAC0_BASE + EMAC_O_CC) |= EMAC_CC_POL; //LEDs are active low.
    
        //-- Configure for use with the internal PHY. --
        EMACPHYConfigSet(EMAC0_BASE, (EMAC_PHY_TYPE_INTERNAL | EMAC_PHY_INT_MDIX_EN | EMAC_PHY_AN_100B_T_FULL_DUPLEX));
    
        // -- Reset the MAC. --
        MAP_EMACReset(EMAC0_BASE);
    
        // -- Initialize the MAC and set the DMA mode. --
        MAP_EMACInit(EMAC0_BASE, ui32SysClkHz,
                     EMAC_BCONFIG_MIXED_BURST | EMAC_BCONFIG_PRIORITY_FIXED,
                     4, 4, 0);
    
        // -- Set MAC configuration options. --
        MAP_EMACConfigSet(EMAC0_BASE, (EMAC_CONFIG_FULL_DUPLEX |
                                   //EMAC_CONFIG_100MBPS |
                                       EMAC_CONFIG_CHECKSUM_OFFLOAD |
                                       EMAC_CONFIG_7BYTE_PREAMBLE |
                                       EMAC_CONFIG_IF_GAP_96BITS |
                                       EMAC_CONFIG_USE_MACADDR0 |
                                       EMAC_CONFIG_SA_FROM_DESCRIPTOR |
                                       EMAC_CONFIG_BO_LIMIT_1024),
                          (EMAC_MODE_RX_STORE_FORWARD |
                           EMAC_MODE_TX_STORE_FORWARD |
                           EMAC_MODE_TX_THRESHOLD_64_BYTES |
                           EMAC_MODE_RX_THRESHOLD_64_BYTES), 0);
    
        // -- Program the hardware with its MAC address (for filtering). --
        MAP_EMACAddrSet(EMAC0_BASE, 0, (uint8_t *)macAddrArray);
    
        // -- Initialize the Ethernet DMA descriptors. --
        InitDMADescriptors();
    
        // -- Set MAC filtering options.  We receive all broadcast and multicast
        // packets along with those addressed specifically for us. --
        MAP_EMACFrameFilterSet(EMAC0_BASE, (EMAC_FRMFILTER_SADDR |
                                            EMAC_FRMFILTER_PASS_MULTICAST |
                                            EMAC_FRMFILTER_PASS_NO_CTRL));
    
        // -- Clear any pending interrupts. --
        MAP_EMACIntClear(EMAC0_BASE, EMACIntStatus(EMAC0_BASE, false));
    
        // -- Mark the first receive descriptor as available to the DMA to start the receive processing. --
        rxDmaDesc[rxDmaDescIdx].des0 |= DES0_RX_CTRL_OWN;
    
    	// -- Enable the Ethernet MAC transmitter and receiver. --
        EMACTxEnable(EMAC0_BASE);
        EMACRxEnable(EMAC0_BASE);
    }
    
    
    /**
     * Initialize the transmit and receive DMA descriptor lists.
     */
    static void InitDMADescriptors(void)
    {
        int i;
        uint32_t setBuffAddr;
    
        //Initialize TX DMA descriptor list
        for(i = 0; i < NUM_TX_DESCRIPTORS; i++)
        {
            //Use chain structure rather than ring structure
            txDmaDesc[i].des0 = ( DES0_TX_CTRL_LAST_SEG | DES0_TX_CTRL_FIRST_SEG | DES0_TX_CTRL_CHAINED );
                //DES0_TX_CTRL_LAST_SEG | DES0_TX_CTRL_FIRST_SEG | DES0_TX_CTRL_INTERRUPT | DES0_TX_CTRL_CHAINED | DES0_TX_CTRL_IP_ALL_CKHSUMS );
            //Initialize transmit buffer size
            txDmaDesc[i].des1 = (DES1_TX_CTRL_SADDR_INSERT |
                    (TX_BUFFER_SIZE << DES1_TX_CTRL_BUFF1_SIZE_S));
            //Transmit buffer address
            setBuffAddr = (uint32_t) TxBuffer;
            txDmaDesc[i].des2 = setBuffAddr;
            //Next descriptor address
            txDmaDesc[i].des3 = (uint32_t) &txDmaDesc[i + 1];
            //Reserved fields
            txDmaDesc[i].des4 = 0;
            txDmaDesc[i].des5 = 0;
            //Transmit frame time stamp
            txDmaDesc[i].des6 = 0;
            txDmaDesc[i].des7 = 0;
        }
        //The last descriptor is chained to the first entry
        txDmaDesc[NUM_TX_DESCRIPTORS - 1].des3 = (uint32_t) &txDmaDesc[0];
      
        //Initialize RX DMA descriptor list
        for(i = 0; i < NUM_RX_DESCRIPTORS; i++)
        {
            //
            rxDmaDesc[i].des0 = 0;
            //Use chain structure rather than ring structure
            rxDmaDesc[i].des1 = (DES1_RX_CTRL_CHAINED | 
                    (RX_BUFFER_SIZE << DES1_RX_CTRL_BUFF1_SIZE_S) );                
            setBuffAddr = (uint32_t)RxBuffer;
            //set Receive buffer address
            rxDmaDesc[i].des2 = setBuffAddr;
            //Next descriptor address
            rxDmaDesc[i].des3 = (uint32_t) &rxDmaDesc[i + 1];
            //Extended status
            rxDmaDesc[i].des4 = 0;
            //Reserved field
            rxDmaDesc[i].des5 = 0;
            //Receive frame time stamp
            rxDmaDesc[i].des6 = 0;
            rxDmaDesc[i].des7 = 0;
        }
        //The last descriptor is chained to the first entry
        rxDmaDesc[NUM_RX_DESCRIPTORS - 1].des3 = (uint32_t) &rxDmaDesc[0];
    
        // Start from the beginning of both descriptor chains.  We actually set
        // the transmit descriptor index to the last descriptor in the chain
        // since it will be incremented before use and this means the first
        // transmission we perform will use the correct descriptor.
        rxDmaDescIdx = 0;
        txDmaDescIdx = NUM_TX_DESCRIPTORS - 1;
    
    	// -- Set the Start location of the descriptor list. --
        HWREG(EMAC0_BASE + EMAC_O_RXDLADDR) = (uint32_t)rxDmaDesc;
        HWREG(EMAC0_BASE + EMAC_O_TXDLADDR) = (uint32_t)txDmaDesc;
        //MAP_EMACRxDMADescriptorListSet(EMAC0_BASE, rxDmaDesc);
        //MAP_EMACTxDMADescriptorListSet(EMAC0_BASE, txDmaDesc);
    }

    Thanks,

  • Hi Koki,

    Unfortunately, I'm not able to find anyone who knows much about this problem.  I checked with our connectivity group, but they only support wireless devices.  I did try searching on E2E for TM4C products and ethernet issues and found quite a few topics, but nothing related to your problem.  You might try searching there as well.  I'll keep looking around for someone who might be able to help.

  • Hi, Dennis

    You might try searching there as well.  I'll keep looking around for someone who might be able to help.

    Yes, I will also search from past forums.

    Please let me know if you get any information about it.

    Thanks,

    Koki

  • Hi Koki,

    Here is a suggestion, as a method to isolate and identify the issue, can you write a test function that can read and dump the Ethernet registers to see if one could identify a register that is different?  

  • Hi,  Dennis

    I summarized only where there was a difference in the register values.

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

    〇・・・Register value when the system operates normally
    ×・・・Register value when not received correctly


    EMAC_PMTCTLSTAT (Ethernet MAC PMT Control and Status Register)
    〇 0x01000000
    × 0x03000000

    EMAC_TXCNTGB (Ethernet MAC Transmit Frame Count for Good and Bad Frames )
    〇 0x000000C9
    × 0x00000000

    EMAC_TXOCTCNTG (Ethernet MAC Transmit Octet Count Good)
    〇 0x00005630
    × 0x00000000


    EMAC_RXCNTGB (Ethernet MAC Receive Frame Count for Good and Bad Frames)
    〇 0x000000E1
    × 0x00000000

    EMAC_RXCNTGUNI (Ethernet MAC Receive Frame Count for Good Unicast Frames
    〇 0x000000CD
    × 0x00000000

    EMAC_DMARIS (Ethernet MAC DMA Interrupt Status)
    〇 0x006804C4
    × 0x00660004

    EMAC_MFBOC (Ethernet MAC Missed Frame and Buffer Overflow Counter )
    〇 0x00000001
    × 0x00000000

    EMAC_HOSRXDESC (Ethernet MAC Current Host Receive Descriptor )
    〇 0x200238DC
    × 0x200238BC

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

    Also, the sample code provided by TI uses a receive interrupt, but I use a flag to check if it was received.

    Is there any problem with the confirmation method using this flag?

     

    Thanks,

    Koki

  • Hi Koki,

    Are you using LWIP v1.4.1 for Ethernet clocking? 

  • Hi, 

    Are you using LWIP v1.4.1 for Ethernet clocking? 

    No TCI / IP stack is used.
    Currently, I am trying to see if Ethernet frames can be received only with EMAC.

     

    Currently, I was looking at the Programming Example described in the API guide in the following folder, and I was curious.

    file:///C:/ti/simplelink_msp432e4_sdk_4_20_00_12/docs/driverlib/msp432e4/api_guide/html/group__emac__api.html

    In the middle of initialization, there was the following description.

     

    // Wait for the link to become active.

    while ((EMACPHYRead (EMAC0_BASE, ui8PHYAddr, EPHY_BMSR) & EPHY_BMSR_LINKSTAT) == 0) {}

    The above waits for the LAN link and then enables EMAC and DMA.

    As a test I added the above and everything seems to be working fine for now.

    Is it necessary to wait for the link before enabling EMAC and DMA?

    Thanks,

    Koki

  • Is it necessary to wait for the link before enabling EMAC and DMA?

    That does not seem correct. Why did EMACPHYRead() even need to test link state? Perhaps only necessary for unplugging cable so code does not fault read buffer DMARIS flags. The PHY is separated inside the EMAC on some TI Ethernet peripherals.  

  • Hi, GI

    Perhaps only necessary for unplugging cable so code does not fault read buffer DMARIS flags.

    Please tell me a little more detail.
     
    If you have any ideas for solving this problem, please let me know again.

    Thanks,

    Koki

  • Hi Koki,

    Above you stated the red code seems to fix the problem?

    For LWIP 1.4.1 configuration a GPTM driven SW interrupt 1st loads Tm4C129_HAL.c, secondly the PHY is tested HAL level for link status. The IP/MAC function call to DHCP still loops for PHY link status flag to become true in a similar link state test as above located in the application code stream.  Such order keeps the upper IP layers from over running the PHY and attempting to assign an IP to the stack before the EMAC is fully configured for PHY data transfers via the HAL. That's code behavior and various code examples exist with LWIP network stack loaded on EK-TM4C1294XL launch pad.

    Regards,

  • Hi, GI

    Above you stated the red code seems to fix the problem?

    Yes, it's working fine for now.

     

    1. The above isn't the fundamental solution, right?

    2. Is it okay to check the Ethernet reception with the flag? (In the sample code, reception was confirmed by interrupt.)

    3. If you have any idea about the cause of "ETH cannot be received correctly", please let me know.

    Thanks,

    Koki

  • In most cases, it works normally, but in rare cases it cannot be received

    Perhaps the case you may check DMARIS flag for Ro bit status may indicate over run if DMA receiver inputs to fast with no buffer space remaining Thinking

  • Hi, GI

    OK, I'll check!

    2. Is it okay to check the Ethernet reception with the flag? (In the sample code, reception was confirmed by interrupt.)

    How about 2 ?

    Thanks,

    Koki

  • 2. Is it okay to check the Ethernet reception with the flag?

    If your code uses the utils/ring buffer.c it can benefit from reading buffer flag status. Perhaps why LWIP is recommended to handle the 7 network or transport layers. 

    (In the sample code, reception was confirmed by interrupt.)

    How about 2 ?

    Yet if DMARIS has Ro flag set then interrupt fault (Ro) comes after the cause of fault flag status. You need to stop DMARIS flag (Ro) from being set and empty DMA Rx register before next byte comes into PHY. That is difficult to achieve if the data stream has many bytes, hence the 7 network layer filters data up the TCP/IP stack using ring buffer for the PCB.

    Perhaps try to import to CCS & modify TM4c1294 projects for MPS432 that use LWIP1.4.1 as the transports lawyers Thinking  Otherwise locate project folders under MPS432 that use LWIP transports to handle the DMA descriptors data. CCS has resource explorer to find these project, if they even exist. It would be wise to invest in EK-TM4C1294XL launch pad to do more extensive TCPIP transfers via LWIP v1.4.1. 

    Best of luck in your adventure Koki Wink

  • Hi Koki,

    It's been a while since we have heard from you, so I'm going to assume you were able to move forward with your project.

    Thank you GI for you assistance with this issue.


    I will mark this posting as RESOLVED, but if this isn’t the case, please click the "This did NOT resolve my issue" button and reply to this thread with more information.
    If this thread is locked, please click the "Ask a related question" button, and in the new thread describe the current status of your issue and any additional details you may have to assist us in helping to solve your issues.