Merhaba,
ESP32'de HTTP-OTA yöntemiyle yazılımı güncellemeye çalışıyorum. Bir adrese http request edip dosyayı indirip flash'a yazabiliyorum. İşlem bitince reset atılıyor ve yeni yüklenmiş olan uygulama çalışmaya başlıyor, fakat bir süre sonra RTC_WDT sebepli bir reset ile sistem yeniden başlıyor ve esp eski yazılımı başlatıyor. Burada belirttiğim "bir süre" aslında 90 sn. RTC watc-dog timer için bizim ayarladığımız süre.
Bu konuda dökümanın söylediği şey; yeni yüklenen program çalışırken bir hata oluşursa, sistem tekrar eski programdan başlatılır. (rollback)
Eğer roll-back seçeneğini kapatırsam bu durumu engelliyorum yani sürekli yeni program çalışıyor ama bir süre sonra çalışan uygulama ile ilgili başka hatalar geliyor. Tam anlamasam da programın bozuk olduğunu belirtiyor.
Aklıma tek gelen şey program yazılırken bir hata olması. Update işleminin yapıldığı task'ın priority'sini en yükseğe çektim ama durum değişmedi.
Daha önce benzer bir işlem yapan varsa bilgilendirirse sevinirim.
# Name Type SubType Offset Size Flags
# Note: if you have increased the bootloader size make sure to update the offsets to avoid overlap
nvs data nvs 0x4000
certs data nvs 0x2000
otadata data ota 0x2000
phy_init data phy 0x1000
ota_0 app ota_0 0x180000
ota_1 app ota_1 0x180000
esp_err_t _http_event_handler(esp_http_client_event_t *evt)
{
assert(evt != NULL);
switch (evt->event_id)
{
case HTTP_EVENT_ERROR:
ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
break;
case HTTP_EVENT_ON_CONNECTED:
ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
break;
case HTTP_EVENT_HEADER_SENT:
ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
break;
case HTTP_EVENT_ON_HEADER:
ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
break;
case HTTP_EVENT_ON_DATA:
ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
if (!esp_http_client_is_chunked_response(evt->client))
{
// Write out data
ESP_LOGD(TAG, "%.*s", evt->data_len, (char *)evt->data);
}
break;
case HTTP_EVENT_ON_FINISH:
ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
break;
case HTTP_EVENT_DISCONNECTED:
ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED");
break;
}
return ESP_OK;
}
static void start_ota()
{
// if (!fw_versions_are_equal(current_ver, ota_config.targetFwVer) && ota_params_are_specified(ota_config))
{
ESP_LOGW(TAG, "Starting OTA, firmware versions are different - current: %s, target: %s", FIRMWARE_VERSION, dev->otaFwVer);
ESP_LOGI(TAG, "Target firmware version: %s", dev->otaFwVer);
ESP_LOGI(TAG, "Firmware URL: %s", dev->otaFwUrl);
msg_print("OTA start");
vTaskDelay(1000);
esp_http_client_config_t config = {
.url = dev->otaFwUrl,
.cert_pem = (char *)server_cert_pem_start,
.event_handler = _http_event_handler,
};
/* OTA OPERATION*/
// esp_err_t ret = esp_https_ota(&config);
esp_err_t ret = ESP_FAIL;
int cnt = 0;
do
{
esp_https_ota_config_t ota_config = {
.http_config = &config,
};
esp_https_ota_handle_t https_ota_handle = NULL;
ret = esp_https_ota_begin(&ota_config, &https_ota_handle);
if (https_ota_handle == NULL)
{
sprintf((char *)&ota_print, "OTA Not Started.");
ota_print_new++;
ret = ESP_FAIL;
break;
}
while (1)
{
ret = esp_https_ota_perform(https_ota_handle);
if (ret != ESP_ERR_HTTPS_OTA_IN_PROGRESS)
{
break;
}
sprintf((char *)&ota_print, "OTA Progress: %d", cnt);
ota_print_new++;
cnt++;
}
if (ret != ESP_OK)
{
esp_https_ota_abort(https_ota_handle);
}
else
{
ret = esp_https_ota_finish(https_ota_handle);
}
if (ret != ESP_OK)
{
sprintf((char *)&ota_print, "OTA Aborted: %d", cnt);
ota_print_new++;
}
else
{
sprintf((char *)&ota_print, "OTA Complete: %d", cnt);
ota_print_new++;
}
} while (0);
if (ret == ESP_OK)
{
sys_reset_run();
}
else
{
msg_print("OTA Fail");
ESP_LOGE(TAG, "Firmware Upgrades Failed");
}
dev->flg.ota_state = ota_cmd_none;
}
vTaskDelete(0);
}
Ben sorunsuz ota güncellemesini kullanıyorum. partition table ve ota kodu yuarıda ki gibi belki faydası olur diye ekliyorum.
ota komut kontrolü yapan ayrı bir taskin içinde de aşağıda ki kod parçası ile ilgili taski oluşturuyorum.
if (dev->flg.ota_state == ota_cmd_start)
{
dev->flg.ota_state = ota_cmd_busy;
xTaskCreatePinnedToCore(start_ota, "ota", 1024 * 3, NULL, 1, NULL, 1);
}
@hasankara teşekkürler. Ben de otayı benzer şekilde kullanıyorum. Partition table ile ilgili sorunum yok, zaten yeni uygulamayı update ederken partition table'ı değiştirmiyorum.
Advanced_ota_example örneğindeki gibi ota'yı kullanıyorum. Seninki gibi sayılır. Fakat yeni uygulama yüklendikten sonra RTC-watc-dog ile reset atıyordu ve eski uygulamaya geçiyordu.
Bootloader config menüsünde CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE diye bir seçenek var bunu disable edince sorun çözüldü. Roll-back özelliği ile hatalı çalışan uygulama silinip eskisine dönüyor. Bunu disable edince sorun çözüldü ama doğru mu yaptım emin olmamadım.
Advanced_ota_example'da da bu özellik default olarak disable geliyor. Eğer enable edersem, reset atmıyor ama power on/off yapınca yeni yazılımı silip eskisini yüklüyor.
Aşağıdaki linkdeki açıklaması var ama bana wdt ve power on/off durumunda roll-back yapması saçma geldi.
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html#config-bootloader-app-rollback-enable
(https://i.ibb.co/W3LDJQR/Screenshot-2022-03-19-120322.png) (https://ibb.co/W3LDJQR)
Bu özellikten benimde yeni haberim oldu diyebilirim. Bende kapalıymış ilgili özellik. Faydası olur diye benim ayarların resmini yüklüyorum.
Eyv hocam bende açıktı ben de kapattım.