espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.34k stars 7.2k forks source link

esp_ota_write could erase SPI Flash block size instead of sector size (IDFGH-13411) #14318

Open bryghtlabs-richard opened 1 month ago

bryghtlabs-richard commented 1 month ago

Is your feature request related to a problem?

I'd like my OTA firmware updates to be faster. I've found OTA_SIZE_UNKNOWN to be faster than OTA_WITH_SEQUENTIAL_WRITES on my system. Testing shows my flash's block-erase may be slower than sector-erase but per-byte block-erase is much faster.

Describe the solution you'd like.

When updating with OTA_WITH_SEQUENTIAL_WRITES, esp_ota_write() should use block-erase as long as the partition is large enough and the current write position is suitably sized and aligned with the partition boundaries.

Describe alternatives you've considered.

No response

Additional context.

Esptool's stub loader does something very similar.

Please consider this a low-priority request. I might also get to it.

Samples from 3.2MB firmware download over TLS:

Approach Time
OTA_WITH_SEQUENTIAL_WRITES 62s
OTA_SIZE_UNKNOWN 31s
Prototype hack 23s

Over HTTPS we can specify the size to get best erase+programming time. However, over BLE, I have to use OTA_WITH_SEQUENTIAL_WRITES to prevent loss of connection due to iOS BLE timeouts during bulk partition erase, so that's why I'm interested in improving it.

mahavirj commented 1 month ago

@bryghtlabs-richard

Thought process while adding the erase during write (sequential writes) feature was to:

  1. Improve the non-IRAM resident interrupt responsiveness by keeping the flash cache disabled for smaller duration
  2. Manage erase operation length based on the size of buffer passed to esp_ota_write API. esp_partition_erase_range does optimize the erase operation to block, sector level erase, based on the length supplied.

IMO, replicating the erase operation optimization at app_update layer seems un-necessary and could introduce additional code complexity. This feature in turn must also be configurable because of point (1) that I mentioned above.

Testing shows my flash's block-erase may be slower than sector-erase but per-byte block-erase is much faster.

Could you please elaborate on what you mean by per-byte block-erase here?

Is it possible to share more information on the prototype hack that you mentioned above?

bryghtlabs-richard commented 1 month ago

@mahavirj,

R: Testing shows my flash's block-erase may be slower than sector-erase but per-byte block-erase is much faster. M: Could you please elaborate on what you mean by per-byte block-erase here?

I think I explained it poorly. 64KB block-erase is slower than 4KB sector erase, but it is not (64K/4K) times slower, so on average, block-erase is faster per-byte. Example from IS25LP032 datasheet, section 9.5 AC characteristics, shows block erase to be 2.4x the rate of sector erase:

Operation Size TypicalTime TypicalBytePerSecond
Sector Erase 4KB 45ms 89kB/s
Block Erase 32KB 150ms 213kB/s
Block Erase 64KB 300ms 213kB/s

Is it possible to share more information on the prototype hack that you mentioned above?

Sure! Please see: https://github.com/bryghtlabs-richard/esp-idf/tree/perf/ota-erase

...esp_partition_erase_range does optimize the erase operation to block, sector level erase, based on the length supplied.

In my cases, the buffer passed to esp_ota_write() is not large enough to trigger a block-erase. If the buffer were large enough, there's some risk it would not be suitably aligned either. My prototype patch changes esp_ota_write() , so that when an erase is needed before a write, and the partition is large enough, OTA will extend the call to esp_partition_erase_range() to end on a block-boundary. This way fewer, faster erase operations are used.