@@ -203,14 +203,22 @@ bool UpdateClass::_writeBuffer(){
203
203
if (!_progress && _progress_callback) {
204
204
_progress_callback (0 , _size);
205
205
}
206
- if (!ESP.partitionEraseRange (_partition, _progress, SPI_FLASH_SEC_SIZE)){
207
- _abort (UPDATE_ERROR_ERASE);
208
- return false ;
206
+ bool block_erase = (_size - _progress >= SPI_FLASH_BLOCK_SIZE) && ((_partition->address + _progress) % SPI_FLASH_BLOCK_SIZE == 0 ); // if it's the block boundary, than erase the whole block from here
207
+ bool part_head_sectors = _partition->address % SPI_FLASH_BLOCK_SIZE && (_progress < SPI_FLASH_BLOCK_SIZE); // sector belong to unaligned partition heading block
208
+ bool part_tail_sectors = _partition->address + _progress > (_partition->address + _size) / SPI_FLASH_BLOCK_SIZE * SPI_FLASH_BLOCK_SIZE; // sector belong to unaligned partition tailing block
209
+ if (block_erase || part_head_sectors || part_tail_sectors){
210
+ if (!ESP.partitionEraseRange (_partition, _progress, block_erase ? SPI_FLASH_BLOCK_SIZE : SPI_FLASH_SEC_SIZE)){
211
+ _abort (UPDATE_ERROR_ERASE);
212
+ return false ;
213
+ }
209
214
}
210
- if (!ESP.partitionWrite (_partition, _progress + skip, (uint32_t *)_buffer + skip/sizeof (uint32_t ), _bufferLen - skip)) {
215
+
216
+ // try to skip empty blocks on unecrypted partitions
217
+ 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)) {
211
218
_abort (UPDATE_ERROR_WRITE);
212
219
return false ;
213
220
}
221
+
214
222
// restore magic or md5 will fail
215
223
if (!_progress && _command == U_FLASH){
216
224
_buffer[0 ] = ESP_IMAGE_HEADER_MAGIC;
@@ -389,4 +397,20 @@ const char * UpdateClass::errorString(){
389
397
return _err2str (_error);
390
398
}
391
399
400
+ bool UpdateClass::_chkDataInBlock (const uint8_t *data, size_t len) const {
401
+ // check 32-bit aligned blocks only
402
+ if (!len || len % sizeof (uint32_t ))
403
+ return true ;
404
+
405
+ size_t dwl = len / sizeof (uint32_t );
406
+
407
+ do {
408
+ if (*(uint32_t *)data ^ 0xffffffff ) // for SPI NOR flash empty blocks are all one's, i.e. filled with 0xff byte
409
+ return true ;
410
+
411
+ data += sizeof (uint32_t );
412
+ } while (--dwl);
413
+ return false ;
414
+ }
415
+
392
416
UpdateClass Update;
0 commit comments