ESP32: check if OTA/new firmware is working properly

Hi,
I am not sure if this is PlatformIO issue or Espressif or Arduino.
I am compiling the project with:
build_flags = -D CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=1
and:

platform = espressif32
framework = arduino

expecting, that I will be able to check post-OTA if the program is working OK or not, and in case not working ok the rollback would be possible.
For this I use example from Espressif github:

  esp_ota_img_states_t ota_state;
  Serial.print("ota_state:");Serial.println(esp_ota_get_state_partition(running, &ota_state));
  if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) {
      if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) {
          // run diagnostic function ...
          bool diagnostic_is_ok = diagnostic();
          if (diagnostic_is_ok) {
              Serial.printf("Diagnostics completed successfully! Continuing execution ...\n");
              esp_ota_mark_app_valid_cancel_rollback();
          } else {
              Serial.printf("Diagnostics failed! Start rollback to the previous version ...\n");
              esp_ota_mark_app_invalid_rollback_and_reboot();
          }
      }
  }

but the outcome (after OTA) is always the same: ota_state = ESP_OK
that means: I am not able to control the rollback

it looks like OTA itself marks the partition to be valid or I don’t know what exactly who is marking it to be valid.
Anybody experienced it and found the solution?

Well if you are using the ArduinoOTA library, which in turns uses the Update library, when an OTA update is received correctly, it will do

I think this will code will mark it as valid (so no ESP_OTA_IMG_PENDING_VERIFY) and reboot the system.

Nonetheless, you should still be able to perform a rollback by calling into the rollback functions

i.e.,

          if (diagnostic_is_ok) {
              Serial.printf("Diagnostics completed successfully! Continuing execution ...\n");
              // Literally nothing to do
          } else {
              Serial.printf("Diagnostics failed! Start rollback to the previous version ...\n");
              if (Update.canRollBack()) {
                  Update.rollBack(); 
                  //reset microcontroller to reboot into rolled back partition
              } else {
                  Serial.printf("Can't do rollback!...\n");
              }
          }
1 Like

Thank you @maxgerhardt
I applied what you suggested:

{
  Serial.printf("[%s]: \n",__func__);
  const esp_partition_t *running = esp_ota_get_running_partition();
  Serial.printf("running partition: %s\n",running->label);
  // bool diagnostic_is_ok = diagnostic();
  bool diagnostic_is_ok = false;
  if (diagnostic_is_ok) {
      Serial.printf("Diagnostics completed successfully! Continuing execution ...\n");
  } else {
      Serial.printf("Diagnostics failed! Start rollback to the previous version ...\n");
      if (Update.canRollBack()) {
          Update.rollBack(); 
      } else {
          Serial.printf("Can't do rollback!...\n");
      }
  }  
}

but calling Update.rollBack() does literally nothing:

14:22:41.069 > [check_ota_partition]: 
14:22:41.071 > running partition: app0
14:22:41.071 > Diagnostics failed! Start rollback to the previous version ...
14:22:52.190 > [check_ota_partition]: 
14:22:52.190 > running partition: app0
14:22:52.193 > Diagnostics failed! Start rollback to the previous version ...
14:23:03.324 > [check_ota_partition]: 
14:23:03.324 > running partition: app0
14:23:03.327 > Diagnostics failed! Start rollback to the previous version ...
14:23:14.443 > [check_ota_partition]: 
14:23:14.443 > running partition: app0
14:23:14.445 > Diagnostics failed! Start rollback to the previous version ...
14:23:25.581 > [check_ota_partition]: 
14:23:25.581 > running partition: app0
14:23:25.583 > Diagnostics failed! Start rollback to the previous version ...
14:23:36.739 > [check_ota_partition]: 
14:23:36.740 > running partition: app0
14:23:36.742 > Diagnostics failed! Start rollback to the previous version ...
14:23:47.902 > [check_ota_partition]: 
14:23:47.902 > running partition: app0
14:23:47.904 > Diagnostics failed! Start rollback to the previous version ...

This part has to be implemented after calling Update.rollBack();, otherwise it will just mark it as “the next partition to boot to”, but not do anything. You could reuse the same reset code as in the ArduinoOTA class.

1 Like

bloody hell - you are completely right!
I was sure that:

Update.rollBack(); 
//reset microcontroller to reboot into rolled back partition

meant: “Update.rollBack(); does the rollback INCLUDING reset” :wink:

thanks a lot

Of course now, if the diagnostic_function() is blabla, ESP32 will periodically switch partitions :wink:
So I have to think what to check to make sure is it not ambiguous