mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-31 19:24:33 +02:00
Merge branch 'feature/ota_incremental_erase_during_write' into 'master'
Feature/ota incremental erase during write See merge request espressif/esp-idf!9726
This commit is contained in:
@@ -52,7 +52,7 @@
|
||||
typedef struct ota_ops_entry_ {
|
||||
uint32_t handle;
|
||||
const esp_partition_t *part;
|
||||
uint32_t erased_size;
|
||||
bool need_erase;
|
||||
uint32_t wrote_size;
|
||||
uint8_t partial_bytes;
|
||||
uint8_t partial_data[16];
|
||||
@@ -158,16 +158,17 @@ esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp
|
||||
}
|
||||
#endif
|
||||
|
||||
// If input image size is 0 or OTA_SIZE_UNKNOWN, erase entire partition
|
||||
if ((image_size == 0) || (image_size == OTA_SIZE_UNKNOWN)) {
|
||||
ret = esp_partition_erase_range(partition, 0, partition->size);
|
||||
} else {
|
||||
const int aligned_erase_size = (image_size + SPI_FLASH_SEC_SIZE - 1) & ~(SPI_FLASH_SEC_SIZE - 1);
|
||||
ret = esp_partition_erase_range(partition, 0, aligned_erase_size);
|
||||
}
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
if (image_size != OTA_WITH_SEQUENTIAL_WRITES) {
|
||||
// If input image size is 0 or OTA_SIZE_UNKNOWN, erase entire partition
|
||||
if ((image_size == 0) || (image_size == OTA_SIZE_UNKNOWN)) {
|
||||
ret = esp_partition_erase_range(partition, 0, partition->size);
|
||||
} else {
|
||||
const int aligned_erase_size = (image_size + SPI_FLASH_SEC_SIZE - 1) & ~(SPI_FLASH_SEC_SIZE - 1);
|
||||
ret = esp_partition_erase_range(partition, 0, aligned_erase_size);
|
||||
}
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
new_entry = (ota_ops_entry_t *) calloc(sizeof(ota_ops_entry_t), 1);
|
||||
@@ -177,14 +178,9 @@ esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp
|
||||
|
||||
LIST_INSERT_HEAD(&s_ota_ops_entries_head, new_entry, entries);
|
||||
|
||||
if ((image_size == 0) || (image_size == OTA_SIZE_UNKNOWN)) {
|
||||
new_entry->erased_size = partition->size;
|
||||
} else {
|
||||
new_entry->erased_size = image_size;
|
||||
}
|
||||
|
||||
new_entry->part = partition;
|
||||
new_entry->handle = ++s_ota_ops_last_handle;
|
||||
new_entry->need_erase = (image_size == OTA_WITH_SEQUENTIAL_WRITES);
|
||||
*out_handle = new_entry->handle;
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -203,8 +199,22 @@ esp_err_t esp_ota_write(esp_ota_handle_t handle, const void *data, size_t size)
|
||||
// find ota handle in linked list
|
||||
for (it = LIST_FIRST(&s_ota_ops_entries_head); it != NULL; it = LIST_NEXT(it, entries)) {
|
||||
if (it->handle == handle) {
|
||||
// must erase the partition before writing to it
|
||||
assert(it->erased_size > 0 && "must erase the partition before writing to it");
|
||||
if (it->need_erase) {
|
||||
// must erase the partition before writing to it
|
||||
uint32_t first_sector = it->wrote_size / SPI_FLASH_SEC_SIZE;
|
||||
uint32_t last_sector = (it->wrote_size + size) / SPI_FLASH_SEC_SIZE;
|
||||
|
||||
ret = ESP_OK;
|
||||
if ((it->wrote_size % SPI_FLASH_SEC_SIZE) == 0) {
|
||||
ret = esp_partition_erase_range(it->part, it->wrote_size, ((last_sector - first_sector) + 1) * SPI_FLASH_SEC_SIZE);
|
||||
} else if (first_sector != last_sector) {
|
||||
ret = esp_partition_erase_range(it->part, (first_sector + 1) * SPI_FLASH_SEC_SIZE, (last_sector - first_sector) * SPI_FLASH_SEC_SIZE);
|
||||
}
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (it->wrote_size == 0 && it->partial_bytes == 0 && size > 0 && data_bytes[0] != ESP_IMAGE_HEADER_MAGIC) {
|
||||
ESP_LOGE(TAG, "OTA image has invalid magic byte (expected 0xE9, saw 0x%02x)", data_bytes[0]);
|
||||
return ESP_ERR_OTA_VALIDATE_FAILED;
|
||||
@@ -270,7 +280,7 @@ esp_err_t esp_ota_write_with_offset(esp_ota_handle_t handle, const void *data, s
|
||||
for (it = LIST_FIRST(&s_ota_ops_entries_head); it != NULL; it = LIST_NEXT(it, entries)) {
|
||||
if (it->handle == handle) {
|
||||
// must erase the partition before writing to it
|
||||
assert(it->erased_size > 0 && "must erase the partition before writing to it");
|
||||
assert(it->need_erase == 0 && "must erase the partition before writing to it");
|
||||
|
||||
/* esp_ota_write_with_offset is used to write data in non contiguous manner.
|
||||
* Hence, unaligned data(less than 16 bytes) cannot be cached if flash encryption is enabled.
|
||||
@@ -310,7 +320,7 @@ esp_err_t esp_ota_end(esp_ota_handle_t handle)
|
||||
/* 'it' holds the ota_ops_entry_t for 'handle' */
|
||||
|
||||
// esp_ota_end() is only valid if some data was written to this handle
|
||||
if ((it->erased_size == 0) || (it->wrote_size == 0)) {
|
||||
if (it->wrote_size == 0) {
|
||||
ret = ESP_ERR_INVALID_ARG;
|
||||
goto cleanup;
|
||||
}
|
||||
|
@@ -29,6 +29,7 @@ extern "C"
|
||||
#endif
|
||||
|
||||
#define OTA_SIZE_UNKNOWN 0xffffffff /*!< Used for esp_ota_begin() if new image size is unknown */
|
||||
#define OTA_WITH_SEQUENTIAL_WRITES 0xfffffffe /*!< Used for esp_ota_begin() if new image size is unknown and erase can be done in incremental manner (assuming write operation is in continuous sequence) */
|
||||
|
||||
#define ESP_ERR_OTA_BASE 0x1500 /*!< Base error code for ota_ops api */
|
||||
#define ESP_ERR_OTA_PARTITION_CONFLICT (ESP_ERR_OTA_BASE + 0x01) /*!< Error if request was to write or erase the current running partition */
|
||||
|
@@ -30,6 +30,7 @@ typedef esp_err_t(*http_client_init_cb_t)(esp_http_client_handle_t);
|
||||
typedef struct {
|
||||
const esp_http_client_config_t *http_config; /*!< ESP HTTP client configuration */
|
||||
http_client_init_cb_t http_client_init_cb; /*!< Callback after ESP HTTP client is initialised */
|
||||
bool bulk_flash_erase; /*!< Erase entire flash partition during initialization. By default flash partition is erased during write operation and in chunk of 4K sector size */
|
||||
} esp_https_ota_config_t;
|
||||
|
||||
#define ESP_ERR_HTTPS_OTA_BASE (0x9000)
|
||||
|
@@ -39,6 +39,7 @@ struct esp_https_ota_handle {
|
||||
size_t ota_upgrade_buf_size;
|
||||
int binary_file_len;
|
||||
esp_https_ota_state state;
|
||||
bool bulk_flash_erase;
|
||||
};
|
||||
|
||||
typedef struct esp_https_ota_handle esp_https_ota_t;
|
||||
@@ -207,7 +208,7 @@ esp_err_t esp_https_ota_begin(esp_https_ota_config_t *ota_config, esp_https_ota_
|
||||
goto http_cleanup;
|
||||
}
|
||||
https_ota_handle->ota_upgrade_buf_size = alloc_size;
|
||||
|
||||
https_ota_handle->bulk_flash_erase = ota_config->bulk_flash_erase;
|
||||
https_ota_handle->binary_file_len = 0;
|
||||
*handle = (esp_https_ota_handle_t)https_ota_handle;
|
||||
https_ota_handle->state = ESP_HTTPS_OTA_BEGIN;
|
||||
@@ -280,9 +281,10 @@ esp_err_t esp_https_ota_perform(esp_https_ota_handle_t https_ota_handle)
|
||||
|
||||
esp_err_t err;
|
||||
int data_read;
|
||||
const int erase_size = handle->bulk_flash_erase ? OTA_SIZE_UNKNOWN : OTA_WITH_SEQUENTIAL_WRITES;
|
||||
switch (handle->state) {
|
||||
case ESP_HTTPS_OTA_BEGIN:
|
||||
err = esp_ota_begin(handle->update_partition, OTA_SIZE_UNKNOWN, &handle->update_handle);
|
||||
err = esp_ota_begin(handle->update_partition, erase_size, &handle->update_handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err));
|
||||
return err;
|
||||
|
@@ -183,7 +183,7 @@ static void ota_example_task(void *pvParameter)
|
||||
|
||||
image_header_was_checked = true;
|
||||
|
||||
err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
|
||||
err = esp_ota_begin(update_partition, OTA_WITH_SEQUENTIAL_WRITES, &update_handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err));
|
||||
http_cleanup(client);
|
||||
|
Reference in New Issue
Block a user