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.

TM4C129ENCPDT: Ethernet connection lost when disconnect/connect of wire - Link status

Part Number: TM4C129ENCPDT

An old fault, reported by https://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/p/524931/1909843?tisearch=e2e-sitesearch&keymatch=EPHY_STS#1909843, seems not included in new versions of Tivaware (version 2.2.0.295) in the file tiva-tm4c129.c .

The solution was reading a register for link status just before calling the link-down function:

.

.

/* In this case we drop through since we may need to reconfigure
* the MAC depending upon the speed and half/fui32l-duplex settings.
*/
}
else
{
// HERE IS MY FIX
/* fix link status bit error by reading Basic Mode Status register*/
EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_BMSR);
// END OF MY FIX

/* Tell lwIP the link is down */
#if NO_SYS
netif_set_link_down(psNetif);
#else
tcpip_callback((tcpip_callback_fn)netif_set_link_down, psNetif);
#endif

.

As we are in the process of upgrading sensors at off-shore wind turbine sites, a very costly process, we would like to have the findings in that old threat confirmed ?

  • Hi,

      I don't think it was conclusive in the finding reported by the poster in the post you reference. As Amit (who is no longer with TM4C support) mentioned in the post, there is no issue with the link status during plug and unplug when running a stock TivaWare Ethernet example. Do you see the same issue as the referenced post? Did the workaround in that post solve the problem? As far as I tell, tivaif_process_phy_interrupt() in the latest TivaWare version has added support for EEE mode. Otherwise, it is much the same as the one pasted in that post. In the ISR, it first checks if there is a change to the LINK bit in the MISR1 register. If yes, check for whether the LINK bit is high or low in the STS register before passing the corresponding link info to the lwip stack. 

    /**
     * Process interrupts from the PHY.
     *
     * should be called from the Stellaris Ethernet Interrupt Handler.  This
     * function will read packets from the Stellaris Ethernet fifo and place them
     * into a pbuf queue.  If the transmitter is idle and there is at least one packet
     * on the transmit queue, it will place it in the transmit fifo and start the
     * transmitter.
     *
     */
    void
    tivaif_process_phy_interrupt(struct netif *psNetif)
    {
        uint16_t ui16Val, ui16Status;
    #if EEE_SUPPORT
        uint16_t ui16EEEStatus;
    #endif
        uint32_t ui32Config, ui32Mode, ui32RxMaxFrameSize;
    
        /* Read the PHY interrupt status.  This clears all interrupt sources.
         * Note that we are only enabling sources in EPHY_MISR1 so we don't
         * read EPHY_MISR2.
         */
        ui16Val = EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_MISR1);
    
        /* Read the current PHY status. */
        ui16Status = EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_STS);
    
        /* If EEE mode support is requested then read the value of the Link
         * partners status
         */
    #if EEE_SUPPORT
        ui16EEEStatus = EMACPHYMMDRead(EMAC0_BASE, PHY_PHYS_ADDR, 0x703D);
    #endif
    
        /* Has the link status changed? */
        if(ui16Val & EPHY_MISR1_LINKSTAT)
        {
            /* Is link up or down now? */
            if(ui16Status & EPHY_STS_LINK)
            {
                /* Tell lwIP the link is up. */
    #if NO_SYS
                netif_set_link_up(psNetif);
    #else
                tcpip_callback((tcpip_callback_fn)netif_set_link_up, psNetif);
    #endif
    
                /* if the link has been advertised as EEE capable then configure
                 * the MAC register for LPI timers and manually set the PHY link
                 * status bit
                 */
    #if EEE_SUPPORT
                if(ui16EEEStatus & 0x2)
                {
                    EMACLPIConfig(EMAC0_BASE, true, 1000, 36);
                    EMACLPILinkSet(EMAC0_BASE);
                    g_bEEELinkActive = true;
                }
    #endif
    
                /* In this case we drop through since we may need to reconfigure
                 * the MAC depending upon the speed and half/fui32l-duplex settings.
                 */
            }
            else
            {
                /* Tell lwIP the link is down */
    #if NO_SYS
                netif_set_link_down(psNetif);
    #else
                tcpip_callback((tcpip_callback_fn)netif_set_link_down, psNetif);
    #endif
    
                /* if the link has been advertised as EEE capable then clear the
                 * MAC register LPI timers and manually clear the PHY link status
                 * bit
                 */
    #if EEE_SUPPORT
               	g_bEEELinkActive = false;
               	EMACLPILinkClear(EMAC0_BASE);
               	EMACLPIConfig(EMAC0_BASE, false, 1000, 0);
    #endif
            }
        }
    
        /* Has the speed or duplex status changed? */
        if(ui16Val & (EPHY_MISR1_SPEED | EPHY_MISR1_SPEED | EPHY_MISR1_ANC))
        {
            /* Get the current MAC configuration. */
            EMACConfigGet(EMAC0_BASE, &ui32Config, &ui32Mode,
                            &ui32RxMaxFrameSize);
    
            /* What speed is the interface running at now?
             */
            if(ui16Status & EPHY_STS_SPEED)
            {
                /* 10Mbps is selected */
                ui32Config &= ~EMAC_CONFIG_100MBPS;
            }
            else
            {
                /* 100Mbps is selected */
                ui32Config |= EMAC_CONFIG_100MBPS;
            }
    
            /* Are we in fui32l- or half-duplex mode? */
            if(ui16Status & EPHY_STS_DUPLEX)
            {
                /* Fui32l duplex. */
                ui32Config |= EMAC_CONFIG_FULL_DUPLEX;
            }
            else
            {
                /* Half duplex. */
                ui32Config &= ~EMAC_CONFIG_FULL_DUPLEX;
            }
    
            /* Reconfigure the MAC */
            EMACConfigSet(EMAC0_BASE, ui32Config, ui32Mode, ui32RxMaxFrameSize);
        }
    }
    

  • We are not in doubt that we have this as a major issue with our clients. The mentioned fix made the unplug/plug situation work well. We just want a confirmation that we now use the fix correct.

  • Hi Peter,

     Thank you for confirming your observation as this finding is new to me. I'm also glad that the workaround resolves your issue. I will bookmark this post for future reference. The current code is reading the STS register bit 0 for LINK status. Reading the datasheet, it has a note saying "This bit is not cleared upon a read of the EPHSTS register". I'm not fully sure what this means. I wonder when the NIC is unplugged, this bit remains sticky and not change. Hence, the workaround by the poster in that reference post forces to read the BMSR register to refresh the sticky bit. 

  • I agree with your thinking and reading of the register descriptions. I have to add that seldom the old code works, maybe one out of 20 times. We actually tried to make Wireshark comparisons of the activities when succes/no succes, but nothing could give further explanation.

    By setting breakpoints at the link-up and link-down actions, it is seen that the change of link flag, when attaching the wire, works correct leading to the evaluation of up or down, but ends down !

    It seems that the internal state is corrupted during the removal of the wire.

    Problem now is simply if the solution is reliable and correct ?