8000 UpdateClass - speedup flash erase/writes (#7002) · hathach/arduino-esp32@4647809 · GitHub
[go: up one dir, main page]

Skip to content

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 4647809

Browse files
authored
UpdateClass - speedup flash erase/writes (espressif#7002)
- on flash writes try to use large block erase - skip writing empty blocks of data after erase - more accurate block calculations
1 parent 3cb73dc commit 4647809

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

libraries/Update/src/Update.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828

2929
#define ENCRYPTED_BLOCK_SIZE 16
3030

31+
#define SPI_SECTORS_PER_BLOCK 16 // usually large erase block is 32k/64k
32+
#define SPI_FLASH_BLOCK_SIZE (SPI_SECTORS_PER_BLOCK*SPI_FLASH_SEC_SIZE)
33+
3134
class UpdateClass {
3235
public:
3336
typedef std::function<void(size_t, size_t)> THandlerFunction_Progress;
@@ -166,6 +169,7 @@ class UpdateClass {
166169
bool _verifyHeader(uint8_t data);
167170
bool _verifyEnd();
168171
bool _enablePartition(const esp_partition_t* partition);
172+
bool _chkDataInBlock(const uint8_t *data, size_t len) const; // check if block contains any data or is empty
169173

170174

171175
uint8_t _error;

libraries/Update/src/Updater.cpp

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,14 +203,23 @@ bool UpdateClass::_writeBuffer(){
203203
if (!_progress && _progress_callback) {
204204
_progress_callback(0, _size);
205205
}
206-
if(!ESP.partitionEraseRange(_partition, _progress, SPI_FLASH_SEC_SIZE)){
207-
_abort(UPDATE_ERROR_ERASE);
208-
return false;
206+
size_t offset = _partition->address + _progress;
207+
bool block_erase = (_size - _progress >= SPI_FLASH_BLOCK_SIZE) && (offset % SPI_FLASH_BLOCK_SIZE == 0); // if it's the block boundary, than erase the whole block from here
208+
bool part_head_sectors = _partition->address % SPI_FLASH_BLOCK_SIZE && offset < (_partition->address / SPI_FLASH_BLOCK_SIZE + 1) * SPI_FLASH_BLOCK_SIZE; // sector belong to unaligned partition heading block
209+
bool part_tail_sectors = offset >= (_partition->address + _size) / SPI_FLASH_BLOCK_SIZE * SPI_FLASH_BLOCK_SIZE; // sector belong to unaligned partition tailing block
210+
if (block_erase || part_head_sectors || part_tail_sectors){
211+
if(!ESP.partitionEraseRange(_partition, _progress, block_erase ? SPI_FLASH_BLOCK_SIZE : SPI_FLASH_SEC_SIZE)){
212+
_abort(UPDATE_ERROR_ERASE);
213+
return false;
214+
}
209215
}
210-
if (!ESP.partitionWrite(_partition, _progress + skip, (uint32_t*)_buffer + skip/sizeof(uint32_t), _bufferLen - skip)) {
216+
217+
// try to skip empty blocks on unecrypted partitions
218+
if ((_partition->encrypted || _chkDataInBlock(_buffer + skip/sizeof(uint32_t), _bufferLen - skip)) && !ESP.partitionWrite(_partition, _progress + skip, (uint32_t*)_buffer + skip/sizeof(uint32_t), _bufferLen - skip)) {
211219
_abort(UPDATE_ERROR_WRITE);
212220
return false;
213221
}
222+
214223
//restore magic or md5 will fail
215224
if(!_progress && _command == U_FLASH){
216225
_buffer[0] = ESP_IMAGE_HEADER_MAGIC;
@@ -389,4 +398,20 @@ const char * UpdateClass::errorString(){
389398
return _err2str(_error);
390399
}
391400

401+
bool UpdateClass::_chkDataInBlock(const uint8_t *data, size_t len) const {
402+
// check 32-bit aligned blocks only
403+
if (!len || len % sizeof(uint32_t))
404+
return true;
405+
406+
size_t dwl = len / sizeof(uint32_t);
407+
408+
do {
409+
if (*(uint32_t*)data ^ 0xffffffff) // for SPI NOR flash empty blocks are all one's, i.e. filled with 0xff byte
410+
return true;
411+
412+
data += sizeof(uint32_t);
413+
} while (--dwl);
414+
return false;
415+
}
416+
392417
UpdateClass Update;

0 commit comments

Comments
 (0)
0