add faster overwrite alternate flashing method

This commit is contained in:
King Kévin 2022-10-24 16:27:07 +02:00
parent 8f31c8a740
commit 5c0e27b9e2
1 changed files with 66 additions and 27 deletions

View File

@ -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
}
}