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.

Ethernet Bootloader: Uninitialized UIP Variables

Hello,

I have been working with the Ethernet bootloader (boot_emac_flash example project) on a TM4C1294 microcontroller. I have been having issues uploading new firmware a second time. It works fine the first time and then doesn't work the second time. The BOOTP request would go out and my computer, running the reflash application, would reply. I noticed that the microcontroller was sending out ARP "who has" requests to very strange (and seemingly random) IP addresses.

After much investigation and testing, I've come to the conclusion that both uip_netmask and uip_draddr are declared but never initialized anywhere inside the third party uip files, but they are actively used inside the uip_arp.c file to send out requests. I wanted to make note of this and make everyone aware. Is this intentional or a bug? If this is intentional, did I miss some documentation that mentions this?

Thanks,

Cam

  • Hello Cam

    I have asked my colleague to look into the same.
  • Hello CamK,

    Thanks for bringing this issue to our notice. I started working on this issue today. Sorry for the delay as I was held up with other debug issues.

    I am able to replicate the problem. So far what I found is that the application "boot_demo_emac_flash" does not call the call back function "SoftwareUpdateRequestCallback" when I try to load an application using LMFlash Programmer. This results in the bootloader not being called.

    This call back function is registered with the "swupdate" utility (in ./utils/swupdate.c file).

    I will have to look into why the "swupdate" utility is not working as expected. I will continue to work on this issue next week.

    Thanks,
    Sai
  • Hello Sai,

    Did you ever come to any conclusions on this issue?

    Regards,
    Cam
  • Hello Sai,

    Did anything ever come of this?

    Regards,
    Cam
  • Hello CamK,

    I think the issue I was seeing was with my network switch. When I use the same LaunchPad (with the exact same code) on a different switch, it works fine. I do have a managed switch so maybe it blocks certain ports. With my old switch I am able to update using "boot_demo_emac_flash".

    I wonder if you are having the same issue. Maybe the ports are blocked on the router/switch that you are using.

    Thanks,
    Sai
  • Hello Sai,

    What version of TivaWare are you using? This project started with the development of version 2.1.1.71 and has not been upgraded to the newest version of TivaWare, though it doesn't appear that any changes were made to these files. Here are the list of changes I made and to which files that made this work. I have dug up these changes from several months ago, so hopefully I'm able to recall everything correctly.

    * in bl_emac.c, I added the following line up UpdateBOOTP()

    *((uint32_t *)(void *)(&uip_netmask)) = 0x0000FFFF;
    

    *in uip_arp.c, I modified the uip_arp_out() function as follows

    void
    uip_arp_out(void)
    {
      struct arp_entry *tabptr;
      
      /* Find the destination IP address in the ARP table and construct
         the Ethernet header. If the destination IP addres isn't on the
         local network, we use the default router's IP address instead.
    
         If not ARP table entry is found, we overwrite the original IP
         packet with an ARP request for the IP address. */
    
      /* First check if destination is a local broadcast. */
      if(uip_ipaddr_cmp(IPBUF->destipaddr, broadcast_ipaddr)) {
        memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6);
      } else {
        /* Check if the destination address is on the local network. */
    	  if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) {
          /* Destination address was not on the local network, so we need to
    	 use the default router's IP address instead of the destination
    	 address when determining the MAC address. */
            uip_ipaddr_copy(ipaddr, IPBUF->destipaddr);
    
          //uip_ipaddr_copy(ipaddr, uip_draddr);
        } else {
          /* Else, we use the destination IP address. */
          uip_ipaddr_copy(ipaddr, IPBUF->destipaddr);
        }
    
        for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
          tabptr = &arp_table[i];
          if(uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) {
    	break;
          }
        }
    
        if(i == UIP_ARPTAB_SIZE) {
          /* The destination address was not in our ARP table, so we
    	 overwrite the IP packet with an ARP request. */
    
          memset(BUF->ethhdr.dest.addr, 0xff, 6);
          memset(BUF->dhwaddr.addr, 0x00, 6);
          memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
          memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
        
          uip_ipaddr_copy(BUF->dipaddr, ipaddr);
          uip_ipaddr_copy(BUF->sipaddr, uip_hostaddr);
          BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */
          BUF->hwtype = HTONS(ARP_HWTYPE_ETH);
          BUF->protocol = HTONS(UIP_ETHTYPE_IP);
          BUF->hwlen = 6;
          BUF->protolen = 4;
          BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
    
          uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN];
        
          uip_len = sizeof(struct arp_hdr);
          return;
        }
    
        /* Build an ethernet header. */
        memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6);
      }
      memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
      
      IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP);
    
      uip_len += sizeof(struct uip_eth_hdr);
    }

    After making these changes, it works great.  I am able to use the Ethernet bootloader. I have no issues so I don't think it's a port issue. We have tested on networks with DHCP, a local network with just a switch, a local network with a managed switch, static IP cases, etc. It's works fine and dandy. Without making these changes, I don't see how it's possible to use the uip_draddr or uip_netmask variables. They are never initialized as far as I can tell. 

    Was this addressed in a later version or is there an initialization I'm missing somewhere? Do you define UIP_FIXEDADDR = 1 in uipopt.h? I have it defined as 0.

    At this point, the change is working for me, but I'd like to clarify and understand to make sure I don't run into issues in the future (and so others have some visibility).

    Regards,

    CamK

  • Hello CamK,

    Stellaris Sai said:
    I think the issue I was seeing was with my network switch. When I use the same LaunchPad (with the exact same code) on a different switch, it works fine. I do have a managed switch so maybe it blocks certain ports. With my old switch I am able to update using "boot_demo_emac_flash". 

    "boot_demo_emac_flash" application uses the "swupdate" utility (in ./utils/swupdate.c file), to update firmware over Ethernet, that is, it does not enter the Bootloader to update firmware. This utility uses non-standard ports for updating firmware and that's why I think the managed switch that I tested with was blocking it.

    CamK said:
    I have been working with the Ethernet bootloader (boot_emac_flash example project) on a TM4C1294 microcontroller. I have been having issues uploading new firmware a second time. It works fine the first time and then doesn't work the second time.

    From the above statement (made on your first post of this thread), I assumed that you are using the Ethernet Bootlaoder (boot_emac_flash) and the accompanying application (boot_demo_emac_flash). But now after reading your post (multiple times), it looks like you are reentering the bootloader after updating firmware (and not using the "swupdate" utility). Is this correct?

    If so, then how is your application entering the bootloader? Is it by using a scheme similar to the one showed in "boot_demo_flash", where the SVC handler in the flash-based bootloader is called (after disabling interrupts)? If so, I am able to enter the bootloader ("boot_emac_flash") from the application "boot_demo_flash", and reprogramming the application (boot_demo_flash). I am able to repeat the sequence multiple times with TivaWare versions 2.1.3.156 and 2.1.0.12573.

    CamK said:
    in uip_arp.c, I modified the uip_arp_out() function as follows

    As a matter of practice, I don't recommend modifying the uIP code. This is a third party stack and we don't have an in-house expert to comment on the impact of the modifyications you posted.

    Thanks,

    Sai