ESP32-S3 OTA Update from USB PenDrive resets during esp_ota_end()

lipun12ka4
Posts: 5
Joined: Tue Dec 06, 2022 12:55 pm

ESP32-S3 OTA Update from USB PenDrive resets during esp_ota_end()

Postby lipun12ka4 » Tue Dec 06, 2022 1:03 pm

<r>I am trying to Make OTA Updates work from a USB PenDrive with ESP32S3. Everything works untill I call the esp_ota_end() function. That causes a TG1WDT_SYS_RST Reset. <br/>
The Example (HTTPS OTA Update) over WiFi Works, but I require the USB Based OTA Function to Work.<br/>
I will hugely appreciate any help/pointers in this regard.<br/>
  1. #include "Common_Variables.h"
  2. #include "stdbool.h"
  3. #include "esp_ota_ops.h"        //included header file for esp_ota driver
  4.  
  5. #define OTA_MAX_BYTES_PER_BATCH 4096
  6.  
  7. uint8_t buf[OTA_MAX_BYTES_PER_BATCH+1];
  8.  
  9. static char* TAG = "OTA";
  10.  
  11. static uint32_t total = 0;
  12. static uint32_t pct = 0;
  13. static uint32_t pct_send = 0;
  14. static char message_data[10];
  15.  
  16. //static esp_err_t err;//Error variable to indicate when calling function return error.It is used in NVS function (WRITE,READ SERIAL number from NVS)
  17. static esp_ota_handle_t update_handle = 0;  //should be used for subsequent esp_ota_write() and esp_ota_end() calls
  18. //const esp_partition_t *update_partition = NULL; //Pointer to info for partition which should be updated next.
  19. //NULL result indicates invalid OTA data partition, or that no eligible OTA app slot partition was found
  20.  
  21.  
  22. //Function is used to implement OTA function
  23. static void ota_func_task(void *pvParameter){
  24. //esp_err_t ota_func_task(void) {
  25.     FILE *ota_bin_file;
  26.     int finished = 0;
  27.  
  28.  
  29.     struct stat entry_stat;
  30.     uint32_t file_size_number = 0;
  31.     char file_size[16];
  32.  
  33.     char ota_bin_file_path[50] = "/usb/OTA/VCI_AL.bin";
  34.  
  35.         printf("OTA Bin File Path = %s \n", ota_bin_file_path);
  36.  
  37.         ota_bin_file = fopen (ota_bin_file_path, "rb" );
  38.  
  39.         if (ota_bin_file == NULL) {
  40.             printf("Failed to open file for reading \n");
  41.             vTaskDelete(NULL);
  42.         }else{
  43.             printf("Opened OTA BIN file for reading \n");
  44.             //stat();
  45.             if (stat(ota_bin_file_path, &entry_stat) == -1) {
  46.                     printf("Failed to stat %s \n", ota_bin_file_path);
  47.                     //return ESP_FAIL;
  48.                     vTaskDelete(NULL);
  49.                 }
  50.                 file_size_number = (uint32_t) entry_stat.st_size;
  51.                 printf("File Size is %d \n", file_size_number);
  52.  
  53.                 sprintf(file_size, "%ld", entry_stat.st_size);
  54.                 printf("Found %s : (%s bytes) \n", ota_bin_file_path, file_size);
  55.         }
  56.  
  57.         printf("starting main task firmware update \n");
  58.  
  59.         vTaskDelay(500 / portTICK_PERIOD_MS);
  60.  
  61.         const esp_partition_t *configured = esp_ota_get_boot_partition();
  62.         const esp_partition_t *running = esp_ota_get_running_partition();
  63.  
  64.         if (configured != running) {
  65.             printf("Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x \n",configured->address, running->address);
  66.             printf("This can happen if either the OTA boot data or preferred boot image become corrupted somehow.\n");
  67.         }
  68.  
  69.         printf("Running partition type %d sub-type %d (offset 0x%08x) \n",running->type, running->subtype, running->address);
  70.  
  71.         const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL);
  72.         assert(update_partition != NULL);
  73.  
  74.         printf("Writing to partition subtype %d at offset 0x%x \n", update_partition->subtype, update_partition->address);
  75.  
  76.         //esp_err_t err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
  77.  
  78.         esp_err_t err = esp_ota_begin(update_partition, file_size_number, &update_handle);
  79.  
  80.         ESP_LOGI(TAG, "esp_begin result = %d", err);
  81.         printf("Update Handle is %d \n", update_handle);
  82.  
  83.         if (err != ESP_OK) {
  84.             printf("esp_ota_begin failed, error=%d \n", err);
  85.             printf("esp_ota_begin failed\n");
  86.             vTaskDelete(NULL);
  87.         }
  88.  
  89.         printf("esp_ota_begin succeeded \n-----------------------\n");
  90.                     while(!finished)
  91.                     {
  92.                             unsigned int retn = fread(buf, 1, OTA_MAX_BYTES_PER_BATCH, ota_bin_file);
  93.                             printf("First Byte of the Read Data Chunk is %X \n", buf[0]);
  94.  
  95.                             if(retn != OTA_MAX_BYTES_PER_BATCH)
  96.                             {
  97.                                 printf("Finished reading, Last Chunk size %d \n",retn);
  98.  
  99.                                 err = esp_ota_write(update_handle, buf, retn);
  100.  
  101.                                 if (err == ESP_ERR_INVALID_ARG) {
  102.                                     printf("error: esp_ota_write failed! err=0x%x\n", err);
  103.                                     vTaskDelete(NULL);
  104.                                 } else if (err == ESP_ERR_OTA_VALIDATE_FAILED) {
  105.                                     printf("error: First byte of image contains invalid app image magic byte\n");
  106.                                 } else if (err == ESP_ERR_FLASH_OP_FAIL) {
  107.                                     printf("error: Flash write IO Operaion failed\n");
  108.                                 } else if (err == ESP_ERR_FLASH_OP_TIMEOUT) {
  109.                                     printf("error: Flash write failed due to TimeOut\n");
  110.                                 } else if (err == ESP_ERR_OTA_SELECT_INFO_INVALID) {
  111.                                     printf("error: OTA data partition has invalid contents\n");
  112.                                 } else if (err == ESP_OK) {
  113.                                     printf("Wrote %d Bytes to OTA Partition \n", retn);
  114.                                 }
  115.  
  116.                                 ESP_LOGI(TAG, "Ota result = %d", err);
  117.  
  118.                                 total += retn;
  119.                                 pct = total * 100 / file_size_number;
  120.  
  121.                                 itoa(pct, message_data, 10);
  122.                                 printf("Progress %s %% \n", message_data);
  123.                                 printf("Total Bytes Read from the OTA BIN File is %d \n", total);
  124.  
  125.                                 //vTaskDelay(5000/portTICK_PERIOD_MS);
  126.                                 printf("Update Handle is %d \n", update_handle);
  127.                                 err = esp_ota_end(update_handle);
  128.  
  129.                                 if (err != ESP_OK) {
  130.                                     if (err == ESP_ERR_OTA_VALIDATE_FAILED) {
  131.                                         ESP_LOGE(TAG, "Image validation failed, image is corrupted");
  132.                                     } else {
  133.                                         ESP_LOGE(TAG, "esp_ota_end failed (%s)!", esp_err_to_name(err));
  134.                                     }
  135.                                     vTaskDelete(NULL);
  136.                                 }
  137.  
  138.                                 //vTaskDelay(5000/portTICK_PERIOD_MS);
  139.                                 printf("OTA Update has Ended \n");
  140.                                 err = esp_ota_set_boot_partition(update_partition);
  141.                                 if (err != ESP_OK) {
  142.                                     ESP_LOGE(TAG, "esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(err));
  143.                                 }
  144.  
  145.                                 vTaskDelay(5000/portTICK_PERIOD_MS);
  146.                                 ESP_LOGI(TAG, "Prepare to restart system!");
  147.                                 finished = 1;
  148.                                 break;
  149.                             }
  150.                             else
  151.                             {
  152.  
  153.                                 //gpio_set_level(WiFi_LED, toggle);
  154.                                 //toggle = !toggle;
  155.  
  156.                                 err = esp_ota_write(update_handle, buf, retn);
  157.  
  158.                                 if (err == ESP_ERR_INVALID_ARG) {
  159.                                     printf("error: esp_ota_write failed! err=0x%x\n", err);
  160.                                     vTaskDelete(NULL);
  161.                                 } else if (err == ESP_ERR_OTA_VALIDATE_FAILED) {
  162.                                     printf("error: First byte of image contains invalid app image magic byte\n");
  163.                                 } else if (err == ESP_ERR_FLASH_OP_FAIL) {
  164.                                     printf("error: Flash write IO Operaion failed\n");
  165.                                 } else if (err == ESP_ERR_FLASH_OP_TIMEOUT) {
  166.                                     printf("error: Flash write failed due to TimeOut\n");
  167.                                 } else if (err == ESP_ERR_OTA_SELECT_INFO_INVALID) {
  168.                                     printf("error: OTA data partition has invalid contents\n");
  169.                                 } else if (err == ESP_OK) {
  170.                                     printf("Wrote %d Bytes to OTA Partition \n", retn);
  171.                                 }
  172.  
  173.                                 total += OTA_MAX_BYTES_PER_BATCH;
  174.  
  175.                                 pct = total * 100 / file_size_number; //calculated percentage
  176.  
  177.                                 if(pct != pct_send ) //i.e. if the rounded off percentage is updated
  178.                                 {
  179.                                     pct_send = pct;
  180.                                     itoa(pct, message_data, 10);
  181.                                     printf("Progress %s %% \n", message_data);
  182.                                 }
  183.                             }
  184.                     }//Reading of data from PenDrive complete
  185.     //return ESP_OK;
  186.     vTaskDelete(NULL);
  187. }   //end of OTA function
  188.  
  189.  
  190. esp_err_t ota_func(){
  191.     xTaskCreate(&ota_func_task, "ota_func_task", 8192, NULL, 5, NULL);
  192.     return ESP_OK;
  193. }
  1. 18:21:51.636 -> ESP-ROM:esp32s3-20210327
  2. 18:21:51.636 -> Build:Mar 27 2021
  3. 18:21:51.636 -> rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT)
  4. 18:21:51.636 -> SPIWP:0xee
  5. 18:21:51.636 -> mode:DIO, clock div:1
  6. 18:21:51.636 -> load:0x3fce3808,len:0x1744
  7. 18:21:51.636 -> load:0x403c9700,len:0xc00
  8. 18:21:51.636 -> load:0x403cc700,len:0x3218
  9. 18:21:51.636 -> entry 0x403c9968
  10. 18:21:51.636 -> [0;32mI (24) boot: ESP-IDF v4.4.3-dirty 2nd stage bootloader[0m
  11. 18:21:51.636 -> [0;32mI (25) boot: compile time 17:13:57[0m
  12. 18:21:51.636 -> [0;32mI (25) boot: chip revision: 0[0m
  13. 18:21:51.636 -> [0;32mI (27) boot.esp32s3: Boot SPI Speed : 80MHz[0m
  14. 18:21:51.636 -> [0;32mI (32) boot.esp32s3: SPI Mode       : DIO[0m
  15. 18:21:51.636 -> [0;32mI (36) boot.esp32s3: SPI Flash Size : 16MB[0m
  16. 18:21:51.636 -> [0;32mI (41) boot: Enabling RNG early entropy source...[0m
  17. 18:21:51.636 -> [0;32mI (47) boot: Partition Table:[0m
  18. 18:21:51.636 -> [0;32mI (50) boot: ## Label            Usage          Type ST Offset   Length[0m
  19. 18:21:51.636 -> [0;32mI (57) boot:  0 nvs              WiFi data        01 02 00009000 00004000[0m
  20. 18:21:51.636 -> [0;32mI (65) boot:  1 otadata          OTA data         01 00 0000d000 00002000[0m
  21. 18:21:51.636 -> [0;32mI (72) boot:  2 phy_init         RF data          01 01 0000f000 00001000[0m
  22. 18:21:51.636 -> [0;32mI (80) boot:  3 factory          factory app      00 00 00010000 00200000[0m
  23. 18:21:51.636 -> [0;32mI (87) boot:  4 ota_0            OTA app          00 10 00210000 00200000[0m
  24. 18:21:51.636 -> [0;32mI (95) boot:  5 ota_1            OTA app          00 11 00410000 00200000[0m
  25. 18:21:51.636 -> [0;32mI (102) boot: End of partition table[0m
  26. 18:21:51.636 -> [0;32mI (106) boot: Defaulting to factory image[0m
  27. 18:21:51.636 -> [0;32mI (111) esp_image: segment 0: paddr=00010020 vaddr=3c070020 size=15c74h ( 89204) map[0m
  28. 18:21:51.636 -> [0;32mI (136) esp_image: segment 1: paddr=00025c9c vaddr=3fc97600 size=050d8h ( 20696) load[0m
  29. 18:21:51.636 -> [0;32mI (140) esp_image: segment 2: paddr=0002ad7c vaddr=40374000 size=0529ch ( 21148) load[0m
  30. 18:21:51.636 -> [0;32mI (146) esp_image: segment 3: paddr=00030020 vaddr=42000020 size=6d768h (448360) map[0m
  31. 18:21:51.865 -> [0;32mI (230) esp_image: segment 4: paddr=0009d790 vaddr=4037929c size=0e35ch ( 58204) load[0m
  32. 18:21:51.865 -> [0;32mI (243) esp_image: segment 5: paddr=000abaf4 vaddr=50000000 size=00010h (    16) load[0m
  33. 18:21:51.865 -> [0;32mI (251) boot: Loaded app from partition at offset 0x10000[0m
  34. 18:21:51.865 -> [0;32mI (251) boot: Disabling RNG early entropy source...[0m
  35. 18:21:51.865 -> [0;32mI (263) cpu_start: Pro cpu up.[0m
  36. 18:21:51.865 -> [0;32mI (263) cpu_start: Starting app cpu, entry point is 0x40375304[0m
  37. 18:21:51.865 -> [0;32mI (0) cpu_start: App cpu up.[0m
  38. 18:21:51.865 -> [0;32mI (277) cpu_start: Pro cpu start user code[0m
  39. 18:21:51.865 -> [0;32mI (278) cpu_start: cpu freq: 160000000[0m
  40. 18:21:51.865 -> [0;32mI (278) cpu_start: Application information:[0m
  41. 18:21:51.865 -> [0;32mI (280) cpu_start: Project name:     VCI_AL[0m
  42. 18:21:51.865 -> [0;32mI (285) cpu_start: App version:      010af76-dirty[0m
  43. 18:21:51.865 -> [0;32mI (291) cpu_start: Compile time:     Dec  6 2022 17:39:08[0m
  44. 18:21:51.865 -> [0;32mI (297) cpu_start: ELF file SHA256:  45e3beec6be7d774...[0m
  45. 18:21:51.865 -> [0;32mI (303) cpu_start: ESP-IDF:          v4.4.3-dirty[0m
  46. 18:21:51.865 -> [0;32mI (308) heap_init: Initializing. RAM available for dynamic allocation:[0m
  47. 18:21:51.865 -> [0;32mI (315) heap_init: At 3FCA2148 len 000475C8 (285 KiB): D/IRAM[0m
  48. 18:21:51.865 -> [0;32mI (322) heap_init: At 3FCE9710 len 00005724 (21 KiB): STACK/DRAM[0m
  49. 18:21:51.865 -> [0;32mI (328) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM[0m
  50. 18:21:51.865 -> [0;32mI (335) heap_init: At 600FE000 len 00002000 (8 KiB): RTCRAM[0m
  51. 18:21:51.865 -> [0;32mI (341) spi_flash: detected chip: gd[0m
  52. 18:21:51.865 -> [0;32mI (345) spi_flash: flash io: dio[0m
  53. 18:21:51.865 -> [0;32mI (350) sleep: Configure to isolate all GPIO pins in sleep state[0m
  54. 18:21:51.865 -> [0;32mI (356) sleep: Enable automatic switching of GPIO sleep configuration[0m
  55. 18:21:51.865 -> [0;32mI (363) esp_core_dump_uart: Init core dump to UART[0m
  56. 18:21:51.865 -> [0;32mI (368) coexist: coexist rom version e7ae62f[0m
  57. 18:21:51.865 -> [0;32mI (374) cpu_start: Starting scheduler on PRO CPU.[0m
  58. 18:21:51.865 -> [0;32mI (0) cpu_start: Starting scheduler on APP CPU.[0m
  59. 18:21:54.056 -> [0;32mI (4794) uart: queue free spaces: 20[0m
  60. 18:21:54.102 -> [0;33mW (4804) BT_INIT: esp_bt_controller_mem_release not implemented, return OK[0m
  61. 18:21:54.102 -> [0;32mI (4804) BT_INIT: BT controller compile version [421c279][0m
  62. 18:21:54.102 -> [0;32mI (4804) phy_init: phy_version 503,13653eb,Jun  1 2022,17:47:08[0m
  63. 18:21:54.151 -> [0;32mI (4844) system_api: Base MAC address is not set[0m
  64. 18:21:54.151 -> [0;32mI (4844) system_api: read default base MAC address from EFUSE[0m
  65. 18:21:54.151 -> [0;32mI (4844) BT_INIT: Bluetooth MAC: f4:12:fa:d5:66:7a
  66. 18:21:54.151 -> [0m
  67. 18:21:54.151 -> [0;32mI (4854) NimBLE: GAP procedure initiated: stop advertising.
  68. 18:21:54.151 -> [0m
  69. 18:21:54.151 -> [0;32mI (4864) NimBLE: GAP procedure initiated: advertise; [0m
  70. 18:21:54.151 -> [0;32mI (4864) NimBLE: disc_mode=2[0m
  71. 18:21:54.151 -> [0;32mI (4874) NimBLE:  adv_channel_map=0 own_addr_type=0 adv_filter_policy=0 adv_itvl_min=0 adv_itvl_max=0[0m
  72. 18:21:54.151 -> [0;32mI (4884) NimBLE:
  73. 18:21:54.151 -> [0m
  74. 18:21:56.155 -> Waiting 2 Seconds  .  .
  75. 18:21:56.155 -> Copied "TOOL BUSY" into the Message
  76. 18:21:58.159 -> Waiting 2 Seconds  .  .
  77. 18:21:58.159 -> Copied "TOOL READY" into the Message
  78. 18:21:58.159 -> [0;32mI (8884) uart: queue free spaces: 20[0m
  79. 18:21:58.159 -> ESP32 Started;
  80. 18:22:18.085 -> [0;32mI (28794) UART0: [DATA_EVT]: {"Command":"UpdateOTA"};
  81. 18:22:18.085 -> [0m
  82. 18:22:18.085 -> Received Total 23 bytes of Data
  83. 18:22:18.085 -> The Received Data String is : {"Command":"UpdateOTA"}
  84. 18:22:18.085 -> Received Command: UpdateOTA
  85. 18:22:18.085 -> Received UpdateOTA inside parse_commands
  86. 18:22:20.092 -> [0;32mI (30834) MSC: Waiting for USB stick to be connected[0m
  87. 18:22:20.549 -> [0;32mI (31274) MSC: MSC device connected[0m
  88. 18:22:21.644 -> Device info:
  89. 18:22:21.644 ->      Capacity: 14805 MB
  90. 18:22:21.644 ->      Sector size: 512
  91. 18:22:21.644 ->      Sector count: 30322687
  92. 18:22:21.644 ->      PID: 0x1985
  93. 18:22:21.644 ->      VID: 0x 3F0
  94. 18:22:21.644 ->    

chegewara
Posts: 2207
Joined: Wed Jun 14, 2017 9:00 pm

Re: ESP32-S3 OTA Update from USB PenDrive resets during esp_ota_end()

Postby chegewara » Tue Dec 06, 2022 11:05 pm

You have good amount of logs in this code, but the logs you posted tells us nothing, sorry.

https://man7.org/linux/man-pages/man3/fread.3.html
If an error occurs, or the end of the file
is reached, the return value is a short item count (or zero).

fread() does not distinguish between end-of-file and error, and
callers must use feof(3) and ferror(3) to determine which
occurred.

lipun12ka4
Posts: 5
Joined: Tue Dec 06, 2022 12:55 pm

Re: ESP32-S3 OTA Update from USB PenDrive resets during esp_ota_end()

Postby lipun12ka4 » Wed Dec 07, 2022 2:20 am

chegewara wrote:
Tue Dec 06, 2022 11:05 pm
You have good amount of logs in this code, but the logs you posted tells us nothing, sorry.

https://man7.org/linux/man-pages/man3/fread.3.html
If an error occurs, or the end of the file
is reached, the return value is a short item count (or zero).

fread() does not distinguish between end-of-file and error, and
callers must use feof(3) and ferror(3) to determine which
occurred.
Well, I pasted the complete Log, but it seems the Forum Post doesn't like very long logs. I ama attaching the complete Log here.
Attachments
OTA Pen Drive Log.txt
(6.41 KiB) Downloaded 122 times

chegewara
Posts: 2207
Joined: Wed Jun 14, 2017 9:00 pm

Re: ESP32-S3 OTA Update from USB PenDrive resets during esp_ota_end()

Postby chegewara » Wed Dec 07, 2022 4:03 am

Sorry, but still the same logs. No ota begin, no progress, no ota end etc.
From logs we cant see if file is open, read and ota progressed, also no crash log (reset) you mentioned.

lipun12ka4
Posts: 5
Joined: Tue Dec 06, 2022 12:55 pm

Re: ESP32-S3 OTA Update from USB PenDrive resets during esp_ota_end()

Postby lipun12ka4 » Wed Dec 07, 2022 4:17 am

chegewara wrote:
Wed Dec 07, 2022 4:03 am
Sorry, but still the same logs. No ota begin, no progress, no ota end etc.
From logs we cant see if file is open, read and ota progressed, also no crash log (reset) you mentioned.
I did not verify if all text was there in the text file. So Stupid of me. Apparantly, when I am copying the Text from my serial terminal output some of the text was missing, had to manually checked and copies/typed those lines.
Attachments
OTA Pen Drive Log.txt
(6.41 KiB) Downloaded 122 times

lipun12ka4
Posts: 5
Joined: Tue Dec 06, 2022 12:55 pm

Re: ESP32-S3 OTA Update from USB PenDrive resets during esp_ota_end()

Postby lipun12ka4 » Tue Dec 27, 2022 1:04 pm

Well, the problem was the MSC function was using a Level1 Interrupt, while the TWAI function also uses the same. When I changed the Interrupt for the MSC Class to Level3 it worked, no more crashes. and OTA from PenDrive done in 7 Seconds. That is Fast.

frankcohen
Posts: 23
Joined: Mon Apr 05, 2021 4:03 am

Re: ESP32-S3 OTA Update from USB PenDrive resets during esp_ota_end()

Postby frankcohen » Sun Aug 06, 2023 8:51 pm

Hi lipun12ka4, thank you for posting your code, logs, and the solution. I am building a mobile entertainment experience called Reflections. I did not want to use the Wifi OTA solutions because they assume we all have SSL certificate management solutions. For example, what happens to your OTA solution a year from now when the device's SSL certificate expires?! For my device I already designed and built a Bluetooth Low Energy (BLE) solution to move files from a server to the device, including the OTA bin file and a version number file. Simple modifications to your code let me use OTA to install the bin file from a local NAND/SD card storage device. Thank you for posting. Below is my update to your code. And I am hosting everything of the Reflections project at https://github.com/frankcohen/ReflectionsOS

OTA.h

Code: Select all

#ifndef _OTA_
#define _OTA_

#include "config.h"
#include "secrets.h"

#include "Arduino.h"

#include "esp_ota_ops.h"        //included header file for esp_ota driver
#include "FS.h"
#include "SD.h"

class OTA
{
  public:
    OTA();
    void begin();
    bool update();
    void loop();

  private:

};

#endif // _OTA_
OTA.cpp

Code: Select all

/*
 Reflections, mobile connected entertainment device

 Repository is at https://github.com/frankcohen/ReflectionsOS
 Includes board wiring directions, server side components, examples, support

 Licensed under GPL v3 Open Source Software
 (c) Frank Cohen, All rights reserved. fcohen@starlingwatch.com
 Read the license in the license.txt file that comes with this code.

 Thank you to @lipun12ka4 on Espressif Forums for sharing his OTA code,
 a problem, and solution:
 https://esp32.com/posting.php?f=13&mode=reply&t=30973&sid=89252e0558c707c8813146f40cccf9fc

*/

#include "OTA.h"

OTA::OTA(){}

void OTA::begin()
{ 
}
 
#define OTA_MAX_BYTES_PER_BATCH 4096
 
uint8_t buf[ OTA_MAX_BYTES_PER_BATCH + 1 ];
 
static char* TAG = "OTA";
 
static uint32_t total = 0;
static uint32_t pct = 0;
static uint32_t pct_send = 0;
static char message_data[10];
 
//static esp_err_t err;//Error variable to indicate when calling function return error.It is used in NVS function (WRITE,READ SERIAL number from NVS)

static esp_ota_handle_t update_handle = 0;  //should be used for subsequent esp_ota_write() and esp_ota_end() calls

//const esp_partition_t *update_partition = NULL; //Pointer to info for partition which should be updated next.

//NULL result indicates invalid OTA data partition, or that no eligible OTA app slot partition was found 

/*
  Uses ESP32 app_update to do local OTA, where Storage.replicate()
  already downloads the firmware and version number
  (.bin and file named OTA_VERSION_FILE_NAME).
  https://github.com/espressif/esp-idf/tree/master/components/app_update

  This does the installation using the OTA mechanism

  Upon successful update, stores the new version number to the version file
  and restarts the device.
*/

bool OTA::update()
{
  //  Find the otaversion.txt file, return if it does not exist
  File versfile = SD.open( OTA_VERSION_FILE_NAME, FILE_READ );
  if( !versfile )
  {
      Serial.print( F( "Failed to open " ) );
      Serial.print( OTA_VERSION_FILE_NAME );
      Serial.println( F( ", skipping update" ) );
      return false;
  }

  // Deserialize the version number
  char myNum[5];
  int i = 0;
  while ( versfile.available() && ( i < 5 ) )
  {
    myNum[ i ] = versfile.read();
    i++;
  }
  myNum[ i ] = 0;
  int myVer = atoi( myNum );

  Serial.print( F( "OTA version number from file is " ) );
  Serial.println( myVer );

  if ( myVer <= VERSION_NUMBER )
  {
    Serial.println( F( "No need to update." ) );
    return false;
  }

  // Update to the new firmware

  File ota_bin_file;
  int finished = 0;
  struct stat entry_stat;
  uint32_t file_size = 0;

  Serial.print( F( "OTA Bin File Path = " ) );
  Serial.println( OTA_BIN_FILE_NAME );

  ota_bin_file = SD.open( OTA_BIN_FILE_NAME, FILE_READ );

  if ( ! ota_bin_file ) 
  {
    Serial.print( F( "Failed to open OTA file: ") );
    Serial.println( OTA_BIN_FILE_NAME );
    return false;
  }
  
  file_size = (uint32_t) ota_bin_file.size();
  Serial.print( F( "OTA file size is " ) );
  Serial.println( file_size );
  
  const esp_partition_t *configured = esp_ota_get_boot_partition();
  const esp_partition_t *running = esp_ota_get_running_partition();

  if ( configured != running )
  {
    Serial.print( F( "Configured OTA boot partition at offset" ) );
    Serial.print( configured->address, HEX );
    Serial.print( F( " but running from offset " ) );
    Serial.println( running->address, HEX );
    Serial.print( F( "This can happen from corrupted OTA boot data or preferred boot image data.") );
  }

  Serial.print( F( "Running partition type " ) );
  Serial.print( running->type );
  Serial.print( F( " sub->type " ) );
  Serial.print( running->subtype );
  Serial.print( F( " offset " ) );
  Serial.println( running->address );

  const esp_partition_t *update_partition = esp_ota_get_next_update_partition( NULL );
  if ( update_partition == NULL )
  {
    Serial.print( F( "OTA update_partition is NULL ") );
    return false;
  }

  Serial.print( F( "Writing to partition subtype " ) );
  Serial.print( update_partition->subtype );
  Serial.print( F( " at offset " ) );
  Serial.println( update_partition->address );

  esp_err_t err = esp_ota_begin( update_partition, file_size, &update_handle );

  Serial.print( F( "esp_begin result = " ) );
  Serial.println( err );

  Serial.print( F( "Update handle is " ) );
  Serial.println( update_handle );

  if ( err != ESP_OK )
  {
    Serial.print( F( "esp_ota_begin failed, error " ) );
    Serial.println( err );
    return false;        
  }

  Serial.println( F( "esp_ota_begin succeeded" ) );

  while( !finished )
  {
    unsigned int retn = ota_bin_file.read( buf, OTA_MAX_BYTES_PER_BATCH );
    Serial.print( F( "First Byte of the Read Data Chunk is " ) );
    Serial.println( buf[0] );

    if ( retn != OTA_MAX_BYTES_PER_BATCH )
    {
      Serial.print( F( "Finished reading, last chunk size " ) );
      Serial.println( retn );

      err = esp_ota_write(update_handle, buf, retn);

      if (err == ESP_ERR_INVALID_ARG) 
      {
        Serial.print( F( "error: esp_ota_write failed! err = " ) );
        Serial.println( err );
        return false;
      } 
      else if (err == ESP_ERR_OTA_VALIDATE_FAILED) 
      {
        Serial.println( F( "error: First byte of image contains invalid app image magic byte" ) );
        return false;
      } 
      else if (err == ESP_ERR_FLASH_OP_FAIL)
      {
        Serial.println( F( "error: Flash write IO Operaion failed" ) );
        return false;
      } 
      else if ( err == ESP_ERR_FLASH_OP_TIMEOUT )
      {
        Serial.println( F( "error: Flash write failed due to TimeOut") );
        return false;
      }
      else if (err == ESP_ERR_OTA_SELECT_INFO_INVALID )
      {
        Serial.println( F( "error: OTA data partition has invalid contents" ) );
        return false;
      }
      else if (err == ESP_OK) 
      {
        Serial.print( F( "Wrote " ) );
        Serial.print( retn );
        Serial.println( F( " bytes to OTA Partition" ) );
      }

      Serial.print( F( "Ota result = " ) );
      Serial.println( err );

      total += retn;
      pct = total * 100 / file_size;
      itoa( pct, message_data, 10 );

      Serial.print( F( "Progress " ) );
      Serial.print( message_data) ;
      Serial.print( F( "/ttotal bytes read from the OTA BIN rile is " ) );
      Serial.println( total );

      delay( 2000 );

      Serial.print( F( "Update handle is " ) );
      Serial.println( update_handle );
      err = esp_ota_end( update_handle );

      if (err != ESP_OK) 
      {
        if ( err == ESP_ERR_OTA_VALIDATE_FAILED ) 
        {
          Serial.println( F( "Image validation failed, image corrupt" ) );
        }
        else
        {
          Serial.print( F( "esp_ota_end failed " ) );
          Serial.println( esp_err_to_name( err ) );
        }
        return false;
      }

      Serial.println( F( "OTA update ended" ) );

      err = esp_ota_set_boot_partition( update_partition );
      if ( err != ESP_OK )
      {
        Serial.print( F( "esp_ota_set_boot_partition failed, " ) );
        Serial.println( esp_err_to_name( err ) );
      }

      Serial.println( F( "Prepare to restart" ) );
      delay(5000);
      finished = 1;
      break;
    }
    else
    {
      err = esp_ota_write(update_handle, buf, retn);

      if ( err == ESP_ERR_INVALID_ARG )
      {
        Serial.print( F( "esp_ota_write failed. err= " ) );
        Serial.println( err );
        return false;
      }
      else if ( err == ESP_ERR_OTA_VALIDATE_FAILED )
      {
        Serial.print( F( "error: First byte of image contains invalid app image magic byte" ) );
        return false;
      }
      else if ( err == ESP_ERR_FLASH_OP_FAIL )
      {
        Serial.print( F( "error: Flash write IO Operaion failed" ) );
        return false;
      } 
      else if ( err == ESP_ERR_FLASH_OP_TIMEOUT )
      {
        Serial.print( F( "error: Flash write failed due to TimeOut" ) );
        return false;
      }
      else if ( err == ESP_ERR_OTA_SELECT_INFO_INVALID )
      {
        Serial.print( F( "error: OTA data partition has invalid contents" ) );
        return false;
      } 
      else if ( err == ESP_OK )
      {
        Serial.print( F( "Wrote " ) );
        Serial.print( retn );
        Serial.println( F( " bytes to OTA Partition" ) );
      }

      total += OTA_MAX_BYTES_PER_BATCH;

      pct = total * 100 / file_size;

      if( pct != pct_send )
      {
        pct_send = pct;
        itoa(pct, message_data, 10);
        Serial.print( F( "Progress " ) );
        Serial.println( message_data );
      }
    }
  }

  // Save the new version number to the otaversion file

  Serial.println( F( "Save the new version number to the otaversion file" ) );

  if( SD.remove( OTA_VERSION_FILE_NAME ) )
  {
    Serial.print("Deleted ");
    Serial.println( OTA_VERSION_FILE_NAME );

    File versfile = SD.open( OTA_VERSION_FILE_NAME, FILE_WRITE );
    if( !versfile )
    {
      Serial.println( F( "Failed to open OTA VERSION file for writing" ) );
      return false;
    }

    char numberArray[20];
    itoa( VERSION_NUMBER, numberArray, 10);
    versfile.print( numberArray );

    Serial.println( F( "Done" ) );
  } 
  else
  {
    Serial.print( F( "Failed to delete " ) );
    Serial.println( OTA_VERSION_FILE_NAME );
    return false;
  }

  Serial.println( F( "Update finished" ) );
  Serial.println( F( "Restarting the host" ) );
  ESP.restart();
  return true;
}
-Frank

Klhnikov
Posts: 2
Joined: Sat Nov 19, 2022 12:06 am

Re: ESP32-S3 OTA Update from USB PenDrive resets during esp_ota_end()

Postby Klhnikov » Sat Aug 19, 2023 11:34 pm

Hi every one, I also did a fork of this code but to send and read the ota directly from UART_0 (attached USB port).

Thank again to OP and lets continue the share !

Code: Select all

#include "main.hpp"

uint8_t buf[OTA_MAX_BYTES_PER_BATCH+1];
 
static uint32_t total = 0;
static uint32_t pct = 0;
static uint32_t pct_send = 0;
static char message_data[10];
 
//static esp_err_t err;//Error variable to indicate when calling function return error.It is used in NVS function (WRITE,READ SERIAL number from NVS)
static esp_ota_handle_t update_handle = 0;  //should be used for subsequent esp_ota_write() and esp_ota_end() calls
//const esp_partition_t *update_partition = NULL; //Pointer to info for partition which should be updated next.
//NULL result indicates invalid OTA data partition, or that no eligible OTA app slot partition was found
 
 
//Function is used to implement OTA function
int ota_flash(uint32_t ota_size_number){

	blink_status = false;
	int finished = 0;

	printf("starting main task firmware update \n");

	vTaskDelay(500 / portTICK_PERIOD_MS);

	const esp_partition_t *configured = esp_ota_get_boot_partition();
	const esp_partition_t *running = esp_ota_get_running_partition();

	if (configured != running) {
		printf("Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x \n",configured->address, running->address);
		printf("This can happen if either the OTA boot data or preferred boot image become corrupted somehow.\n");
	}

	//printf("Running partition type %d sub-type %d (offset 0x%08x) \n",running->type, running->subtype, running->address);

	const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL);
	assert(update_partition != NULL);

	//printf("Writing to partition subtype %d at offset 0x%x \n", update_partition->subtype, update_partition->address);

	//esp_err_t err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
	esp_err_t err = esp_ota_begin(update_partition, ota_size_number, &update_handle);

	//printf("Update Handle is %d \n", update_handle);

	if (err != ESP_OK) {
		printf("esp_ota_begin failed, error=%d \n", err);
		printf("esp_ota_begin failed\n");
		return(1);
	}

	printf("esp_ota_begin succeeded \n");

	while(!finished)
	{
		// read by OTA_MAX_BYTES_PER_BATCH
		unsigned int retn = uart_read_bytes(UART_PORT, buf, OTA_MAX_BYTES_PER_BATCH, 500 / portTICK_RATE_MS);

		//printf("First Byte of the Read Data Chunk is %X \n", buf[0]);	

		if (retn != OTA_MAX_BYTES_PER_BATCH)
		{
		//	printf("Finished reading, Last Chunk size %d \n",retn);

			err = esp_ota_write(update_handle, buf, retn);

			if (err == ESP_ERR_INVALID_ARG) {
				printf("error: esp_ota_write failed! err=0x%x\n", err);
				return(1);
			} else if (err == ESP_ERR_OTA_VALIDATE_FAILED) {
				printf("error: First byte of image contains invalid app image magic byte\n");
			} else if (err == ESP_ERR_FLASH_OP_FAIL) {
				printf("error: Flash write IO Operaion failed\n");
			} else if (err == ESP_ERR_FLASH_OP_TIMEOUT) {
				printf("error: Flash write failed due to TimeOut\n");
			} else if (err == ESP_ERR_OTA_SELECT_INFO_INVALID) {
				printf("error: OTA data partition has invalid contents\n");
			} else if (err == ESP_OK) {
			//	printf("Wrote %d Bytes to OTA Partition \n", retn);
			}

			total += retn;
			pct = total * 100 / ota_size_number;

			itoa(pct, message_data, 10);
			printf("Progress %s %% \n", message_data);
			//printf("Total Bytes Read from the OTA BIN File is %d \n", total);

			//vTaskDelay(5000/portTICK_PERIOD_MS);
		//	printf("Update Handle is %d \n", update_handle);
			err = esp_ota_end(update_handle);

			// stop LED
			gpio_set_level(LED_GPIO_PIN, LOW);

			if (err != ESP_OK) {
				if (err == ESP_ERR_OTA_VALIDATE_FAILED) {
					printf("Image validation failed, image is corrupted \n");
				} else {
					printf("esp_ota_end failed (%s)! \n", esp_err_to_name(err));
				}
				return(1);
			}

			//vTaskDelay(5000/portTICK_PERIOD_MS);

			printf("OTA Update has Ended \n");

			err = esp_ota_set_boot_partition(update_partition);
			if (err != ESP_OK) {
				printf("esp_ota_set_boot_partition failed (%s)! \n", esp_err_to_name(err));
			}

			//vTaskDelay(5000/portTICK_PERIOD_MS);
			printf("Prepare to restart system! \n");
			finished = 1;
			break;
		}
		else
		{

			// LED blink
			if (blink_status == 0)
				gpio_set_level(LED_GPIO_PIN, HIGH);
			else
				gpio_set_level(LED_GPIO_PIN, LOW);
			blink_status = !blink_status;

			err = esp_ota_write(update_handle, buf, retn);

			if (err == ESP_ERR_INVALID_ARG) {
				printf("error: esp_ota_write failed! err=0x%x\n", err);
				return(1);
			} else if (err == ESP_ERR_OTA_VALIDATE_FAILED) {
				printf("error: First byte of image contains invalid app image magic byte\n");
			} else if (err == ESP_ERR_FLASH_OP_FAIL) {
				printf("error: Flash write IO Operaion failed\n");
			} else if (err == ESP_ERR_FLASH_OP_TIMEOUT) {
				printf("error: Flash write failed due to TimeOut\n");
			} else if (err == ESP_ERR_OTA_SELECT_INFO_INVALID) {
				printf("error: OTA data partition has invalid contents\n");
			} else if (err == ESP_OK) {
			//	printf("Wrote %d Bytes to OTA Partition \n", retn);
			}

			total += OTA_MAX_BYTES_PER_BATCH;

			pct = total * 100 / ota_size_number; //calculated percentage

			if(pct != pct_send ) //i.e. if the rounded off percentage is updated
			{
				pct_send = pct;
				itoa(pct, message_data, 10);
				printf("Progress %s %% \n", message_data);
			}
		}
		
		// this helps regulating the incoming data, must implement the same logic on sender side (send 4096 bytes, wait for "OK")
		uart_write_bytes(UART_PORT, (const char *)"OK\r\n", 4);

	}//Reading of data from USB complete
	return(0);
}   //end of OTA function
And here is the (draft) sender's Python code:

Code: Select all

from utils import connect_serial

if __name__ == "__main__":

	ser = serial.Serial(COM4, 115200, timeout=1)
	filename = "ota.log"

	f = open(filename, 'wb')

	ota_firmware = "path/to/your/firmware.bin"

	with open(ota_firmware, "rb") as firmwarefile:
		data = firmwarefile.read()

	size = len(data)

	print(f"[+] OTA file loaded with size: {size}")

	ser.write(f"ota_flash {size}\r\n".encode())
	print("[+] OTA started...")

	try:
		while True:
			ln = ser.read_until(b"\r\n")
			print(ln)
			f.write(ln)
			f.flush()
			if ln == b'esp_ota_begin succeeded \r\n':
				break
	except KeyboardInterrupt:
		print("[+] Stopping...")

	print("[+] Start sending.")

	try:
		for i in range(0, size, 4096):
			written = ser.write(data[i:i+4096])
			while True:
				ln = ser.read_until(b"\r\n")
				if ln == b"OK\r\n":
					break
				else:
					print(ln)
					f.write(ln)
					f.flush()
					if ln == b"OTA Update has Ended \r\n":
						break
	except KeyboardInterrupt:
		print("[+] Stopping...")

	print("[+] Sending done.")

	try:
		while True:
			ln = ser.read_until(b"\r\n")
			print(ln)
			f.write(ln)
			f.flush()
	except KeyboardInterrupt:
		print("[+] Stopping...")

	f.close()
	ser.close()
	print("[+] Done.")


Who is online

Users browsing this forum: Bing [Bot], HighVoltage and 134 guests