From 5c0e27b9e2368bf874fb771c2b0a12e8dbf46a02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Mon, 24 Oct 2022 16:27:07 +0200 Subject: [PATCH] add faster overwrite alternate flashing method --- examples/device/dfu_freertos/src/main.c | 93 ++++++++++++++++++------- 1 file changed, 66 insertions(+), 27 deletions(-) diff --git a/examples/device/dfu_freertos/src/main.c b/examples/device/dfu_freertos/src/main.c index 65262ba10..f2e94b336 100644 --- a/examples/device/dfu_freertos/src/main.c +++ b/examples/device/dfu_freertos/src/main.c @@ -87,6 +87,9 @@ void usb_device_task(void* param); // used to download image onto OTA partition esp_ota_handle_t ota_handle = 0; +// how to program the downloaded data (0 = using OTA tools, 1 = using partition tools) +static uint8_t dl_method = 0; + // download blocks to program static uint8_t dl_block[CFG_TUD_DFU_XFER_BUFSIZE] = {0}; static uint16_t dl_block_len = 0; @@ -99,36 +102,71 @@ static void dl_task(void* arg) esp_err_t rc; while (true) { if (dl_block_len) { // we received a new block - // get handle for OTA update - if (0 == ota_handle) { - const esp_partition_t *ota_part = esp_ota_get_next_update_partition(NULL); - if (NULL == ota_part) { - ESP_LOGE(TAG, "OTA not found"); - tud_dfu_finish_flashing(DFU_STATUS_ERR_PROG); - return; + const esp_partition_t *ota_part = esp_ota_get_next_update_partition(NULL); + if (NULL == ota_part) { + ESP_LOGE(TAG, "OTA not found"); + tud_dfu_finish_flashing(DFU_STATUS_ERR_PROG); + continue; + } + if (0 == dl_method) { // using OTA tools + // get handle for OTA update + if (0 == ota_handle) { + rc = esp_ota_begin(ota_part, OTA_SIZE_UNKNOWN, &ota_handle); + if (ESP_OK != rc) { + ESP_LOGE(TAG, "init OTA failed"); + esp_ota_abort(ota_handle); + ota_handle = 0; + tud_dfu_finish_flashing(DFU_STATUS_ERR_ERASE); + continue; + } } - rc = esp_ota_begin(ota_part, OTA_SIZE_UNKNOWN, &ota_handle); + + // write data to partition + rc = esp_ota_write_with_offset(ota_handle, dl_block, dl_block_len, dl_block_num * CFG_TUD_DFU_XFER_BUFSIZE); if (ESP_OK != rc) { - ESP_LOGE(TAG, "init OTA failed"); + ESP_LOGE(TAG, "writing OTA failed"); esp_ota_abort(ota_handle); ota_handle = 0; - tud_dfu_finish_flashing(DFU_STATUS_ERR_ERASE); - return; + tud_dfu_finish_flashing(DFU_STATUS_ERR_WRITE); + continue; } - } - // write data to partition - rc = esp_ota_write_with_offset(ota_handle, dl_block, dl_block_len, dl_block_num * CFG_TUD_DFU_XFER_BUFSIZE); - if (ESP_OK != rc) { - ESP_LOGE(TAG, "writing OTA failed"); - esp_ota_abort(ota_handle); - ota_handle = 0; - tud_dfu_finish_flashing(DFU_STATUS_ERR_WRITE); - return; + tud_dfu_finish_flashing(DFU_STATUS_OK); // flashing op for download complete without error + } else if (1 == dl_method) { // using partition tools + // read current data + uint8_t flash_block[CFG_TUD_DFU_XFER_BUFSIZE]; + rc = esp_partition_read(ota_part, dl_block_num * CFG_TUD_DFU_XFER_BUFSIZE, flash_block, dl_block_len); + if (ESP_OK != rc) { + ESP_LOGE(TAG, "reading range failed"); + tud_dfu_finish_flashing(DFU_STATUS_ERR_CHECK_ERASED); + continue; + } + if (0 == memcmp(dl_block, flash_block, dl_block_len)) { // data is the same + dl_block_len = 0; // ready for next block + tud_dfu_finish_flashing(DFU_STATUS_OK); // flashing op for download complete without error + continue; + } + if (0 == (dl_block_num * CFG_TUD_DFU_XFER_BUFSIZE) % 4096) { // new page + rc = esp_partition_erase_range(ota_part, dl_block_num * CFG_TUD_DFU_XFER_BUFSIZE, 4096); // erase page (block is smaller than page + if (ESP_OK != rc) { + ESP_LOGE(TAG, "erase range failed"); + tud_dfu_finish_flashing(DFU_STATUS_ERR_ERASE); + continue; + } + } + rc = esp_partition_write(ota_part, dl_block_num * CFG_TUD_DFU_XFER_BUFSIZE, flash_block, dl_block_len); // write new data + if (ESP_OK != rc) { + ESP_LOGE(TAG, "writing range failed"); + tud_dfu_finish_flashing(DFU_STATUS_ERR_WRITE); + continue; + } + ESP_LOGD(TAG, "writing range OK"); + dl_block_len = 0; // ready for next block + tud_dfu_finish_flashing(DFU_STATUS_OK); // flashing op for download complete without error + } else { // unknown method + tud_dfu_finish_flashing(DFU_STATUS_ERR_TARGET); } - dl_block_len = 0; // ready for next block - tud_dfu_finish_flashing(DFU_STATUS_OK); // flashing op for download complete without error } else { // no new block vTaskDelay(1); // allow other tasks to run (and watchdog reset) } @@ -285,13 +323,13 @@ void tud_dfu_download_cb(uint8_t alt, uint16_t block_num, uint8_t const* data, u ESP_LOGD(TAG, "download, alt=%u block=%u", alt, block_num); - if (alt > 0) { + if (alt > 1) { ESP_LOGW(TAG, "download to invalid alt %u", alt); tud_dfu_finish_flashing(DFU_STATUS_ERR_ADDRESS); return; } - if (0 == length) { // there is nothing to programm + if (0 == length) { // there is nothing to program // finish flashing if (ota_handle) { rc = esp_ota_end(ota_handle); @@ -306,16 +344,17 @@ void tud_dfu_download_cb(uint8_t alt, uint16_t block_num, uint8_t const* data, u tud_dfu_finish_flashing(DFU_STATUS_OK); // flashing op for download complete without error } else if (length > CFG_TUD_DFU_XFER_BUFSIZE) { // more data than we can handle tud_dfu_finish_flashing(DFU_STATUS_ERR_PROG); - } else if (dl_block_len) { // there is already a block to programm + } else if (dl_block_len) { // there is already a block to program tud_dfu_finish_flashing(DFU_STATUS_ERR_STALLEDPKT); - } else { // all is fine to programm + } else { // all is fine to program if (!dl_started) { xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_DOWNLOAD), 0); dl_started = true; } memcpy(dl_block, data, length); // copy data for dl_task + dl_method = alt; // remember how to flash dl_block_num = block_num; // remember offset - dl_block_len = length; // notitfy dl_task block is ready + dl_block_len = length; // notify dl_task block is ready } }