User Tools

Site Tools


esp32_ota

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
esp32_ota [2024/03/13 12:24]
sausage
esp32_ota [2024/03/20 01:50] (current)
sausage [ESP32 OTA and Rollbacks - What happens under the hood?]
Line 5: Line 5:
 Over The Air (OTA) provides a way to send firmware to your ESP32 board in the field without the need for a cable and physical access to the device. Over The Air (OTA) provides a way to send firmware to your ESP32 board in the field without the need for a cable and physical access to the device.
  
-The purpose of this article is manually step through the various stages of the OTA process and illustrate the state of the ESP32 at each stage. ​+The purpose of this article is to manually step through the various stages of the OTA process and illustrate the state of the ESP32 at each stage. ​
  
 Together we will set up a number of firmwares suitable for testing on different partitions in flash memory. Together we will set up a number of firmwares suitable for testing on different partitions in flash memory.
Line 22: Line 22:
 https://​docs.espressif.com/​projects/​esp-idf/​en/​latest/​esp32/​api-reference/​system/​ota.html#​rollback-process https://​docs.espressif.com/​projects/​esp-idf/​en/​latest/​esp32/​api-reference/​system/​ota.html#​rollback-process
  
-This article is based on esp-idf-v5.1.1-2.+This article is based on esp-idf-v5.2.
  
 ===== The stock firmware ===== ===== The stock firmware =====
Line 35: Line 35:
  
   gen_esp32part.py .\partitions.log > .\partitions.csv   gen_esp32part.py .\partitions.log > .\partitions.csv
 +  ​
 +<WRAP center round important 90%>
 +If you don't have gen_esp32part.py,​ please check the troubleshooter below.
 +</​WRAP>​
  
 Open the CSV, and it will probably look something like this (if anything at all): Open the CSV, and it will probably look something like this (if anything at all):
Line 46: Line 50:
 </​code>​ </​code>​
  
-Ignoring the ''​nvs''​ and ''​phy_init''​ partitions, we have the default ''​factory''​ partition that starts at 0x10000. Ironically, the list of partitions doesn'​t list the bootloader partition at 0x1000 or the partition that the partition table itself is stored ​on (at 0x8000). ​+Ignoring the ''​nvs''​ and ''​phy_init''​ partitions, we have the default ''​factory''​ partition that starts at 0x10000. Ironically, the list of partitions doesn'​t list the bootloader partition at 0x1000 or the partition that the partition table itself is stored (at 0x8000). ​
  
 ===== OTA partitions ===== ===== OTA partitions =====
Line 212: Line 216:
   - 4blinks.bin   - 4blinks.bin
  
-Now the ''​idf.py flash''​ command is only able to flash the default project firmware to the ''​factory''​ partition. So we'll need to switch to a different command to flash a named firmware to a particular partition.+Note that the ''​idf.py flash''​ command is only able to flash the default project firmware to the ''​factory''​ partition. So we'll need to switch to a different command to flash a named firmware to a particular partition.
  
 Take another look at our partitions table. Take another look at our partitions table.
Line 280: Line 284:
 This reads out the ''​otadata''​ partition, which starts at 0xd000 and is 0x2000 in length out to a file. This reads out the ''​otadata''​ partition, which starts at 0xd000 and is 0x2000 in length out to a file.
  
-If you open the ''​otadata-partition.bin''​ file in a hex reader (I recommend ​HxD - https://​mh-nexus.de/​en/​hxd/​),​ you'll see that the entire file is filled with 0xFF bytes.+If you open the ''​otadata-partition.bin''​ file in a hex reader (I recommend ​[[https://​mh-nexus.de/​en/​hxd/​|HxD]]), you'll see that the entire file is filled with 0xFF bytes.
  
 We can use a tool to set ''​ota_0''​s firmware as the one we want to boot from: We can use a tool to set ''​ota_0''​s firmware as the one we want to boot from:
Line 354: Line 358:
  
 In our case, the second sector has a new entry, the ''​02''​ sequence. This is for the firmware on ''​ota_1''​. ''​02''​ is greater than ''​01''​ so this is the firmware selected for boot by the bootloader. In our case, the second sector has a new entry, the ''​02''​ sequence. This is for the firmware on ''​ota_1''​. ''​02''​ is greater than ''​01''​ so this is the firmware selected for boot by the bootloader.
 +
 +How an OTA partition is determined from sequence numbers in the otadata partition is not explained in the documentation,​ but is explained in the code. You can see it here: https://​github.com/​pycom/​esp-idf-2.0/​blob/​master/​components/​app_update/​esp_ota_ops.c#​L297
 +
 +Essentially,​ for two partitions all odd sequence numbers are ''​ota_0''​ and even numbers are ''​ota_1''​. The formula is:
 +
 +  (ota_seq - 1) % number_of_ota_partitions
  
 Revise on the ''​otadata''​ partition here:  Revise on the ''​otadata''​ partition here: 
Line 460: Line 470:
 All our firmwares failed to run the ''​esp_ota_mark_app_valid_cancel_rollback()''​ to mark the ''​otadata''​ as valid. So in each case, they have become aborted and rolled back to the previously known good firmware. All our firmwares failed to run the ''​esp_ota_mark_app_valid_cancel_rollback()''​ to mark the ''​otadata''​ as valid. So in each case, they have become aborted and rolled back to the previously known good firmware.
  
-The ''​factory''​ firmware isn'​t ​controlled ​by the ''​otadata'',​ the rollback process or OTA at all.+The ''​factory''​ firmware isn'​t ​affected ​by ''​otadata'', ​or the rollback processor OTA at all.
  
 To finish up, let's take a last look at the raw otadata: To finish up, let's take a last look at the raw otadata:
Line 486: Line 496:
 Have fun! Have fun!
  
 +
 +===== Troubleshooting =====
 +//The gen_esp32part.py command isn't found.//
 +
 +For some reason, gen_esp32part.py is not added to your path by default when starting your ESP-IDF console. For Powershell add the following to line 59 of your ''​frameworks\esp-idf-v5.2\export.ps1''​ file:
 +
 +  function gen_esp32part.py { &python "​$IDF_PATH\components\partition_table\gen_esp32part.py"​ $args }
 +
 +For Windows Command Prompt, in ''​frameworks\esp-idf-v5.2\export.bat''​ add to line 66:
 +
 +  DOSKEY gen_esp32part.py=python.exe "​%IDF_PATH%\components\partition_table\gen_esp32part.py"​ $*
 +
 +For shell and fish terminals, it's the same deal.
  
 ===== More reading ===== ===== More reading =====
   - https://​blog.espressif.com/​ota-updates-framework-ab5438e30c12   - https://​blog.espressif.com/​ota-updates-framework-ab5438e30c12
   - https://​esp32.com/​viewtopic.php?​t=14939   - https://​esp32.com/​viewtopic.php?​t=14939
 +
 +===== Thank yous =====
 +Many thanks to boarchuz and craig from the [[https://​discord.gg/​wwK29JJV|Espressif MCUs]] discord server for their assistance with this article.
  
esp32_ota.1710332657.txt.gz ยท Last modified: 2024/03/13 12:24 by sausage