OTA upgrade never finishes

Pato
Posts: 31
Joined: Sat Mar 24, 2018 12:52 am

OTA upgrade never finishes

Postby Pato » Tue Jun 05, 2018 10:42 pm

Hi folks,

I'm trying to implement OTA upgrade with the NON-OS SDK 2.2.0 on the ESP8266, upgrading from a local server.
My application finds the file (I can see in the server log that the HEAD and GET request succeeded) and the ESP seems to erase some sectors.

However, after all sector have been erased, nothing seems to happens, system_upgrade_flag_check() always returns UPGRADE_FLAG_START until the timeout on the upgrade expires (set through struct upgrade_server_info.check_times), even with larges timeout values as 180000 seconds.

The output from the SDK is as follow:

Code: Select all

system_upgrade_start
upgrade_connect 50768
upgrade_connect_cb
pusrdata = HTTP/1.0 200 OK

server do not support HEAD method now send GET message
pusrdata = Server: SimpleHTTP/0.6 Python/2.7.9
Date: Tue, 05 Jun 2018 12:40:31 GMT
Content-type: application/octet-stream
Content-Length: 231316
Last-Modified: Mon, 04 Jun 2018 13:49:22 GMT


sumlength = 231316
sec_block 57
.........................................................upgrade_get_sum_disconcb 46888
erase sector=1 ok
erase sector=2 ok
erase sector=3 ok
(more erase ok...)
erase sector=55 ok
erase sector=56 ok
erase sector=57 ok

ALL=57 sectors erase ok!
upgrade_connect_cb
totallen = 17
totallen = 1477
totallen = 2937
(more totallen...)
totallen = 230697
totallen = 231519

(nothing more is printed)...

upgrade_check_cb  << Called on timeout, here I check the flag indicating the result of the upgrade: it is always false (failed, upgrade_flag == false)



Have you ever encountered this issue, and have some idea ?
What output should I excpect in the console along the whole OTA process ?

My config is:
2nd boot version : 1.7(5d6f877)
SPI Speed : 40MHz
SPI Mode : QIO
SPI Flash Size & Map: 32Mbit(512KB+512KB)
jump to run user2 @ 81000
Compiled with ./gen_misc.sh, selcting the options above.

I would love you !
I'm stuck and have no idea on how to get more debug info...

AgentSmithers
Posts: 119
Joined: Sat Apr 01, 2017 1:21 am
Contact:

Re: OTA upgrade never finishes

Postby AgentSmithers » Wed Jun 06, 2018 2:01 am

Greeting's Pato,
Sorry if this is information you are already aware of. But the code in NONOS that is used for Firmware OTA is all custom. There are API calls to signal the CHIP to boot from a different sector, however, the process of SPIWriting the Data is specific to your code Sir. If you like you may post it here and I can guide you through it, If not we can also coordinate a skype meeting and we can peek at it together.

Pato
Posts: 31
Joined: Sat Mar 24, 2018 12:52 am

Re: OTA upgrade never finishes

Postby Pato » Wed Jun 06, 2018 6:06 pm

Hey AgentSmithers,
Thanks for your interest !

I post below the very same code I use (I made it minimalistic so that it is easier to post). I simply replaced the user_main.c of the NONOS_SDK_2.2.0/examples/IoTDemo project by this one, and I build it with ./gen_misc.sh without any errors, using the procedure describe in Espressif's documentation ("ESP8266 SDKGetting Started Guide"), using the virtual machine and environment provided by Espressif.
I compiled version 1 and 2 of this same application with the options:
SPI Speed : 40MHz
SPI Mode : QIO
SPI Flash Size & Map: 32Mbit(512KB+512KB)

I flashed boot_v1.7.bin first at address 0x00000, then the user1.app (originally named user1.4096.new.4.bin, I gave it a shorter nickname :) ) at 0x01000.

On a local machine (actually a Raspeberry PI) where I put the binaries user1.app and user2.app, I run the very useful and simple Python HTTP server, listenning on port 8070:

Code: Select all

python -m SimpleHTTPServer 8070


And here I'm still wroking on how to get clues...

NB1: A function from the SDK prints "server do not support HEAD method now send GET message". However the SimpleHTTPServer does support HEAD requests: a HEAD request with curl complete successfully with no error, and the logs of the server indicate a successful answer to the ESP... Could the problem be here ?

NB2: You said
The process of SPIWriting the Data is specific to your code

Do you mean I must write "manually" each bytes of the new app to the SPI flash with the SPI functions ? If so, what are the OTA upgrade functions for ? I though they were already supposed to manage it.

NB3: I saw you already spent a large amount of time helping other people on this forum (and sometimes on others websites ;) ), that's very appreciable and kind. Thanks. Really.

-------------------
Here is my code, if you want to give it a try:

Code: Select all

/*
 * FOTA test code: once it's connected to Wifi, it starts the FOTA process:
 * it connects to a local server to retrieve the new bin to flash and upgrades. That's all.
 * Core code based on https://harizanov.com/2015/06/firmware-over-the-air-fota-for-esp8266-soc/
 */

#include "ets_sys.h"
#include "osapi.h"
#include "gpio.h"
#include "os_type.h"
#include "user_interface.h"
#include "mem.h"
#include "upgrade.h"
#include "ip_addr.h"
#include "espconn.h"


uint32 priv_param_start_sec;
char ssid[32] = "MyWifiSSID";
char password[64] = "superpassword";




/**
 * @brief   Was present in IoT_Demo/user/user_main.c on which this code is based...
 */
uint32 ICACHE_FLASH_ATTR user_rf_cal_sector_set(void)
{
    enum flash_size_map size_map = system_get_flash_size_map();
    uint32 rf_cal_sec = 0;

    switch (size_map) {
        case FLASH_SIZE_4M_MAP_256_256:
            rf_cal_sec = 128 - 5;
            priv_param_start_sec = 0x3C;
            break;

        case FLASH_SIZE_8M_MAP_512_512:
            rf_cal_sec = 256 - 5;
            priv_param_start_sec = 0x7C;
            break;

        case FLASH_SIZE_16M_MAP_512_512:
            rf_cal_sec = 512 - 5;
            priv_param_start_sec = 0x7C;
            break;
        case FLASH_SIZE_16M_MAP_1024_1024:
            rf_cal_sec = 512 - 5;
            priv_param_start_sec = 0xFC;
            break;

        case FLASH_SIZE_32M_MAP_512_512:
            rf_cal_sec = 1024 - 5;
            priv_param_start_sec = 0x7C;
            break;
        case FLASH_SIZE_32M_MAP_1024_1024:
            rf_cal_sec = 1024 - 5;
            priv_param_start_sec = 0xFC;
            break;

        case FLASH_SIZE_64M_MAP_1024_1024:
            rf_cal_sec = 2048 - 5;
            priv_param_start_sec = 0xFC;
            break;
        case FLASH_SIZE_128M_MAP_1024_1024:
            rf_cal_sec = 4096 - 5;
            priv_param_start_sec = 0xFC;
            break;
        default:
            rf_cal_sec = 0;
            priv_param_start_sec = 0;
            break;
    }

    return rf_cal_sec;
}



/**
 * @brief   Was present in IoT_Demo/user/user_main.c on wich this code is based...
 */
void ICACHE_FLASH_ATTR user_rf_pre_init(void)
{

}




/**
 * @brief   Callback function called when the upgrade process ended, because of
 *          timeout or upgrade finished ?
 */
static void OtaFinishedCallback(void *arg)
{
    struct upgrade_server_info *update = arg;
   
    if (update->upgrade_flag == true)
    {
        os_printf("[OTA] Success, now rebooting!\n");
        system_upgrade_reboot();
    }
    else
    {
        os_printf("[OTA] Failed!\n");
    }
}
 


/**
 * @brief   Start the OTA upgrade process.
 *
 */
static void HandleUpgrade(const uint8 *server_ip, uint16_t port, const char *path)
{
    const char* file;
    uint8_t userBin = system_upgrade_userbin_check();
   
   
    /* Check wich slot/bin is currently running to determine the new bin to download */
    switch(userBin)
    {
        case UPGRADE_FW_BIN1: file = "user2.app"; break;
        case UPGRADE_FW_BIN2: file = "user1.app"; break;
        default:
            os_printf("[OTA] Invalid userbin number! \n");
            return;
    }
 
 
    /* Set the info about source server and upgrade process properties */
    struct upgrade_server_info* update = (struct upgrade_server_info *)os_zalloc(sizeof(struct upgrade_server_info));
   
    os_memcpy(update->ip, server_ip, 4);   
    update->pespconn = (struct espconn *)os_zalloc(sizeof(struct espconn));
    update->port = port;
    update->check_cb = OtaFinishedCallback;
    update->check_times = 60000;
    update->url = (uint8 *)os_zalloc(512);
     
    os_sprintf((char*)update->url, "GET %s%s HTTP/1.0\r\nHost: "IPSTR":%d\r\nConnection: close\r\n\r\n",
                path, file, IP2STR(update->ip), update->port);
               
    os_printf("[OTA] Server "IPSTR":%d. Path: %s%s\n", IP2STR(update->ip), update->port, path, file);           
    os_printf("Request: %s \n", update->url);
 
 
    /* Debug */
    if (system_upgrade_start(update) == false) os_printf("[OTA] Could not start upgrade\n");
    else os_printf("[OTA] Started upgrading...\n");
}




/**
 * @brief   Callback function called when the wifi connection is fully operational.
 *          Launch the OTA upgrade.
 *
 */
void WifiConnectedCb(System_Event_t *event)
{   
   
    /* Run OTA process only when we are fully connected to WiFi */
    if(event->event == EVENT_STAMODE_GOT_IP)
    {
        os_printf("Connected to Wifi (EVENT_STAMODE_GOT_IP) \n");
        os_printf("Now Testing FOTA... \n");
       
        uint8 serverIp[] = {192, 168, 0, 106};
        uint16 port = 8070;
        char path[] = "pato/espOtaTest/";
   
        HandleUpgrade(serverIp, port, path);
    }   
}



/**
 * @brief   Called when system is fully initialized. Here we do our custom initialization
 *          like connecting to wifi and setting timers.
 */
void PostInitCb()
{
    /* Connect to WiFi */
    os_printf("I'm version 1 ! \n");
    os_printf("Setting up the Esp as a Wifi station... \n");
   
    struct station_config stationConfig;
    os_memcpy(stationConfig.ssid, ssid, 32);
    os_memcpy(stationConfig.password, password, 64);
   
    wifi_set_opmode_current(STATION_MODE);   
    wifi_station_set_config(&stationConfig);   
    wifi_set_event_handler_cb(WifiConnectedCb);
    wifi_station_connect();
    os_printf("Connecting to WiFi... \n");

}



/**
 * @brief   Main entry point of our programm
 */
void user_init()
{
    system_init_done_cb(PostInitCb);   
}

AgentSmithers
Posts: 119
Joined: Sat Apr 01, 2017 1:21 am
Contact:

Re: OTA upgrade never finishes

Postby AgentSmithers » Thu Jun 07, 2018 12:37 pm

NB1: A function from the SDK prints "server do not support HEAD method now send GET message". However the SimpleHTTPServer does support HEAD requests: a HEAD request with curl complete successfully with no error, and the logs of the server indicate a successful answer to the ESP... Could the problem be here ?
I think it's best we do a Skype meeting to look together. Hard to say because we don't use the same environment, I'm GMT-8 (USA PST)

NB2: You said
The process of SPIWriting the Data is specific to your code

Do you mean I must write "manually" each bytes of the new app to the SPI flash with the SPI functions? If so, what are the OTA upgrade functions for? I thought they were already supposed to manage it.

From my complete (And working) understanding yes, If your using some sort of cloud API I've never used that but I'm not an expert yet. The two Star's of the show I've seen are "Her Majesty" and "Pratik", they are a bit more polished then I am with NONOS. Take a look at the code sample below and note the SPI_FLASH_WRITE, You are correct, As it pulls via HTTP or w.e custom protocol you built you can take that and SPI write it, then you call the API's to set the FOTA flags and reboot. You write to the SPI offset your chip did not load from (Writing to your code while running it will crash your chip during runtime). I hope that makes sense.

NB3: I saw you already spent a large amount of time helping other people on this forum (and sometimes on others websites ;) ), that's very appreciable and kind. Thanks. Really.
Yea, I'm just your friendly neighborhood forum Spiderman... It's either this or back to basket weaving so I tend to try to keep my critical thinking sharp. :D

Code: Select all

/*
 * \brief: otaHandleUpload handles a POST to update the firmware
 *
 * Returns the number of bytes consumed from the request, -1 if a response has been sent.
 */
LOCAL int16_t ICACHE_FLASH_ATTR otaHandleUpload(OtaConn *oc) {
  uint32_t offset = oc->rxBufOff;

  // assume no error yet...
  char *err = NULL;
  uint16_t code = 400;

  // check overall size
  if (oc->reqLen > flashMaxSize[flashSizeMap]) {
    os_printf("OTA: FW too large: %ld > %ld\n",
      (long int) oc->reqLen,
      (long int)  flashMaxSize[flashSizeMap]);
    err = "Firmware image too large";
  } else if (oc->reqLen < OTA_CHUNK_SZ) {
    os_printf("OTA: FW too small: %ld\n", (long int) oc->reqLen);
    err = "Firmware too small";
  }

  // check that we have at least OTA_CHUNK_SZ bytes buffered or it's the last chunk, else we can't write
  if (oc->rxBufFill < OTA_CHUNK_SZ && offset+OTA_CHUNK_SZ <= oc->reqLen) return 0;
  uint16_t toFlash = OTA_CHUNK_SZ;
  if (oc->rxBufFill < toFlash) toFlash = oc->rxBufFill;

  // let's see which partition we need to flash
  uint8 id = system_upgrade_userbin_check();

  // check that data starts with an appropriate header
  if (err == NULL && offset == 0) err = check_header(oc->rxBuffer+oc->rxBufOff, 1-id);

  // return an error if there is one
  if (err != NULL) {
    os_printf("OTA Error %d: %s\n", code, err);
    sendResponse(oc, code, err);
    return -1;
  }

  // let's see which what flash address we're uploading to
  uint32_t address = id ? 0x1000 : flashUser2Addr[flashSizeMap];
  address += offset;

  // erase next flash block if necessary
  if (address % SPI_FLASH_SEC_SIZE == 0){
          os_printf("OTA Flashing 0x%05lx\n", (long unsigned int) address);
          spi_flash_erase_sector(address/SPI_FLASH_SEC_SIZE);
  }

  // write the data
  //os_printf("Writing %d bytes at 0x%05x (%d of %d)\n", connData->post->buffSize, address,
  //      connData->post->received, connData->post->len);
  spi_flash_write(address, (uint32 *)oc->rxBuffer, toFlash); <======= THIS HERE PATO!!!!!!

  if (offset + toFlash == oc->reqLen) {
    sendResponse(oc, 200, "");
    return -1;
  }
  return toFlash;
}

Pato
Posts: 31
Joined: Sat Mar 24, 2018 12:52 am

Re: OTA upgrade never finishes

Postby Pato » Sun Jun 17, 2018 6:17 pm

Hey !

As I could not find out why the OTA library does not work with my environment, I ended up rewritting my own OTA upgrade library, according to what AgentSmither said and like many other pieces of codes on the net do:

    - Send a HTTP GET request to my local server to download the file
    - Use system_upgrade_set_flag() to manage the upgrade state manually
    - In a TCP receive callback function, flash the bytes as they arrive with spi_flash_write() function
    - Reboot with system_upgrade_reboot()

I took inspiration from the OTA code of rboot (https://github.com/raburton/rboot-sample), replacing the rboot functions by the ones from the Espressif's SDK. I could perform OTA upgrade this way, and it offers a way to do custom checks of the integrity of the file, etc
So if you want a robust and reliable OTA mechanism, that are the basic steps :)

Thanks for your interest :)

AgentSmithers
Posts: 119
Joined: Sat Apr 01, 2017 1:21 am
Contact:

Re: OTA upgrade never finishes

Postby AgentSmithers » Mon Jun 18, 2018 11:16 pm

Pato wrote:Hey !

As I could not find out why the OTA library does not work with my environment, I ended up rewritting my own OTA upgrade library, according to what AgentSmither said and like many other pieces of codes on the net do:

    - Send a HTTP GET request to my local server to download the file
    - Use system_upgrade_set_flag() to manage the upgrade state manually
    - In a TCP receive callback function, flash the bytes as they arrive with spi_flash_write() function
    - Reboot with system_upgrade_reboot()

I took inspiration from the OTA code of rboot (https://github.com/raburton/rboot-sample), replacing the rboot functions by the ones from the Espressif's SDK. I could perform OTA upgrade this way, and it offers a way to do custom checks of the integrity of the file, etc
So if you want a robust and reliable OTA mechanism, that are the basic steps :)

Thanks for your interest :)


Glad to hear, mind sharing your writings here for the other poor OTA people on this forum :), I see post about this constantly however very few live solutions :)

Pato
Posts: 31
Joined: Sat Mar 24, 2018 12:52 am

Re: OTA upgrade never finishes

Postby Pato » Fri Jun 22, 2018 5:38 pm

Hey !

I merely replaced the code in the tcp_recv_cb() by my custom code to use the SPI flash function from Espressif instead of the one of rboot (https://github.com/raburton/rboot-sample).
It still need to be cleaned up as it was brute test-and-dev, but the basis is here:

Code: Select all


typedef struct {
   uint8 rom_slot;           // rom slot to update, or FLASH_BY_ADDR
   ota_callback callback;  // user callback when completed
   uint32 total_len;
   uint32 content_len;
   struct espconn *conn;
   ip_addr_t ip;
   //rboot_write_status write_status;
} upgrade_status;


#define OTA_CHUNK_SIZE  512     /**< Chunk size of the raw data we handle and flash (aka size of our working buffer) */

static upgrade_status *upgrade;
static char buffer_g_u8[OTA_CHUNK_SIZE];   /* Working buffer */
static uint16 pos_g_u16 = 0;                /* Current position in the working buffer [bytes]*/


// called when connection receives data (hopefully the rom)
static void ICACHE_FLASH_ATTR upgrade_recvcb(void *arg, char *pusrdata, uint16 length)
{
   os_timer_disarm(&ota_timer);        // MANAGE TIMER TO EXIT IN CASE OF FAILURE
   
   // We treat the data by chunk of 512 bytes, as we can only writes data at addresses
   // and with length that are multiples of 512 bytes. << Wrong, just need to be a multiple of 4 bytes !!
    static uint32 address_u32 = 0x01000;
    static uint32 progress_u32 = 0; //Nb o bytes of data flashed
   uint16 nbToCopy_u16 = 0;
   uint16 nbConsumed_u16 = 0 ;
   
   while(length > nbConsumed_u16)
   {
   
       // Copy as many bytes in the working buffer as we can (until buffer is full or
       // there is no more bytes received via TCP)
       nbToCopy_u16 = (uint16) Min(length - nbConsumed_u16, OTA_CHUNK_SIZE - pos_g_u16);
             
             
       os_memcpy(buffer_g_u8 + pos_g_u16, pusrdata + nbConsumed_u16, nbToCopy_u16);
       pos_g_u16 = (uint16) (pos_g_u16 + nbToCopy_u16);                // Roll back to zero if we reached the end of the buffer      
       nbConsumed_u16 = (uint16) (nbConsumed_u16 + nbToCopy_u16);
      
      
       if(pos_g_u16 == OTA_CHUNK_SIZE)      // The position cursor is out of the buffer's bound, meaning we filled the buffer
       {
           pos_g_u16 = 0;
           if(upgrade->content_len == 0)    // We haven't parsed the header yet. Assumes all the info we need is in the first 512 bytes of the header (header is generally shorter)
           {
               // Get content length fromthe header Content-Length
               char *ptrContentLen_pc;
               ptrContentLen_pc = os_strstr(buffer_g_u8, "Content-Length: ");
               if(ptrContentLen_pc != NULL)
               {
                   upgrade->content_len = (uint32) atoi(ptrContentLen_pc + 16);             // USE STRTOUL to handle errors ?
                   os_printf("Total size = %d \n", upgrade->content_len);
               }
              
               // Find the start of the content payload, here the bytes of the new software
               // to flash.
               // To flash by block of 512 bytes, we then need to move the payload received
               // to the start of the buffer (that were occupied before by the headers).
               char *ptrDataStart_pc;
               uint16 dataPos_u16;
               uint16 dataLen_u16;
              
               ptrDataStart_pc = os_strstr(buffer_g_u8, "\r\n\r\n");
               if(ptrDataStart_pc != NULL)
               {
                   ptrDataStart_pc += 4;                           // Skip the "\r\n\r\n" sequence
                   dataPos_u16 = (uint16) (ptrDataStart_pc - buffer_g_u8);    // Index of the first byte of data in the bufer
                   dataLen_u16 = (uint16) (OTA_CHUNK_SIZE - dataPos_u16);     // Nb of byte of the payload in this chunk
                   os_printf("Start of data found, %d bytes remainings \n", dataLen_u16);
                  
                   os_memmove(&buffer_g_u8[0], &buffer_g_u8[dataPos_u16], dataLen_u16);    // Use memmove instead of memcpy to hanle overlaps
                   pos_g_u16 = dataLen_u16;                                            // Positionate the curor righ aftert the data   
                   os_printf("Moved bytes \n");
               }
              
              
              
                              
           }
           else
           {
               // Our buffer is full and only contains bytes of the payload, it's time to flash !
               progress_u32 += OTA_CHUNK_SIZE;
               SpiFlashOpResult res;
              
               // Erase next flash sector (requiered according to the doc)
               if(address_u32 % SPI_FLASH_SEC_SIZE == 0)
               {
                   os_printf("Erasing next sector \n");
                   spi_flash_erase_sector((uint16)(address_u32/SPI_FLASH_SEC_SIZE));   
               }

               os_printf("Flashing at address 0x%06X, consummed %d/%d \n", address_u32, progress_u32, upgrade->content_len);              
               res = spi_flash_write(address_u32, (uint32*)buffer_g_u8, OTA_CHUNK_SIZE);
               address_u32 += OTA_CHUNK_SIZE;
              
               //if(res == SPI_FLASH_RESULT_OK) os_printf("OK\n");
               if(res == SPI_FLASH_RESULT_ERR) os_printf("ERR\n");
               if(res == SPI_FLASH_RESULT_TIMEOUT) os_printf("TIMEOUT\n");
                      
              
           }
          
        
      
      
       }
       else
       {
           // The bufer is not full, because it's the last chunk or an incomplete one.
           // If it's the last, we flash the remaning bytes
           uint32 remaining_u32 = upgrade->content_len - progress_u32;
          
           if((progress_u32 > 0) && (remaining_u32 < OTA_CHUNK_SIZE))
           {
                              // Erase next flash sector (requiered according to the doc)
               if(address_u32 % SPI_FLASH_SEC_SIZE == 0)
               {
                   os_printf("Erasing next sector \n");
                   spi_flash_erase_sector((uint16)(address_u32/SPI_FLASH_SEC_SIZE));   
               }
          
               progress_u32 += remaining_u32;
               spi_flash_write(address_u32, (uint32*)buffer_g_u8, OTA_CHUNK_SIZE);       
               os_printf("Flashing at address 0x%06X, consummed %d/%d \n", address_u32, progress_u32, upgrade->content_len);
              
               // Finalize
               system_upgrade_flag_set(UPGRADE_FLAG_FINISH);
               ota_deinit();
           }
       }
      
      
   
   }
      
   

}
Last edited by Pato on Tue Jun 26, 2018 3:40 pm, edited 2 times in total.

AgentSmithers
Posts: 119
Joined: Sat Apr 01, 2017 1:21 am
Contact:

Re: OTA upgrade never finishes

Postby AgentSmithers » Tue Jun 26, 2018 10:16 am

Thanks for the Feedback Pato.
https://bbs.espressif.com/viewtopic.php?f=7&t=10359 Maybe this is something you may be able to Chime in on.

My question to you is if you do an HTTP GET for a .BIN file your going to get an HTTP Header back before the binary data. I took a look at the function code you provided but didn't see how it handled that part of the hand shake.

*Reviewing more* I see
if(upgrade->content_len == 0) I guess at this point it may try to determine the HTTP Header then part it from there am I correct?
Any Additional code you think I'll need or can I run a copy and paste test after crafting an HTTP GET to the .BIN file?

Definition error: 'upgrade' undeclared (first use in this function) <=== What kind of Structure is this?
if(upgrade->content_len == 0)

Thanks Pato!

Pato
Posts: 31
Joined: Sat Mar 24, 2018 12:52 am

Re: OTA upgrade never finishes

Postby Pato » Tue Jun 26, 2018 3:37 pm

Hey,

In this raw brute ugly test code, indeed I receive a HTTP header before the data but I don't bother parsing it. I just store the bytes as they arrive in buffer_g_u8[] until I have 512 bytes. Then I assume that in this 512 bytes there is the full header and the start of the data payload (my .bin). I just look for the string "Content-Length: " to know how many bytes I must expect and I store this value in upgrade->content_len (when non-null it means I got and parsed the header).
Then I just look for "\r\n\r\n" that indicates the start of the data, that's all... I don't manually send any reply back to the server.

" 'upgrade' undeclared (first use in this function) <=== What kind of Structure is this?"
Sorry, this is the struct defined at the top of rboot-ota.c by rburton to track the progress of the OTA in its initial code. I edited my previous post to add it (as said, it was dev code, I did not clean it up yet)

I started to craft directly in rboot-ota.c

John Liu
Posts: 4
Joined: Fri Jun 29, 2018 2:41 pm

Re: OTA upgrade never finishes

Postby John Liu » Wed Jul 18, 2018 10:33 am

这问题出在tools目录下的gen_appbin.py脚本,fix如下:

1> 对\tools\gen_appbin.py脚本单独进行测试,发现问题出在函数gen_appbin()的最后对all_bin_crc的判断上:
if boot_mode == '1' or boot_mode == '2':
all_bin_crc = getFileCRC(flash_bin_name)
if all_bin_crc < 0:
all_bin_crc = abs(all_bin_crc) - 1
else :
all_bin_crc = abs(all_bin_crc) + 1
print "bin crc: %x"%all_bin_crc
如果all_bin_crc < 0,那么计算出的CRC就是正确的,否则错误。这就是为何有时候CRC相等,有时候不等的原因。

2> 修改上述代码为如下,CRC问题解决。

if boot_mode == '1' or boot_mode == '2':
all_bin_crc = getFileCRC(flash_bin_name)
all_bin_crc = ~all_bin_crc

Who is online

Users browsing this forum: No registered users and 12 guests