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.

EK-TM4C1294XL: lwip 2.0.2 port problem

Part Number: EK-TM4C1294XL

I have ported lwip version 2.0.2 following the guidelines I found in some forums. Everything works fine with one exception: when the network cable is disconnected and then reconnected again, the lwip stops working.

I was debugging the system and the problem is that, when the cable is disconnected the link drops (EPHY_STS_LINK in the PHY_PHYS_ADDR register, EMAC0_BASE), this is correct, but when the cable is connected again the link bit never returns to one, but remains in zero.

When this happens, the tivaif_process_phy_interrupt function calls netif_set_link_down and never netif_set_link_up (this function is called only once after reset). These functions seem to do nothing in lwip version 1.4.1, but in the new version, the TCP stack no longer receives packets.

I patched de code commenting the call to the function netif_set_link_down in tivaif_process_phy_interrupt. This patch makes the system work. But this solution is not the correct one, since the problem is that, for some reason, the physical layer does not detect that the cable has been connected again.

  • Hi,
    Please refer to this post and see if it will help. e2e.ti.com/.../498224
  • Thank you Charles for your answer but the post do not help.
    The problem is in the tiva driver for the TM4C1294, in the following function:
    void
    tivaif_process_phy_interrupt(struct netif *psNetif)
    {
    uint16_t ui16Val, ui16Status;
    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);

    /* 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); /********************************** this line is never executed if the cable is unplugged and then plugged again ******************************************/
    #else
    tcpip_callback((tcpip_callback_fn)netif_set_link_up, psNetif);
    #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
    }
    }

    /* 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);
    }
    }
  • Hi,

     Where did you get the code that you pasted above? Which TivaWare version do you have?

     I see different contents of the tivaif_process_phy_interrupt in the file C:\ti\TivaWare_C_Series-2.1.4.178\third_party\lwip-1.4.1\ports\tiva-tm4c129\netif\tiva-tm4c129.c. Here it is checking for the link status and depends on the EPHY_STS_LINK it will call either the netif_set_link_up or netif_set_link_down. 

    /**
     * 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);
        }
    }

  • The version I'm working with is: TivaWare_C_Series-2.1.2.111

    I was aware of the new version but forget about it. My fault.
    I will tray this new version and give you a feedback.
    Thank you Charles

    Vicente

  • Hi Vicente,
    Yes, please try the latest version and see if it makes a difference.
  • I changed to the new version but the problem remains. The function tivaif_process_phy_interrupt do not detect that the link is up (if(ui16Status & EPHY_STS_LINK) is always false) therefore the netif_set_link_up(psNetif); never get called.
    I do not use the new EEE_SUPPORT, do you think this could help?
    Vicente
  • I have modified the enet_lwip program to show, in the main cycle, the status of the link.
    This is the result:
    Ethernet lwIP example

    Static IP Address: 10.10.23.15
    Open a browser and enter the IP address.
    Link status (ui16Status & EPHY_STS_LINK) -> 0
    Link status (ui16Status & EPHY_STS_LINK) -> 0
    Link status (ui16Status & EPHY_STS_LINK) -> 0
    Link status (ui16Status & EPHY_STS_LINK) -> 0
    Link status (ui16Status & EPHY_STS_LINK) -> 1 <-- ethernet cable connected the first time
    Link status (ui16Status & EPHY_STS_LINK) -> 1
    Link status (ui16Status & EPHY_STS_LINK) -> 1
    Link status (ui16Status & EPHY_STS_LINK) -> 1
    Link status (ui16Status & EPHY_STS_LINK) -> 1
    Link status (ui16Status & EPHY_STS_LINK) -> 1
    Link status (ui16Status & EPHY_STS_LINK) -> 0 <-- unplug the cable
    Link status (ui16Status & EPHY_STS_LINK) -> 0
    Link status (ui16Status & EPHY_STS_LINK) -> 0
    Link status (ui16Status & EPHY_STS_LINK) -> 0 <-- connect the cable again
    Link status (ui16Status & EPHY_STS_LINK) -> 0
    Link status (ui16Status & EPHY_STS_LINK) -> 0

    As you can see the link status never become one, as I would expect when the cable is reconnected.
    Thank you
    Vicente
  • Can you try one of the TivaWare examples like enet_io or enet_lwip? These are simple web server examples. After the code is run, I open the browser to the specified IP address and see the MCU hosting the web page. I then disconnect the ethernet cable and refresh the browser and after a few seconds it will error out with message that says the site cannot be reached. I will reconnect the cable back and the browser will display the web page hosted by the MCU again. This somehow tells me that the link status should be working after the cable is re-plugged.

    With that said I do find one post that raised the same question as you. e2e.ti.com/.../1909843
  • I do that already, could you change the enet_lwip code like this:
    while(1)
    {
    ui16Status = EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, 0x010);
    UARTprintf ("Link status (ui16Status & EPHY_STS_LINK) -> %d\n", ui16Status & 0x01);
    SysCtlDelay (120000000 * 5 / 3);
    //
    // Wait till the SysTick Interrupt indicates to change the state of the
    // LED.
    //
    // while(g_bLED == false)
    // {
    // }

    }

    You will have to include :
    #include "driverlib/emac.h"

    And, in the begining of the main function:
    int
    main(void)
    {
    uint32_t ui32User0, ui32User1;
    uint8_t pui8MACArray[8];
    uint16_t ui16Status;

    The result is the same as in my last post (the link never get up), but the web page works because in lwip version 1.4.1 the functions netif_link_down and netif_link_up do not prevent the http server for receiving packets. But in the new version it does.

    I will read the post you mention.
    Thank you
    Vicente
  • Charles:

    The patch proposed by Aigars, in the other post, works.

    Anyway I think TI should take a look on this problem, especially if you can reproduce the problem confirming that is not only my mistake.

    Thank you very much.

    Vicente

  • Glad the workaround also works for you.