Updating Application through W5500

Nowadays, most of the commercialized gidgets have been having new versions in terms of software or hardware. For example, you update your smartphones from time to time; there are always new versions of the same series of products, Dyson Electrical Fan for instance. If you have ever planned about commercializing your IoT idea/product, learning how to update your product with W5500 is essential for you.

By utilizing W5500, users do not have to plug their product into the computer every time they want to update the program, instead they can remotely do the update. Apart from how TCP and UDP works, which you must have already learned at this point, you need knowledge about how to manipulate the data in the memory of your MCU.

The file for this tutorial consists of three parts: original boot file, file to be used for the update, and an EXE file of sending command and data to your W5500EVB.

Before burning the bin file into your EVB:

      1. Connect W5500 EVB to the router/NAT that you are using, or any other device that allows you to connect to the internet
      2. Manually change the Network configuration: 
        • Go to “w5500_conf.c”, make sure the subnet mask, local IP address, gateway and DNS are set according to the internet setting you are using with your router/NAT
      3. Rebuild the sample code and burn it into W5500EVB


Steps for Testing

  1. Make sure all the network setting matches the one on you computer
  2. Burn boot.bin into W5500EVB
  3. Open your serial port
  4. Open the Config Tool(ConfigTool_Nuri) downloaded from the website
Photo: Step 3 & 4 for Testing
Photo: Step 4 – Default screen of ConfigTool


5. Press “Search”, device settings will be shown if W5500EVB is successfully connected to your computer
6. If the connection is established, you will receive “FIND” from your serial port

Photo: Step 5 & 6 of Step for Testing


7. Kindly try the following four options

  • Search: search for W5500EVB
  • Setting: Set and save the device setting detail to your W5500EVB if you have made any changes
  • Reset: Not applicable in this tutorial
  • Firmware Upload: upload your selected bin file to your W5500EVB, in this case “app.bin”

It is suggested that you do the firmware upload last.

Photo: Step 7 of Step for Testing
Photo: Firmware Upload
Photo: Firmware Upload Done


8. Once you are doing firmware upload, you will receive messages as shown below:

Photo: Step 8 of Step for Testing

Once the upload is done, you can try the two out of four options again and observe the difference: “Search” and “Setting”. Please be reminded that the sample code is not decided for another update. If you update the firmware again with either  “boot.bin” or “app.bin”, the outcome would be unexpected.

To try or test the whole process again, you have to burn the “boot.bin” file into W5500EVB.


Logic Flow

To know more about how this firmware update example works, first we have to take a look at the memory table:

Photo: Memory Table from STM32F103xx Reference Manual, P.56

By taking another look at the logic flow below, you will know why it is worth to mention the memory map:

Photo: Logic Flow of the Program for Firmware Update

The update process used in this sample code does not erase or remove any part of the code before update. Some parts of the not-yet-updated code will still be involved in the updated program. Therefore, technically it is more like two sets of code combined rather than the original code being altered or changed. The uploaded code of firmware will dominate the process, while only the very little part of the old-version main() is involved in the program. The other major part of the old-version firmware remains in the memory without being involved in the program.

By knowing the logic and the functions involved, you can definitely create your own way of firmware update.


Code Explanation

int main(void)
{
  systick_init(72);
  NVIC_Configuration();
  USART1_Config();
  gpio_for_w5500_config();
  reset_w5500();	
  get_config();

  addr = ApplicationAddress;
  app_first_4_bytes = *(uint32_t*)addr;
/****************


Necessary Configuration




Storing the address of the
location where the new
firmware would be stored
****************/

By referring to the Logic Flow mentioned above, the IF statement defines how the program goes.

  if ((app_first_4_bytes & 0xffffffff) == 0xffffffff)
  {
    printf("\r\nW5500 Demo Code for Remote IAP.\r\n");
    printf("Please upload APP by using ConfigTool\r\n");
    set_default();
    set_network();
  }

  else
  {	    
    switch (ConfigMsg.state)
    {
      case NORMAL_STATE:
        printf(" NORMAL_STATE.\r\n");
        for(i=0;i<1000;i++);
        reboot_app();
        break;

      case  NEW_APP_IN_BACK:
        printf("NEW_APP_IN_BACK.\r\n");
        printf("Copy App: %d\r\n", ConfigMsg.fw_len);
        copy_app(ConfigMsg.fw_len);
        ConfigMsg.fw_len = 0; 
        ConfigMsg.state=NORMAL_STATE;
        write_config_to_flash();
        reboot_app();
        break;
    
      default:
        printf("unknown state=%d\r\n",ConfigMsg.state);
        break;
    }    
  }
   
  while(1)
  {
    do_udp_config();
    do_fw_update();
  }
} 
/****************
If Updated Firmware is not
uploaded yet





If the Updated Firmware is 
uploaded








case NEW_APP_IN_BACK is
not applicable for this
tutorial













Opening two sockets
+ One for message and
  notification
+ One for firmware data
  transfer
****************/

Under the switch statement, the “case NEW_APP_IN_BACK” and default would never happen in this sample code, therefore you can focus only in “case NORMAL_STATE”. The function reboot_app() appears under the “case NORMAL_STATE”, which means whenever an updated firmware is uploaded, “reboot_app()” will be run. It would be discussed below together with the function “reboot()”.

Else if the firmware is not uploaded yet, it directly goes into the main while loop, which contains two functions: do_udp_config() and do_fw_update();


do_udp_config()

As defined by the function’s name, it opens an UDP socket for communication between W5500EVB and updated firmware file holder. In this case the holder would be our computer.

As mentioned previously, there are three options to choose in ConfigTool. In other words, there are three IF statements for messages transferring to the computer. Respectively they are:

  • FIND refers to Search in ConfigTool
  • SETT refers to Setting in ConfigTool
  • FIRM refers to Firmware Upload in ConfigTool
void do_udp_config(void)
{
  memset(&RecvMsg,0,sizeof(RecvMsg));   //clear RecvMsg
  sckState=getSn_SR(SOCK_CONFIG);

  switch(sckState)
  {
    case SOCK_UDP:
      if((len=getSn_RX_RSR(SOCK_CONFIG))>0)
      {		
        if(len>MAX_BUF_SIZE) len=MAX_BUF_SIZE;
        recvfrom(SOCK_CONFIG, (uint8 *)&RecvMsg, len, rIP, &rPort);


If “FIND” as an UDP message is received, EVB sends a response back to computer with the send message “FIND” but with its own network configuration so that the computer knows EVB’s configuration for further actions.

if((RecvMsg.op[0]=='F') && (RecvMsg.op[1]=='I') && (RecvMsg.op[2]=='N') && (RecvMsg.op[3]=='D'))
        {
          RecvMsg = ConfigMsg;
          RecvMsg.op[0]='F';RecvMsg.op[1]='I';RecvMsg.op[2]='N';RecvMsg.op[3]='D';
       
        //response
          sendto(SOCK_CONFIG, ( uint8 *)&RecvMsg, sizeof(RecvMsg), bIP, rPort);
          printf("Find\r\n");
        }


If “SETT” as an UDP packet is received, EVB will change its own network configuration according to the request from the computer, which can also be known as Configuration Update. It reboots after the config update.

        else if((RecvMsg.op[0]=='S') && (RecvMsg.op[1]=='E') && (RecvMsg.op[2]=='T') && (RecvMsg.op[3]=='T'))
        {
          printf("SEET\r\n");
          if((RecvMsg.mac[0]==ConfigMsg.mac[0]) && (RecvMsg.mac[1]==ConfigMsg.mac[1]) && (RecvMsg.mac[2]==ConfigMsg.mac[2]) && 
           (RecvMsg.mac[3]==ConfigMsg.mac[3]) && (RecvMsg.mac[4]==ConfigMsg.mac[4]) && (RecvMsg.mac[5]==ConfigMsg.mac[5]))
          {					
            ConfigMsg = RecvMsg;
            write_config_to_flash();
            reboot();
          }
        }


If “”FIRM” as an UPD packet is received, EVB will send a response to the computer as a signal, asking the computer to connect to another socket for firmware data transmission.

 else if((RecvMsg.op[0]=='F') && (RecvMsg.op[1]=='I') && (RecvMsg.op[2]=='R') && (RecvMsg.op[3]=='M'))
        {
          printf("FIR\r\n");
          //printf("firmware upload\n");
          if((RecvMsg.mac[0]==ConfigMsg.mac[0]) && (RecvMsg.mac[1]==ConfigMsg.mac[1]) && (RecvMsg.mac[2]==ConfigMsg.mac[2]) && 
           (RecvMsg.mac[3]==ConfigMsg.mac[3]) && (RecvMsg.mac[4]==ConfigMsg.mac[4]) && (RecvMsg.mac[5]==ConfigMsg.mac[5]))
          {    
          //response
            sendto(SOCK_CONFIG, (uint8 *)&RecvMsg, sizeof(ConfigMsg),bIP, rPort);
          }
        }
      }
      break;


If socket is closed, it opens an UDP socket.

    case SOCK_CLOSED:
      socket(SOCK_CONFIG, Sn_MR_UDP, UDP_PORT, 0);
      break;
  }
}



do_fw_update()

This function opens a TCP socket for Firmware’s data transmission. To receive the firmware, EVB keeps listening until the computer sends a handshake, then establishes TCP connection with the computer.

Other than that, it processes the Flash’s functions in order to burn the firmware into flash memory simultaneously with receiving firmware’s packets.

void do_fw_update(void)
{
  uint32 len=0;
  uint32 i;
  switch(getSn_SR(SOCK_FW))
  {
  case SOCK_ESTABLISHED:

  /******************************************************
    Preparation of burning new firmware into Flash Memory
   *******************************************************/

    if(getSn_IR(SOCK_FW) & Sn_IR_CON)
    {
      FLASH_Unlock();

      FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
      setSn_IR(SOCK_FW, Sn_IR_CON);
    }

    if((len=getSn_RX_RSR(SOCK_FW))>0)
    {


Once this TCP socket receives data from the computer, it calculates how many pages of flash memory needed to store the whole new firmware, and erases the flash memory of a particular location, waiting for new firmware to be written on. Then the flag “isErased” will be set so that no more erasing would be done.

      if((len==4) && (isErased==0))   
      {
        recv(SOCK_FW, (uint8*)&fLen,4);
        
        nPage=FLASH_PagesMask(fLen);
        
        for(nErasedPage=0; nErasedPage<nPage; nErasedPage++)
        {
          FLASH_ErasePage(flashDest + pageSize*nErasedPage);
        }
        isErased=1;
        //send the len to PC program to tell him flash erased over
        send(SOCK_FW, (uint8*)&fLen, (uint16)4);
        printf(">");
      }



Once empty memory is confirmed, EVB starts receiving packets of new firmware. In the meantime it keeps sending message to the computer to assure the proper transmission of the firmware.

      else
      {
        recv(SOCK_FW, buf, len);
        printf(".");
        for(i=0;i<len;i+=4)
        {
          FLASH_ProgramWord(flashDest,*(uint32*)((uint32)buf + i));
          flashDest+=4;
        }
        rxLen+=len;
        
        send(SOCK_FW, (uint8*)&len, (uint16)4);  //echo to PC program


EVB was notified the size of the new firmware from the first message. When the whole firmware is received properly, EVB disconnects with the computer. And Flash Lock would be executed within the function of “write_config_to_flash()”.

Finally it runs the new firmware through “reboot_app()”.

        if(rxLen==fLen)
        {
          disconnect(SOCK_FW);
          //save to flash
          ConfigMsg.fw_len = fLen;
          ConfigMsg.state=NORMAL_STATE;
          write_config_to_flash();
          printf("\r\nOK.\r\n");
          
          //jump to app
          for(i=0;i<1000;i++);
          reboot_app();
        }
      }
    }
    break;


It initializes necessary variables whenever it opens the TCP socket.

  case SOCK_CLOSED:
    rxLen=0;
    nPage=0;
    nErasedPage=0;
    fLen=0;
    isErased=0;
    close(SOCK_FW);  
    socket(SOCK_FW,Sn_MR_TCP,TCP_RE_PORT,Sn_MR_ND);
    break;

  case SOCK_INIT:
    listen(SOCK_FW);
    break;

  case SOCK_CLOSE_WAIT:
    break;
  }
}



reboot_app() VS reboot()

Reboot normally means restart the boot-loading process. STM32F103xx micro-controller bootloading process starts with address 0x00000000, which contains the value to initialize program counter(PC) and main stack pointer(MSP). The function reboot() direct PC and MSP back to 0x00000000 and trigger the bootloading process.

While for reboot_app(), it directs PC and set to MSP to address where the bootloading of new firmware starts,

The following code clearly shows the difference between these two functions. Please keep in mind that both the new and original firmwares are stored in the memory but at different local. Neither of them is erased or altered.

void reboot_app(void)
{
  pFunction Jump_To_Application;
  uint32 JumpAddress;



/** The address of new Firmware **/
  /** 0x08008000 + 0x00000004 **/
printf(" Reboot_App processing...\r\n");
  JumpAddress = *(vu32*) (ApplicationAddress + 0x00000004);


  Jump_To_Application = (pFunction) JumpAddress;



  /** Set application's stack pointer **/
  __set_MSP(*(__IO uint32_t *)ApplicationAddress);


  Jump_To_Application();
}
void reboot(void)
{
  pFunction Jump_To_Application;
  uint32 JumpAddress;



/** The address of Original Firmware **/
    /** 0x00000000 + 0x00000004 **/
  printf(" Reboot processing...\r\n");
  JumpAddress = *(vu32*) (0x00000004);


  Jump_To_Application = (pFunction) JumpAddress;



  /** No action for stack pointer **/



  Jump_To_Application();
}



Remarks

  • Understanding the Memory and bus architecture, especially the concept of page may help you understand how the management of the is worked in the sample code.
  • Understanding the Booting process of MCU (STM32) helps understand how to boot reboot the device into a different firmware file. The following terms and concepts are of high importance if you are interested in comprehend the whole firmware update process:
    • Program counter
    • Stack
    • Main Stack Pointer
    • Jump to Function
  • Function pointer is involved in “Jump to Function” in an unusual way. Please be noted that function pointer is used with the concept of memory address

  • Since the new firmware is similiar to the original firmware, basically with more “printf()” functions involves, therefore you can study it by yourself to find the difference. Once may have to notice that there is no “reboot_app()” functions involved in new firmware. They are replaced by “reboot()”.



Download