@@ -224,6 +224,54 @@ void callBackExec(MenuItem* sender)
224224 menucallback (sender);
225225}
226226
227+ bool comparePartition (const esp_partition_t * src1, const esp_partition_t * src2, size_t length)
228+ {
229+ size_t lengthLeft = length;
230+ const size_t bufSize = SPI_FLASH_SEC_SIZE;
231+ std::unique_ptr<uint8_t []> buf1 (new uint8_t [bufSize]);
232+ std::unique_ptr<uint8_t []> buf2 (new uint8_t [bufSize]);
233+ uint32_t offset = 0 ;
234+ size_t i;
235+ while ( lengthLeft > 0 ) {
236+ size_t readBytes = (lengthLeft < bufSize) ? lengthLeft : bufSize;
237+ if (!ESP.flashRead (src1->address + offset, reinterpret_cast <uint32_t *>(buf1.get ()), (readBytes + 3 ) & ~3 )
238+ || !ESP.flashRead (src2->address + offset, reinterpret_cast <uint32_t *>(buf2.get ()), (readBytes + 3 ) & ~3 )) {
239+ return false ;
240+ }
241+ for (i = 0 ; i < readBytes; ++i) if (buf1[i] != buf2[i]) return false ;
242+ lengthLeft -= readBytes;
243+ offset += readBytes;
244+ }
245+ return true ;
246+ }
247+
248+ bool copyPartition (File* fs, const esp_partition_t * dst, const esp_partition_t * src, size_t length)
249+ {
250+ M5.Lcd .fillRect ( 110 , 112 , 100 , 20 , 0 );
251+ size_t lengthLeft = length;
252+ const size_t bufSize = SPI_FLASH_SEC_SIZE;
253+ std::unique_ptr<uint8_t []> buf (new uint8_t [bufSize]);
254+ uint32_t offset = 0 ;
255+ uint32_t progress = 0 , progressOld = 0 ;
256+ while ( lengthLeft > 0 ) {
257+ size_t readBytes = (lengthLeft < bufSize) ? lengthLeft : bufSize;
258+ if (!ESP.flashRead (src->address + offset, reinterpret_cast <uint32_t *>(buf.get ()), (readBytes + 3 ) & ~3 )
259+ || !ESP.flashEraseSector ((dst->address + offset) / bufSize)
260+ || !ESP.flashWrite (dst->address + offset, reinterpret_cast <uint32_t *>(buf.get ()), (readBytes + 3 ) & ~3 )) {
261+ return false ;
262+ }
263+ if (fs) fs->write (buf.get (), (readBytes + 3 ) & ~3 );
264+ lengthLeft -= readBytes;
265+ offset += readBytes;
266+ progress = 100 * offset / length;
267+ if (progressOld != progress) {
268+ progressOld = progress;
269+ M5.Lcd .progressBar ( 110 , 112 , 100 , 20 , progress);
270+ }
271+ }
272+ return true ;
273+ }
274+
227275// ======================================================================//
228276typedef std::vector<MenuItem*> vmi;
229277
@@ -237,13 +285,49 @@ void setup() {
237285 pinMode (NEOPIXEL_pin, OUTPUT);
238286 setNeoPixelAll (0 );
239287
240-
241288 if (digitalRead (BUTTON_A_PIN) == 0 ) {
242289 Serial.println (" Will Load menu binary" );
243290 updateFromFS (SD);
244291 ESP.restart ();
245292 }
246293
294+ const esp_partition_t *running = esp_ota_get_running_partition ();
295+ const esp_partition_t *nextupdate = esp_ota_get_next_update_partition (NULL );
296+ constexpr char * menubinfilename {MENU_BIN} ;
297+ if (!nextupdate)
298+ {
299+ M5.Lcd .setTextFont (4 );
300+ M5.Lcd .print (" ! WARNING !\r\n No OTA partition.\r\n Can't use SD-Updater." );
301+ delay (3000 );
302+ }
303+ else if (running && running->label [3 ] == ' 0' && nextupdate->label [3 ] == ' 1' )
304+ {
305+ M5.Lcd .setTextFont (2 );
306+ M5.Lcd .println (" LovyanLauncher on app0" );
307+ size_t sksize = ESP.getSketchSize ();
308+ if (!comparePartition (running, nextupdate, sksize))
309+ {
310+ bool flgSD = SD.begin ( TFCARD_CS_PIN );
311+ M5.Lcd .print (" copy to app1" );
312+ File dst;
313+ if (flgSD) {
314+ dst = (SD.open (menubinfilename, FILE_WRITE ));
315+ M5.Lcd .print (" and SD menu.bin" );
316+ }
317+ if (copyPartition ( flgSD ? &dst : NULL , nextupdate, running, sksize)) {
318+ M5.Lcd .println (" \r\n Done." );
319+ }
320+ if (flgSD) dst.close ();
321+ }
322+ SDUpdater::updateNVS ();
323+ M5.Lcd .println (" Rebooting app1..." );
324+ if (Update.canRollBack ()) {
325+ Update.rollBack ();
326+ ESP.restart ();
327+ }
328+ }
329+ M5.Lcd .fillScreen (0 );
330+
247331 M5ButtonDrawer::width = 106 ;
248332
249333 treeView.clientRect .x = 2 ;
0 commit comments