ESP8266 RTOS : Device Firmware Update Over the Air (DFU-OTA) via the Private Server_u013606170的博客-程序员ITS203

技术标签: 物聯網  linux  單片機  

      ESP8266 is a very popular micro-controller featuring WIFI with its bargaining price. There are some product based on ESP8266/ESP8285 (ESP8285 = ESP8266 embedded 1 MB flash) for home IoT using. The makers enjoy remolding the firmware of the products to fix their personal purposes.

      In most case, the maker re-program ESP8266 in the framework of Arduino, thus, there are lots post and discussion about how to deal with DFU-OTA based on ESP8266 Arduino. However, The information about the same goal but the ESP8266 based on RTOS framework is limited, undocument or incomplete. This post wants to fill the gap.

   By default, DFU-OTA server is based on Espressif: It forces the ESP8266 to be on internet. But some use case the ESP8266 would not be connected with internet (maybe for the security issue). Therefore, private DFU-OTA is very necessary. In here I assume your DFU-OTA server is linux based, But it is easy to port the DFU-OTA function to the other platform, for the DFU-OTA working principle is typical TCP-IP.

 

Notethis example assumes your esp8266 is within 1MB flash!  It may work in otherwise size or not I am not sure.

 

 

零. Download the requisite library:

     In here, You should download the include/upgrade.h,  user/upgrade_lib.c and user/fota_crc32.c., and move them into your ESP8266 project folder. I assume the files place under the sub-folder, dfu-ota, of your project folder.

   

一. Create a c file,  named  dfu_ota.c, under the same sub-folder, the code be :

 

#include "esp_common.h"
#include "espconn.h"


#include "dfu_ota.h"
#include "upgrade.h"



#define LOCAL     static

LOCAL struct espconn g_tcp_client;
LOCAL esp_tcp g_tcp;
LOCAL int g_firmware_length = 0;

enum 
{
 TCP_CONNECTING   = 0x00,
 SENT_TARGET_SECTION  = 0x01,
 RECEIVED_LENGTH   = 0x02,
 KEEP_RECEIVING_DATA  = 0x03,
 RECEIVED_DATA   = 0x04,

 TCP_DISCONNECTED = 0xff,
};


LOCAL int g_sending_state = TCP_DISCONNECTED;


int firmware_upgrading_fail(void)
{ 
 printf("upgrading fail\r\n");
 espconn_disconnect(&g_tcp_client);

 printf("reboot the system\r\n");
 system_restart();
}/*firmware_upgrading_fail*/


//LOCAL uint8_t g_tcp_server_ip[4] = {0};
LOCAL uint8_t g_tcp_retry_connection_count = 0;

LOCAL void tcp_connection_error_callback(void *arg, int8_t err)
{
 struct espconn *p_tcp_server;
 p_tcp_server = arg;

 printf("tcp connection err = %d\r\n", err);

 if(ESPCONN_OK != err)
 {
#define MAX_RETRY_CONNECTION_COUNT   (5)

  if(MAX_RETRY_CONNECTION_COUNT > g_tcp_retry_connection_count)
  {
   printf("retry the tcp connection...\r\n");
   delay_ms(1000);
   g_tcp_retry_connection_count++;
   espconn_connect(&g_tcp_client);
  }
  else
  {
   printf("relinquish this upgrading\r\n");
   g_tcp_retry_connection_count = 0;
   firmware_upgrading_fail();
  }/*if */
 }/*if ESPCONN_OK */

}/*tcp_connection_error_callback*/


LOCAL void tcp_connect_callback(void *arg)
{
 struct espconn *p_tcp_server;
 uint8_t tcp_state;
 uint8_t target_section;
 p_tcp_server = arg;

 if(USER_BIN1 == system_upgrade_userbin_check())
 {
  target_section = 2;
  printf("current firmware in user1\r\n");
 }
 else
 {
  target_section = 1;
  printf("current firmware in user2\r\n");
 }

 printf("fetch firmware%d\r\n", target_section);

 tcp_state = espconn_send(p_tcp_server, &target_section, sizeof(uint8_t));
 printf("target_section sending\r\n");
 g_sending_state = SENT_TARGET_SECTION;
#define INTERVAL_BETWEEN_PACKETS_IN_MSEC  (10)

 delay_ms(INTERVAL_BETWEEN_PACKETS_IN_MSEC);
}/*tcp_connect_callback*/


LOCAL void tcp_sent_to_buffer_callback(void *arg)
{
 struct espconn *p_tcp_server;
 uint8_t tcp_state;

 p_tcp_server = arg;
}/*tcp_sent_to_buffer_callback*/


#define OTA_PACKET_SIZE     (1280)
LOCAL int g_remained_firmware_length = 0;

LOCAL void tcp_received_callback(void *arg, char *p_data, unsigned short len)
{
 struct espconn *p_tcp_server;
 uint8_t tcp_state;
 uint8_t data_buffer[OTA_PACKET_SIZE];

 p_tcp_server = arg;

 switch(g_sending_state)
 {
  case SENT_TARGET_SECTION:
  if(sizeof(int) != len)
  {
   printf("received length error\r\n");
   goto Flag_Error_Occurring;
  }/*if */

  g_sending_state = RECEIVED_LENGTH;
  memcpy(&g_firmware_length, p_data, sizeof(int));
  printf("firmware size = %d\r\n", g_firmware_length);

  if(g_firmware_length < 0)
  {
   printf("firmware_length error\r\n");
   goto Flag_Error_Occurring;
  }
  g_remained_firmware_length = g_firmware_length;
  break;


  case RECEIVED_LENGTH:
  case KEEP_RECEIVING_DATA:

  memcpy(&data_buffer[0], p_data, len);
  g_remained_firmware_length -= len;

  if(0 > g_remained_firmware_length)
  {
   printf("received data size is not marched\r\n");
   goto Flag_Error_Occurring;
  }

  printf("received firmware data %d bytes, remain %d bytes...\r\n", 
   g_firmware_length - g_remained_firmware_length, g_remained_firmware_length);

  if(false == system_upgrade(&data_buffer[0], len))
  {
   printf("\r\nsystem_upgrade error\r\n");
   goto Flag_Error_Occurring;
  }/*if false == system_upgrade*/


  if(0 == g_remained_firmware_length)
  {
   printf("\r\n firmware has been downloaded done\r\n");
   g_sending_state = RECEIVED_DATA;

   if( false == upgrade_crc_check(system_get_fw_start_sec(), g_firmware_length))
   {
    printf("firmware upgrading FAIL : CRC is not consisted!!\r\n");
    system_upgrade_flag_set(UPGRADE_FLAG_IDLE);
    espconn_disconnect(&g_tcp_client);
   }
   else
   {
    printf("firmware upgrading is successful.\r\n");
    system_upgrade_flag_set(UPGRADE_FLAG_FINISH);
    espconn_disconnect(&g_tcp_client);
   }/* check crc*/
  }
  else
  {
   system_upgrade_flag_set(UPGRADE_FLAG_IDLE);
   g_sending_state = KEEP_RECEIVING_DATA;
  }
  break;
 default:
  break;
 }
 return;


Flag_Error_Occurring:
 firmware_upgrading_fail();
 return;
}/*tcp_received_callback*/


LOCAL void tcp_disconnect_callback(void* arg)
{
 printf("ota server disconnected\r\n");
 g_sending_state = TCP_DISCONNECTED;

 system_upgrade_deinit();
 if (UPGRADE_FLAG_FINISH == system_upgrade_flag_check())
 {
  printf("reboot the system for new firmware\r\n");
  system_upgrade_reboot();
 }
 else
 {
  printf("upgrade firmware fail\r\n");
  system_restart();
 }

}/*tcp_disconnect_callback*/



int device_firmware_upgrade_over_the_air(uint8_t *p_server_ip)
{
 uint8_t con_status;
 uint8_t tcp_state;

 printf("start device firmware upgrading over the air...\r\n");


 con_status = wifi_station_get_connect_status();
 
 if (con_status != STATION_GOT_IP) 
 {
  printf("error, this endpoint has not be connected with router.\r\n");
  printf("relinquish this firmware upgrading.\r\n");
  firmware_upgrading_fail();
  return -1;
 }/*if*/


#define TCP_SERVER_REMOTE_PORT       (5555)
 g_tcp.remote_port = (TCP_SERVER_REMOTE_PORT);
 g_tcp_client.type = ESPCONN_TCP;
 g_tcp_client.proto.tcp = &g_tcp;

 memcpy(g_tcp.remote_ip, p_server_ip, 4*sizeof(uint8_t));

 espconn_regist_reconcb(&g_tcp_client, tcp_connection_error_callback);
 espconn_regist_connectcb(&g_tcp_client, tcp_connect_callback);
 espconn_regist_sentcb(&g_tcp_client, tcp_sent_to_buffer_callback);
  espconn_regist_recvcb(&g_tcp_client, tcp_received_callback);
 espconn_regist_disconcb(&g_tcp_client, tcp_disconnect_callback);

 system_upgrade_flag_set(UPGRADE_FLAG_START);
 system_upgrade_init();


#define RELATIVE_END_SECTOR_NUM     (0x80 - 0x0c)
 {
  uint16_t begin_sector;
  uint16_t i;
  printf("erasing flash sector to store new firmware, it takes a while...\r\n");
  begin_sector = system_get_fw_start_sec();
  printf("erasing flash sector from 0x%02x to 0x%02x\r\n", begin_sector, 
   begin_sector + RELATIVE_END_SECTOR_NUM - 1);

  for(i = 0; i< RELATIVE_END_SECTOR_NUM; i++)
   spi_flash_erase_sector(begin_sector + i);
 }/*erase flash*/


 tcp_state = espconn_connect(&g_tcp_client);
 g_sending_state = TCP_CONNECTING;

 if(0 != tcp_state)
 {
  g_sending_state = TCP_DISCONNECTED;
  printf("espconn_connect error, give up this connection\r\n");
  firmware_upgrading_fail();
 }/*if 0*/

 return 0;
}/*device_firmware_upgrade_over_the_air*/

 

The corresponding header dfu_ota.h placed in the same folder, is,

 

#ifndef _DFU_OTA_H_
#define _DFU_OTA_H_


int device_firmware_upgrade_over_the_air(uint8_t *p_server_ip);

#endif

 

To here, the content under dfu_ota folder  be :

$ ls dfu_ota/
dfu_ota.c  dfu_ota.h  fota_crc32.c  Makefile  upgrade.h  upgrade_lib.c

 

The Makefile under dfu_ota folder, copied from common sub-folder, is with the modification, about line 14:

ifndef PDIR
GEN_LIBS = libdfu_ota.a
endif

 

The Makefile under your project's root folder, Should be added the dfu_ota content:

SUBDIRS=    \
        user    \
        :
        dfu_ota
:
:
COMPONENTS_eagle.app.v6 = \
        user/libuser.a  \
        :
        dfu_ota/libdfu_ota.a

 

 

二. DFU-OUA server code.

The DFU-OTA server would be responding the DFU requesting, the code, dfu_ota_server.c be:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#include <linux/limits.h>

//#include <inttypes.h>

 #include <errno.h>

#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

#include <signal.h> 

#include <sys/stat.h>

/*for show ip*/
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>

#include <pthread.h>

#ifdef __mips__
 #include <byteswap.h>
#endif

#include <sys/time.h>


#define PORT_NUMBER       (5555)

#define ONE_PACKET_MAX_SIZE     (4*1024)

#define LOCAL         static

#define INVALID_SOCKET      (int)(~0)
#define MAX_CLIENT_NUMER     (32)



void delay_micro_sec(unsigned int delay_time_in_us)
{
 struct timeval now;
 struct timeval period;
 struct timeval end;

 gettimeofday(&now, NULL);

 period.tv_sec = delay_time_in_us / 1000000;
 period.tv_usec = delay_time_in_us % 1000000;

 timeradd(&now, &period, &end);

 while(timercmp(&now, &end, < ))
  gettimeofday(&now, NULL);

}/*delay_micro_sec*/


LOCAL int g_master_socket;
LOCAL int g_client_socket;

int esp8266_ota_server_start(char **pp_firmware_location)
{
 int i;
 struct sockaddr_in server_addr;

 if(NULL == pp_firmware_location[0] || NULL == pp_firmware_location[1])
 {
  return -1;
 }

 g_master_socket = socket(AF_INET , SOCK_STREAM , 0);

 if(-1 == g_master_socket)
 {
  printf("Could not create socket\r\n");
  return -1;
 }/*if*/

 //Prepare the sockaddr_in structure
 server_addr.sin_family = AF_INET;
 server_addr.sin_addr.s_addr = INADDR_ANY;
 server_addr.sin_port = htons(PORT_NUMBER);

 {
  int reuseaddr;
  int reuseaddr_len;
  reuseaddr = 1;
  reuseaddr_len = sizeof(reuseaddr);
  setsockopt(g_master_socket, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, reuseaddr_len);
 }/*local variabe */

 //Bind
 if(0 > bind(g_master_socket,(struct sockaddr *)&server_addr , sizeof(server_addr)) )
 {
  perror("bind failed. Error\r\n");
  return -2;
 }/*if bind*/
 printf("ota server is ready to be connected\r\n\r\n");


#define MAX_PENDING_CONNECTION_NUMBER   (3)

 listen(g_master_socket , MAX_PENDING_CONNECTION_NUMBER);

 while(1)
 {
  struct sockaddr_in client_addr;
  int socket_len;

  int written_len;
  unsigned int firmware_size;
  int is_succ_sent;

  unsigned char target_firmware_section;

  g_client_socket = accept(g_master_socket, 
   (struct sockaddr *)&client_addr, (socklen_t*)&socket_len);

  if(INVALID_SOCKET == g_client_socket)
  {
   printf("accepted ERROR\r\n");
   continue;
  }/*if */

  printf("\r\n\r\n%s connected\r\n", inet_ntoa(client_addr.sin_addr));

  is_succ_sent = 0;
  {
   socklen_t addr_len;

   addr_len = sizeof(client_addr);
   getpeername(g_client_socket, (struct sockaddr*)&client_addr, &addr_len);
  }/*local variable*/


  {
   struct timeval timeout_val;

#define MAX_ONE_PACKET_TIMEOUT_IN_SEC    (10)
   timeout_val.tv_sec = MAX_ONE_PACKET_TIMEOUT_IN_SEC;
   timeout_val.tv_usec = 0;

   setsockopt(g_client_socket, SOL_SOCKET, SO_SNDTIMEO, 
    &timeout_val, sizeof(timeout_val));

   setsockopt(g_client_socket, SOL_SOCKET, SO_RCVTIMEO, 
    &timeout_val, sizeof(timeout_val));
  }/*local variables*/

  {

   unsigned char read_buffer[16];
   int read_size;

   read_size = read(g_client_socket, &read_buffer[0], sizeof(read_buffer));
   if(1 != read_size)
   {
    printf("received firmware region index size error\r\n");
    goto Flag_end_connection;
   }
   target_firmware_section = 0;
   memcpy(&target_firmware_section, &read_buffer[0], sizeof(unsigned char));


   if(!(1 == target_firmware_section || 2 == target_firmware_section) )
   {
    printf("received firmware region index is not valid\r\n");
    printf("firmware_region_index = %d\r\n", (int)target_firmware_section);
    goto Flag_end_connection;
   }/*if*/

   printf("firmware%d would be transmitted to endpoint\r\n", (int)target_firmware_section);
  }/*local variable*/

  {
   struct stat fw_dir_st = {0};

   if(-1 == stat(pp_firmware_location[target_firmware_section - 1], &fw_dir_st))
   {
    printf("ERROR :: %s does not exist!\r\n", 
     pp_firmware_location[target_firmware_section - 1]);

    goto Flag_end_connection;
   }/*if */

   firmware_size = (int)fw_dir_st.st_size;
   printf("firmware%d size = %3.1f KB\r\n", target_firmware_section, firmware_size/1024.0);
  }/*local variable*/

  {
   unsigned int firmware_size_le;
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
   firmware_size_le = __bswap_32(firmware_size);
#else
   firmware_size_le = firmware_size;
#endif
   written_len = write(g_client_socket, &firmware_size_le, sizeof(unsigned int));

   if(sizeof(unsigned int) != written_len)
   {
    printf("\r\nsend firmware length error\r\n");
    goto Flag_end_connection;
   }/*if */
  }/*send data length*/

 {
  unsigned int remain_firmware_size;
  FILE *fp;

  remain_firmware_size = firmware_size;

  fp = fopen(pp_firmware_location[target_firmware_section - 1], "rb");

  if(NULL == fp)
  {
   printf("open file %s error\r\n", 
    pp_firmware_location[target_firmware_section - 1]);
   goto Flag_end_connection;
  }/*if */

  while(remain_firmware_size > 0)
  {
#define OTA_PACKET_SIZE       (1280)
   unsigned char data_buffer[OTA_PACKET_SIZE];
   unsigned int sending_size;

   sending_size = fread(&data_buffer[0], 1, sizeof(data_buffer), fp);
   written_len = write(g_client_socket, &data_buffer[0], sending_size);

   if(sending_size != written_len)
   {
    printf("\r\nsend firmware data error\r\n");
    goto Flag_end_connection;
   }/*if*/

   remain_firmware_size -= written_len;

   printf("\rfirmware data has sent %3.1f KB, remain %3.1f KB   ", 
    (firmware_size - remain_firmware_size)/1024.0, remain_firmware_size/1024.0);
   fflush(stdout);

#define PACKET_INTERVAL_IN_MSEC     (400)
   delay_micro_sec(PACKET_INTERVAL_IN_MSEC*1000);
  }/*while*/

  fclose(fp); fp = NULL;
  printf("\r\n");

  is_succ_sent = 1;
 }/*send data */

 printf("firmware %3.1f KB has been sent successfully    \r\n", firmware_size/1024.0);

Flag_end_connection:
 if(0 == is_succ_sent)
  printf("WARNING:: firmware upgrading has been FAIL\r\n");

 close(g_client_socket); g_client_socket = INVALID_SOCKET;
 }/*while*/

 close(g_master_socket);
 return 0;
}/*esp8266_ota_server_start*/


int esp8266_ota_server_end(void)
{
 if( INVALID_SOCKET != g_client_socket)
  close(g_client_socket);
 g_client_socket = INVALID_SOCKET;

 if(INVALID_SOCKET != g_master_socket)
  close(g_master_socket);
 g_master_socket = INVALID_SOCKET;

 return 0;
}/*esp8266_ota_server_end*/


void InterruptHandler(int sig)
{
 printf("\r\n__FUNCTION__ = %s\r\n", __FUNCTION__);
 esp8266_ota_server_end();

 exit(0);
}/*InterruptHandler*/


int main(int argc, char *argv[])
{
 extern char *__progname;
 int k;
 char firmware_location[2][PATH_MAX];
 char *p_firmware_location[2];

 signal(SIGINT, InterruptHandler); 

 printf("\r\n%s\r\n", __progname);

 for(k = 0; k < 2; k++){
  memset(&firmware_location[k][0], 0, PATH_MAX);
  p_firmware_location[k] = NULL;
 }/*for k*/

 k = 1;
 while(k < argc)
 {
  if(0 == strncmp("-fw1", argv[k], strlen("-fw1")) 
   || 0 == strncmp("--user1", argv[k], strlen("-user1")) )
  {
   if(k + 1 < argc)
   {
    strncpy(&firmware_location[0][0], argv[k + 1], PATH_MAX);
    p_firmware_location[0] = &firmware_location[0][0];
   }
   else
   {
    printf("ERROR :: -fw1/--user1 should be followed by firmware location.\r\n");
    return -1;
   }/*if */
  }/*if */

  if(0 == strncmp("-fw2", argv[k], strlen("-fw1")) 
   || 0 == strncmp("--user2", argv[k], strlen("-user1")) )
  {
   if(k + 1 < argc)
   {
    strncpy(&firmware_location[1][0], argv[k + 1], PATH_MAX);
    p_firmware_location[1] = &firmware_location[1][0];
   }
   else
   {
    printf("ERROR :: -fw1/--user2 should be followed by firmware location.\r\n");
    return -1;
   }/*if */
  }/*if */

  k++;
 }/*while*/


 if(NULL == p_firmware_location[0])
 {
  printf("-fw1 should be specified\r\n");
  return -1;
 }/*if non specified fw1 location*/

 if(NULL == p_firmware_location[1])
 {
  printf("-fw2 should be specified\r\n");
  return -1;
 }/*if non specified fw2 location*/


 for(k = 0; k < 2; k++)
 {
  struct stat fw_dir_st = {0};

  if(-1 == stat(p_firmware_location[k], &fw_dir_st))
  {
   printf("ERROR :: %s does not exist!\r\n", p_firmware_location[k]);
   return -1;
  }/*if */

  {
   char firmware_absolute_location[PATH_MAX];
   char *p;

   p = realpath(p_firmware_location[k], &firmware_absolute_location[0]);
   if(NULL == p)
   {
    printf("realpath error :: %s\r\n", strerror(errno));
    return -1;
   }/*if*/

   printf("firmware%d : %s\r\n", k + 1, firmware_absolute_location);
  }
  //printf("firmware%d size = %3.1f KB\r\n", k + 1, fw_dir_st.st_size/1024.0);
  
 }/*local variable*/


 printf("\r\nip address of this server:\r\n");
 {
  struct ifaddrs *ifaddr, *ifa;
  int s;
  char host[NI_MAXHOST];

  if (getifaddrs(&ifaddr) == -1)
  {
   perror("getifaddrs");
   exit(EXIT_FAILURE);
  }

  for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
  {
   if (ifa->ifa_addr == NULL)
    continue;

   s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), 
     &host[0], NI_MAXHOST, NULL, 0, NI_NUMERICHOST);

   if( AF_INET == ifa->ifa_addr->sa_family)
   {
    if (s != 0)
    {
     printf("getnameinfo() failed: %s\n", gai_strerror(s));
     exit(EXIT_FAILURE);
    }
    //printf("\tInterface : <%s>\n",ifa->ifa_name );
    //printf("\t  Address : <%s>\n", host);
    printf("\t<%s> : %s\r\n", ifa->ifa_name, &host[0]);
   }
  }/*for ifa*/

  freeifaddrs(ifaddr);
 }/*local variabes*/
 printf("\r\n");
 esp8266_ota_server_start(&p_firmware_location[0]);

 return 0;
}/*main*/

 

And Build the dfu-ota server :

gcc dfu_ota_server.c -o dfu_ota_server

 

 

三. Modify your working project and call the function int  device_firmware_upgrade_over_the_air(uint8_t *p_server_ip) while it is time for DFU-OTA.

   Build the binary twice,  one for user1 (the common binary for being downloaded to ESP8266 via USB-UART), one for user2. (while the scrip gen_misc.sh has been executed, "STEP 2: choose bin generate" would determine this build is for user1 or user2), Once the user1 has been build, you should clean the whole output, especially the .o files, before building user2.

 

 四. Move the built binaries, user1.1024.new.2.bin and user2.1024.new.2.bin to your OTA server and run the dfu_ota_server commnad:

 

./dfu_ota_server -fw1 user1.1024.new.2.bin -fw2 user2.1024.new.2.bin

 

五. Before you download the user1 binary to ESP8266 via UART (USB),  It is necessary to ERASE the whole flash. In linux it is very easy, 

 

 

sudo python ~/.local/lib/python2.7/site-packages/esptool.py --port /dev/ttyUSB0 erase_flash

 

But if you are in Windows, as my knowing, the flashing tool would not erase the flash thoroughly, instead it only cleans the beginning flag. How to erase the flash in Windows authentically I do not know.

 

 

 

It is all, once it is in DFU-OTA, the server would send the Binary to the ESP8266, then ESP8266 would write the binary to the non-current working zone. If the CRC-checking is passed, ESP8266 would reboot from the other zone which contain the binary just downloaded.

 

 

※ In my case, I assume the flash size of the ESP8266 device is 1MB, if your device size is greater than it, your downloading firmware command may be need to be modified as :

 

sudo python ~/.local/lib/python2.7/site-packages/esptool.py --port /dev/ttyUSB0  write_flash --flash_size=1MB 0x00000 ../ESP8266_RTOS_SDK-1.5.X/bin/boot_v1.7.bin 0x01000 upgrade/user1.1024.new.2.bin  0xFE000 ../ESP8266_RTOS_SDK-1.5.X/bin/blank.bin 0xFC000  esp_init_data_default.bin --flash_mode dout

 

 

The hexadecimal codes are the addresses where the following binaries should be locates. The address of esp_init_data_default.bin is flashing-size depending.

for the common esp8266 modules:

 

    0x7c000 for 512 kB, modules like most ESP-01, -03, -07 etc.

    0xfc000 for 1 MB, modules like ESP8285, PSF-A85, some ESP-01, -03 etc.

    0x1fc000 for 2 MB

    0x3fc000 for 4 MB, modules like ESP-12E, NodeMCU devkit 1.0, WeMos D1 mini

    0x7fc000 for 8 MB

    0xffc000 for 16 MB, modules like WeMos D1 mini pro

 

      The command  --flash_size=1MB  is to compel esptool treating  the esp8266 module acting as 1 MB flash, thus the esp_init_data_default.bin would be written in addrress 0xFC000.

 

    If you would not like the esptool treat your module as 1MB flash only,  you should fill the correct address of  esp_init_data_default.bin. But that might lead my DFU-OTA code non-workable.

 

   Addition : esp_init_data_default.bin is for the configuration of esp8266.In which, it is able to set some configuration which is unable be set via APIs, e.g. configure the ADC function to measure the system voltage. More detail about the configuration, please refer to this document,  section 3.9.

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u013606170/article/details/80205632

智能推荐

Netty作为服务器和普通Java Socket客户端传输数据_zhangphil的博客-程序员ITS203

现在用Netty写一个服务器Server,服务器端绑定本地端口80等待连接,当有客户端Socket连接过来后,就发送字符串“hello,world!”给客户端。客户端连接服务器,连接成功则读取字符串并打印出来,然后关闭socket连接。服务器:package zhangphil.server;import java.util.logging.Level;import java.ut...

java如何设置1.5倍行距_【转】如何解决mathtype公式拉大word中行间距的问题_weixin_39628105的博客-程序员ITS203

Mathtype是个好东西,但使用过程中往往还是存在一些问题,大部分都是因为没有熟练应用mathtype所致。在Word文档中插入公式后,行距便会变得很大,简单的调整段落的行距是行不通的。逐个点选公式,然后拖动下角的箭头倒可以将它任意放大缩小以 调整行距,但是如果在一篇文档中使用了大量的公式,这种操作显然太麻烦,手工操作也容易使得公式大小不一,一些小的公式还会影响到显示的效果。下面介绍两 种调整公...

OCI---SQLT_DAT_dingdang的博客-程序员ITS203

日期DATE对应的OCI类型为SQLT_DAT,可以保存为7Bytes。下面是一个日期类型保存的事例:Example (for 30-NOV-1992, 3:17 PM)----------------------------------------------------------Byte       1       2     3      4     5     6      7-----

目标检测(三)传统目标检测与识别的特征提取——基于HOG特征的目标检测原理_失了志的咸鱼的博客-程序员ITS203_hog目标检测

HOG特征与SVM分类器结合,已经被广泛应用于图像识别中,尤其在行人检测,HOG的核心思想是所检测的局部物体外形能够被光强梯度或边缘方向的分布所描述。通过将整幅图像分割成小的连接区域,称为cells,每个cell生成一个方向梯度直方图或者cell中像素的边缘方向,这些直方图的组合可表示出所检测目标的目标的HOG特征。...

linux 怎么禁止遍历目录,遍历linux目录_weixin_39518840的博客-程序员ITS203

LINUX下历遍目录的方法一般是这样的打开目录-》读取-》关闭目录相关函数是opendir -&gt; readdir -&gt; closedir#include DIR *opendir(const char *dirname);#include struct dirent *readdir(DIR *dirp);#include int closedir(DIR *dirp);opendir...

java 最大线程数 设定_Java8 parallelStream 修改默认的线程数量_少年梁大锤的博客-程序员ITS203

parallelStream默认使用了fork-join框架,其默认线程数是CPU核心数。通过查阅资料,发现有两种方法来修改默认的多线程数量:1.全局设置在运行代码之前,加入如下代码:System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "64");一般不建议修改,因为修改虽然改进当前的业务逻辑,但对于...

随便推点

java unicode中文编码转换和反转_山鬼谣me的博客-程序员ITS203

情形今天在调第三方的接口用于查询IP地址所在地时,其返回的是json字符串,并且返回的中文都是Unicode的编码方式。 如下:{"code":0,"data":{"country":"\u4e2d\u56fd","country_id":"CN","area":"\u534e\u5357","area_id":"800000","region":"\u5e7f\u4e1c\u7701","reg

Vue+ElementUi - Form表单_森!!仔的博客-程序员ITS203

通过Vue+ElementUi实现Form表单一些输入框、复习框、单选框、时间框箭头函数与普通方法的不同this定义位置不同获取不同数据

Thread类(创建Thread类的子类、实现Runnable接口)_Valentino112358的博客-程序员ITS203

/* 创建多线程程序的第一种方式:创建Thread类的子类 java.lang.Thread类:是描述线程的类,我们想要实现多线程程序,就必须继承Thread类 实现步骤: 1.创建一个Thread类的子类 2.在Thread类的子类中重写Thread类中的run方法,设置线程任务(开启线程要做什么?) 3.创建Thread...

接口返回的是一个图片文件而不是url 前端如何显示?_盏茶作酒的博客-程序员ITS203_接口返回图片

请求后端接口 返回的时一张图片 如何在img中显示?preview里查看就是显示一张图片console.log(img):.]用blob createObjectURL转换成地址后前端img还是访问不到的效果结果代码 this._http.doGet(this, 'createQRCode', {id: this.lessonId}, (res) =&gt; { var img = document.createElement('img') ...

springcloud 中 zuul 如何修改请求参数_矿泉的博客-程序员ITS203_zuul替换request参数

一. 为什么要用到这个  在基于 springcloud 构建的微服务系统中,通常使用网关zuul来进行一些用户验证等过滤的操作,比如 用户在 header 或者 url 参数中存放了 token ,网关层需要 用该 token 查出用户 的 userId ,并存放于 request 中,以便后续微服务可以直接使用而避免再去用 token 查询。二.基础知识    在 zuul 中最大...

pomelo分布式聊天服务器_CCbleach的博客-程序员ITS203

为什么是聊天?Pomelo是一款游戏服务器框架, 为什么tutorial会从聊天开始?Pomelo是游戏服务器框架,本质上也是高实时、可扩展、多进程的应用框架。除了在library部分有一部分游戏专用的库,其余部分框架完全可用于开发高实时web应用。而且与现在有的node.js高实时应用框架如derby、socketstream、meteor等比起来有更好的可伸缩性。由于游戏在场景管...