W5500EVB as TFTP Client

TFTP, Trivial File Transfer Protocol, is a simple lockstep File Transfer Protocol which allows a client to get a file from or put a file onto a remote host. Similar to but simpler than FTP, File Transfer Protocol, UDP is used for TFTP for simplicity, and the maximum size of file to be transferred is 32MB.

In terms of IoT, TFTP is an convenient protocol that IoT devices usually do not require large firmware files to run with, nor have a large memory store within the device itself but back-up necessary data to cloud storage. It is therefore always good to understand TFTP.


Before burning the bin file into your EVB:

      1. There are two sets of files when you download it. Please be reminded that “Boot_TFTP” is the code for your W5500EVB, while “APP_LED” is the code for TFTP Server
      2. Connect W5500 EVB to the router/NAT that you are using, or any other device that allows you to connect to internet
      3. Manually change the Network configuration: 
        • Go to the definition of function set_default() (Should be inside device.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
        • Change the remote_ip, remote_port and local_port according to your terminal’s network setting. The remote_ip should be exactly the same as your terminal’s.
      4. Rebuild the sample code and burn it into W5500EVB
      5. Turn off the firewall if necessary

Step for Testing

To test to see if the TFTP Client works, you need to have a TFTP server. It is suggested to use a free TFTP server called “tftpd64/tftpd32”, which is easy to be found on the internet.

Set up TFTP server step by step:

  1. Open tftpd64/tftpd32 (icon as shown in the picture)
  2. First click the “Tftp Server”
  3. Then click “browse” and choose the directory which contain the bin file(in this example “app.bin”) you would like to get with your W5500EVB
  4. Press “Show Dir”, you should see your desired file name there
  5. Make sure “Server interfaces” is the same as the IP you have set for W5500EVB
  6. Click “settings” and  click “TFTP”
  7. Click “Browse” choose the base directory, which should be the same as the current directory you have just set
  8. Make sure the Tftp port of TFTP configuration is 69, which a commonly used for TFTP
  9. Click OK, then open terminal and start running W5500EVB.
Photo: Step.1, Icon of tftpd64/tftpd32
Photo: Step 2 to Step 6
Photo: Step 6 to Step 9


When running W5500EVB, please make sure steps mentioned in “Before burning the bin file into your EVB’ has already been done. Then s
end “app.bin%0D%0A” in terminal.

The file is successfully gotten from TFTP Server and a message “TFTP SUCCEED” is received. You may noticed that the LEDs on your board start blinking with patterns.

Photo: Successfully Receive the desired file from TFTP Server


Code Explanation

The structure of the program is similar to the sample code of UDP, since it is based on UDP. Therefore to understand more about the program, you may pay more attention to the following functions: TFTP_init(), TFTP_read_request, TFTP_run. There will be reminders below.

int main(void)
{


After most of the necessary initialization, TFTP_init() is called, which is basically to clear the some data that previously stored and to open a socket as an UDP socket.

  uint8 len,ret;	
  u32 addr; 
  u32 app_first_4_bytes;
  Systick_Init(72);
  NVIC_Configuration(); //NVIC Configuration	
  USART1_Init();
  GPIO_Configuration(); //GPIO configuration
  TIM3_Int_Init(1000,71);
  printf("\r\n MCU initialized.\r\n");
  Reset_W5500();
  WIZ_SPI_Init();
  set_w5500_mac();
  set_default();
  set_network(); 
  printf("Network is ready!\r\n");
  addr = ApplicationAddress;
  app_first_4_bytes = *(vu32*)addr;

// if there is no app code in flash
  if ((app_first_4_bytes & 0xffffffff) == 0xffffffff)
  { 
    write_config_to_eeprom(); 
  }	
  get_config();//read config data from flash 
  TFTP_init(SOCK_TFTP,g_socket_rcv_buf);	

/******************





 These are all the necessary
 initialization













 Clear the some data that previously
 stored and to open a socket as
 an UDP socket.
********************/


Then the program enters into the main loop and starts by checking if the version is the newest version. In this example the program is always not up to date that users can keep testing the program.

  while(1)
  {
    
    if((ConfigMsg.newfirm[0]!=ConfigMsg.sw_ver[0])||(ConfigMsg.newfirm[1]!=ConfigMsg.sw_ver[1]))
    {
      if(USART_RX_STA&0x8000)
      {
        len=USART_RX_STA&0x3fff;
        printf("\r\nsend new version filename: %s\r\n",USART_RX_BUF);
        memcpy(ConfigMsg.filename,USART_RX_BUF,len);
        USART_RX_STA=0;
        memset(USART_RX_BUF,0,len+1);
        filename_flag=1;
      }
      if(filename_flag==1)
      {
        filename_flag=0;
        printf(" TFTP START\r\n");
        tftp_server = (remote_ip[0] << 24) | (remote_ip[1] << 16) | (remote_ip[2] << 8) | (remote_ip[3]);
        TFTP_read_request(tftp_server,ConfigMsg.filename);
        
/****************


  Check Version

  Check the RX buffer if any kind of data is received.
  Message goes into the RX_buffer, which triggers the update process.


  Get and store data from RX buffer to other buffer 

  Clear the RX buffer for packets from the TFTP Server.






  TFTP Server's IP
  Send TFTP Request to Server
****************/


Once request is sent, the TFTP Server will send a response back to indicate whether the file exist, along with the file if it does. It loops until at least a packet is received.

        while(1)
        {	
          ret = TFTP_run();
          if(ret != TFTP_PROGRESS)
          break;
        }
        if(ret == TFTP_SUCCESS)
        {
          printf("TFTP SUCCEED\r\n");	
          TIM_Cmd(TIM3, DISABLE);
          Delay_ms(10);
          reboot_app();
        }
/****************

Receive packet from TFTP Server
It loops until at least a packet is received







Run the updated program if it exists
****************/


if the version of the program was up to date, it does nothing but reboot.

      }
    }
    else
    {
      printf(" newersion do not find, start oldversion\r\n");
      TIM_Cmd(TIM3, DISABLE);	
      reboot_app();
    }
  }
}

When the update is done, W5500EVB starts with a new firmware, with LEDs blinking in pattern.

According to the code, once W5500EVB has reseted, it starts with the original, requiring you to update the program for you to test again.


TFTP_read_request()

A request will be sent according to the message you sent from the terminal and the remote IP address you have set before Through this function. For “send_tftp_rrq()”, it assembles necessary data, constructs them into a packet, and sends it to TFTP Server. Please refer to the function “send_tftp_rrq()” for more detail.

void TFTP_read_request(uint32_t server_ip, uint8_t *filename)
{
  set_server_ip(server_ip);

  #ifdef __TFTP_DEBUG__
    printf("[%s] Set Tftp Server : %x\r\n", __func__, server_ip);
  #endif

  g_progress_state = TFTP_PROGRESS;
  send_tftp_rrq(filename, (uint8_t *)TRANS_BINARY, &default_tftp_opt, 1);
}


TFTP_run()

If the file exists on the server, the file will be divided into packets and be received one by one, until the whole file is received. Acknowledgement will be sent to the server whenever a packet is well received and is stored buffer so as to inform the server W5500EVB is ready for the next packet.

int TFTP_run(void)
{
  uint16_t len, from_port;
  uint32_t from_ip;

/* Timeout Process */
  if(g_resend_flag) 
  {
    if(tftp_time_cnt >= g_timeout) 
    {
      switch(get_tftp_state()) 
      {
        case STATE_WRQ:				
          break;

     /* Case for sending request again when no response is received */
        case STATE_RRQ:  
          send_tftp_rrq(g_filename, (uint8_t *)TRANS_BINARY, &default_tftp_opt, 1);
          break;

        case STATE_OACK:

     /* Case of sending Ack to inform the Server that it is ready for the next packet */
        case STATE_DATA:
          send_tftp_ack(get_block_number());
          break;

        case STATE_ACK:				
          break;

        default:
          break;
      }
      tftp_time_cnt = 0;
      tftp_retry_cnt++;
      if(tftp_retry_cnt >= 5) 
      {
        init_tftp();
        g_progress_state = TFTP_FAIL;
      }
    }
  }

/* Receive Packet Process */
  len = recv_udp_packet(g_tftp_socket, g_tftp_rcv_buf, MAX_MTU_SIZE, &from_ip, &from_port);
  if(len < 0) 
  {
    #ifdef __TFTP_DEBUG__
      printf("[%s] recv_udp_packet error\r\n", __func__);
    #endif
    return g_progress_state;
  }

  recv_tftp_packet(g_tftp_rcv_buf, len, from_ip, from_port);
  return g_progress_state;
}



Remarks

  • Once a TFTP connection is successful, information will appear on server’s window, as shown in the picture. It disappears a few seconds after the transfer is done. There will also be a record shown in “Log viewer”.

  • The following picture shows the message you would get if the run the program but the connection does not succeed, which would probably be that the server is not found, receiving no message after sending a request.
    Note: the tftpd64 windows does not necessarily show anything in such case.
Photo: W5500EVB does not find the server, receiving no response

  • The following picture shows the message you would get if the file you set is not found from the server.
Photo: File does not exist on the Server

  • Please always make sure the procedure mentioned in “Before burning the bin file into your W5500EVB” is done.