@@ -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+
392417UpdateClass Update;
0 commit comments