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.

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.

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 : 40MHzSPI Mode : QIOSPI 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:

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.

/* * 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/ */

/** * @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");

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 saidThe 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.

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, etcSo if you want a robust and reliable OTA mechanism, that are the basic steps

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, etcSo 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

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:

// 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);

// 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;

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)

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)

Documentation

About Us

Espressif Systems is a fabless semiconductor company providing cutting-edge low power WiFi SoCs and wireless solutions for wireless communications and Internet of Things applications. We are the manufacturer of ESP8266EX.