Skip to content

Commit 3af1ca4

Browse files
authored
Merge pull request #14 from bcmi-labs/dfu_qspi
Add DFU support for loading images on external QSPI
2 parents 7e98b4a + 3bfac54 commit 3af1ca4

File tree

15 files changed

+11082
-362
lines changed

15 files changed

+11082
-362
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ mbed_settings.py
1111
mbed_settings.pyc
1212
mbed_config.h
1313
*.hex
14-
*.pem
1514
mbed-os/*
15+
mbed-os/
1616
mcuboot/*

README.md

Lines changed: 26 additions & 331 deletions
Large diffs are not rendered by default.

assets/current-layout.png

55.5 KB
Loading

assets/nRF52840-mcuboot-map.png

-497 KB
Binary file not shown.

encrypt_keys.pem

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCwWzKpkTb6xQTJ
3+
R64n6Um8vpIT1wgVPMNJjWbGVmTENdfidbaLNXA4hrE+XXP1ESQvd7f+gxJXWjXn
4+
kZmKOqfTjWZbNbebHyVehxmpCQBLJTS9aapq+e1NC0bXOB4pHeNoprekXwBVedDz
5+
kDJhDFORCsdhEHbqJTRRnI/ZYnIv4W2ATfVwOHi3z+uEG4Q9jTfy9jPLH66wYCAW
6+
PZaKaM1NDRBlWiii1JaayntTGeuyPHAaJB34hr4uNm/pdsMzd84Psta56jbojCmV
7+
4jUQCtrwvKQXcEsVxnFlBQOPjx7I7j11sPId/PG5TdJ+NQTOMgXcFkSz+QXKG0ZX
8+
rMF2ExUVAgMBAAECggEAFolg/QhgpUU+Klatq84FLUiRNFXbY5NjRWf7hUcPE3/p
9+
+befP0Tx9VdJGTYqFlw9ao97BNxNILqXfuM9YsvCHKfKN8eykfE1/lF3dwF+dxvn
10+
FHmHXKpZp+nUALbcK9b086+ych/t0/6ANE/uEDbaCwP8nKvU9nEQsYk3XMlW3EVV
11+
O+mKr/3+PauAskwEVGUjInVXLRrV+wukoTKcEgI3kecUlsfTgOWO4NVuElsGjHT2
12+
6XumzhJUXGwE/rf1evk1Fi+s+ViqMAnVyx0wdtC4grSRMMLtgZmBe4ooBSgP2U39
13+
xuB6JF1Ffs/P0X112U+DIE2tYuBrYE4ie+/lUTp1QQKBgQDaoCzJYS7we14EYS1f
14+
GYJ+84TMKotItcvPZhRW2nL73IeIuojt878YtLxIU+G3esGvPO6LJAuTGxYOaTP5
15+
guAmOyWiajmde1cIA5uPtrVpe6W0Y3YdOZaPr8LAvyYTS2HFqQFaqUMbRzVb3y6q
16+
tBKzaihuNhsKe0K+hUyE8SmupQKBgQDOgSoMf0JRn3W2ayN/Bra1OEiMM9oWwJrd
17+
0lPxYszHgGWKqsYnvaHNTNfqMUkcTGb+5tnspRE9ZFzE0l2epz+W+comfoeffOsa
18+
RHPWSW7lSz2jNsVCWsPqervXDidLdM+2lqp8gCU5cz9q0CNCFU/w6S11Jh1eyC6N
19+
kPNZL/jxsQKBgHihQrUG84Brga/G8uLzT2a+9To2C05eSQux1m0p8aH4x6vwyNcK
20+
1BlMuErsRbIYgMAxTanmhKBxpJTlBXGZ/hX6MsTP+eRkBtx8KRx+AtEmEYNcEfME
21+
MIgtwbbagabJxDPtEbs1g7qMauu7VKOJ4nuuioptPjRlWKmJIXSFIKulAoGBALR5
22+
dgJOBevH7Nxsbi1J9MwUUHMXrfZMhgxvESXZLxb8Q8IY1e1Ncec2zUzDnh25OBp2
23+
Lub+rD53RAxPvbo2eQC9dcqGsojUZ7QhNwuESgLi6w+FgognQynd8eRVXko34IC2
24+
1HDSnbXD3xy+otHSRndJkozbrrdzRBw9HjBIGM1BAoGAQMqGduiOMMuWzKunwFgB
25+
zvq8++chO80jZiwEsB98wMYbKnqVX8j39znKkRBl0bOsHuZNpyXYriESUKu7DjXf
26+
2vMNsQmYnREqrPuMRqcrYK7KIAQBF9AaDFqtCxgNdFpBU/XlfgNwoM/V3Uz3VsSW
27+
ImMyIlKBPW83511QcseW+jg=
28+
-----END PRIVATE KEY-----

envie/ota.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020
#include "LittleFileSystem.h"
2121
#endif
2222

23-
#define ALL_IN_SD 1
24-
23+
static bool BlockTableLoaded = false;
2524
static BlockTableData block_info[2];
2625

2726
static void loadOTAData(void) {
@@ -92,7 +91,7 @@ static void loadOTAData(void) {
9291
block_info[SECONDARY_BLOCK_DEVICE].mbr_flag = 1;
9392

9493
block_info[SCRATCH_BLOCK_DEVICE].storage_type = INTERNAL_FLASH_OFFSET;
95-
block_info[SCRATCH_BLOCK_DEVICE].data_offset = 2;
94+
block_info[SCRATCH_BLOCK_DEVICE].data_offset = MCUBOOT_SCRATCH_START_ADDR;
9695
block_info[SCRATCH_BLOCK_DEVICE].update_size = MCUBOOT_SCRATCH_SIZE;
9796
block_info[SCRATCH_BLOCK_DEVICE].raw_type = INTERNAL_FLASH_FLAG;
9897
block_info[SCRATCH_BLOCK_DEVICE].raw_flag = 1;
@@ -367,29 +366,31 @@ static void initBlockTable(void) {
367366
*/
368367
mbed::BlockDevice* get_secondary_bd(void) {
369368

370-
initBlockTable();
369+
if(!BlockTableLoaded) {
370+
initBlockTable();
371+
BlockTableLoaded = true;
372+
}
371373

372374
if(block_info[SECONDARY_BLOCK_DEVICE].raw_flag) {
373375
return block_info[SECONDARY_BLOCK_DEVICE].log_bd;
374376
} else {
375377
return block_info[SECONDARY_BLOCK_DEVICE].file_bd;
376378
}
377-
378-
BOOT_LOG_ERR("Cannot define secondary Blockdevice Instance");
379-
return NULL;
380379
}
381380

382381

383382
mbed::BlockDevice* get_scratch_bd(void) {
384383

384+
if(!BlockTableLoaded) {
385+
initBlockTable();
386+
BlockTableLoaded = true;
387+
}
388+
385389
if(block_info[SCRATCH_BLOCK_DEVICE].raw_flag) {
386390
return block_info[SCRATCH_BLOCK_DEVICE].log_bd;;
387391
} else {
388392
return block_info[SCRATCH_BLOCK_DEVICE].file_bd;
389393
}
390-
391-
BOOT_LOG_ERR("Cannot define secondary Blockdevice Instance");
392-
return NULL;
393394
}
394395

395396
#endif

envie/target_init.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#endif
1313

1414
#define BOOTLOADER_CONFIG_MAGIC 0xA0
15-
#define BOOTLOADER_VERSION 22
15+
#define BOOTLOADER_VERSION 0
1616

1717
#define PORTENTA_USB_SPEED_HIGH 1
1818
#define PORTENTA_USB_SPEED_FULL 2

envie_dfu/usbd_desc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
#define USBD_PID 0x035B
3131
#define USBD_LANGID_STRING 0x409
3232
#define USBD_MANUFACTURER_STRING "Arduino SA"
33-
#define USBD_PRODUCT_HS_STRING "Envie H7 Bootloader"
34-
#define USBD_PRODUCT_FS_STRING "Envie H7 Bootloader"
33+
#define USBD_PRODUCT_HS_STRING "Portenta MCUBoot"
34+
#define USBD_PRODUCT_FS_STRING "Portenta MCUBoot"
3535
#define USBD_CONFIGURATION_HS_STRING "DFU Config"
3636
#define USBD_INTERFACE_HS_STRING "DFU Interface"
3737
#define USBD_CONFIGURATION_FS_STRING "DFU Config"

envie_dfu/usbd_dfu_flash.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,13 @@
2626
#include "target_init.h"
2727
#include "QSPIFBlockDevice.h"
2828
#include "FlashSimBlockDevice.h"
29+
#include "flash_map_backend/secondary_bd.h"
2930

3031
/* Private typedef ----------------------------------------------------------- */
3132
/* Private define ------------------------------------------------------------ */
32-
#define FLASH_DESC_STR "@Internal Flash /0x08000000/01*128Ka,15*128Kg"
33-
//#define OPTIONB_DESC_STR "@Option Bits /0x52002000/01*1Ka"
34-
#define QSPI_FLASH_DESC_STR "@External Flash /0x90000000/4096*4Kg"
33+
#define FLASH_DESC_STR "@Internal Flash 2MB /0x08000000/01*128Ka,15*128Kg"
34+
//#define BOOTLOADER_DESC_STR "@Option Bits /0x52002000/01*1Ka"
35+
#define QSPI_FLASH_DESC_STR "@External Flash 16MB /0x90000000/16*128Kg"
3536

3637
#define FLASH_ERASE_TIME (uint16_t)0
3738
#define FLASH_PROGRAM_TIME (uint16_t)0
@@ -52,7 +53,7 @@ uint16_t Flash_If_DeInit(void);
5253
uint16_t Flash_If_GetStatus(uint32_t Add, uint8_t Cmd, uint8_t * buffer);
5354

5455
FlashIAP flash;
55-
QSPIFBlockDevice qspi_flash(PD_11, PD_12, PF_7, PD_13, PF_10, PG_6, QSPIF_POLARITY_MODE_1, 40000000);
56+
mbed::BlockDevice* dfu_secondary_bd = get_secondary_bd();
5657

5758
const uint32_t QSPIFLASH_BASE_ADDRESS = 0x90000000;
5859

@@ -74,8 +75,8 @@ bool Flash_If_Init_requested = false;
7475

7576
void init_Memories() {
7677
flash.init();
77-
qspi_flash.init();
78-
snprintf(BOOTLOADER_DESC_STR, sizeof(BOOTLOADER_DESC_STR), "@Bootloader version %d /0x00000000/0*4Kg", BOOTLOADER_VERSION);
78+
dfu_secondary_bd->init();
79+
snprintf(BOOTLOADER_DESC_STR, sizeof(BOOTLOADER_DESC_STR), "@MCUBoot version %d /0x00000000/0*4Kg", BOOTLOADER_VERSION);
7980
}
8081

8182
Thread writeThread(osPriorityHigh);
@@ -101,7 +102,7 @@ uint16_t Flash_If_Init(void)
101102
uint16_t Flash_If_DeInit(void)
102103
{
103104
flash.deinit();
104-
qspi_flash.deinit();
105+
dfu_secondary_bd->deinit();
105106
return 0;
106107
}
107108

@@ -118,7 +119,7 @@ uint16_t Flash_If_Erase(uint32_t Add)
118119
{
119120
if (isExternalFlash(Add)) {
120121
Add -= QSPIFLASH_BASE_ADDRESS;
121-
return qspi_flash.erase(Add, qspi_flash.get_erase_size(Add));
122+
return dfu_secondary_bd->erase(Add, dfu_secondary_bd->get_erase_size(Add));
122123
} else {
123124
return flash.erase(Add, flash.get_sector_size(Add));
124125
}
@@ -147,10 +148,10 @@ uint16_t Flash_If_Write(uint8_t * src, uint8_t * dest, uint32_t Len)
147148
{
148149
if (isExternalFlash((uint32_t)dest)) {
149150
dest -= QSPIFLASH_BASE_ADDRESS;
150-
if (Len < qspi_flash.get_erase_size(0)) {
151-
Len = qspi_flash.get_erase_size(0);
151+
if (Len < dfu_secondary_bd->get_erase_size(0)) {
152+
Len = dfu_secondary_bd->get_erase_size(0);
152153
}
153-
return qspi_flash.program(src, (uint32_t)dest, Len);
154+
return dfu_secondary_bd->program(src, (uint32_t)dest, Len);
154155
} else {
155156
uint8_t* srcCopy = (uint8_t*)malloc(Len);
156157
memcpy(srcCopy, src, Len);
@@ -177,8 +178,7 @@ uint8_t *Flash_If_Read(uint8_t * src, uint8_t * dest, uint32_t Len)
177178

178179
if (isExternalFlash((uint32_t)src)) {
179180
src -= QSPIFLASH_BASE_ADDRESS;
180-
181-
qspi_flash.read(dest, (uint32_t)src, Len);
181+
dfu_secondary_bd->read(dest, (uint32_t)src, Len);
182182
} else {
183183
for (i = 0; i < Len; i++)
184184
{

mbed-os.lib

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
https://github.com/bcmi-labs/mbed-os-h747/#217dd927510743655f7a609a7f3fb5b1834a806a
1+
https://github.com/bcmi-labs/mbed-os-h747/#aea3bc7eabf0063b5edc2f50348cfd4e6e24c17b

mcuboot.lib

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
https://github.com/bcmi-labs/mcuboot/#d46fa881317c3608b349028dd1c4f3fa2376c4bf
1+
https://github.com/bcmi-labs/mcuboot/#06b344015e753f6f9536a4019857a386259512ba

signing_keys.pem

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDTWNjk6BHDIpsg
3+
9RrlXp1Ty6+TuCf4jJiycdnFtly7eT3xSyQixLLxHcTyWdJbcqSYbPiYFysY7ny8
4+
Ob1iqWmzj4pXg7ZztEJXHE2fuAJvgeutat9RtYBnyE8jFb8xwrLCSnoViW3lVTrG
5+
cUSxZWISg/iH+48DnbvsF2f+dWbItEgYMRvPv0PtzqaKIjQswnGhr6ezJYaE6v9j
6+
tX/qX+4fiyRrCP1JW8pEQXn7szsb5W3PKE43EHP6QigJ/pC0jwz9W2fHj46sxxVt
7+
L31e43pAkzXf+UAMtmdSuQck3vseOcltUnrQ00TUr59mqYOnd0Z1ADzRSrfqLndF
8+
YG/xgdEhAgMBAAECggEAT4I6Potruzx2ncR39NhOWarkB6+dIe1KuL8KDU5YvpKT
9+
EgaRtp7HLtxjLkVKVOrhLxK3xwfYR83YkTsrm0VepZWXlurPJeInnvvf2/luuSJo
10+
VlpBX0zn3KNH2kwhHIhBlcRM/3MvK7qPnP4ZuJ8KcSrCwe2KVPLvMpdvoRPrsg8p
11+
lj8djsont+/8enzVkPmSs+w5pMd3r61ejRJyt2Nrm0lkHzETv0Upt43+1OLutUEm
12+
bwT5kdV/lq/n5npzBoqDjQH7qxowjwz2tGN+vIY+2m75MiScwMwxms+Jy93ueuem
13+
/Vkel7WtCV/Wss8gBHxmt+hfWD0ydEPBmJ5u1QHX0QKBgQDq97IgLNVN1mdFDz07
14+
tOn8TmmhOkt+Dkvq1uMOF8ct3NO6NzpKfFy09WrhqBDoXALf30tA30T7zBJJxwiL
15+
pIUNxAzt7f1RB1zgGw7J/at2shQhpPVG1Mk0WN1YHcxbbmB2dOR6OB4Jp66+sJkZ
16+
AXaskAIuIEngj06nChvlTFLYVQKBgQDmQ+KneG2wVeS+imIOuLVgYy51r/xdos/m
17+
bu22nRcVpTuu7wbE0pK71o0D2M1dvlbfDKmYyDlvOmSBYQmrjGTkLiuMycJMVgTR
18+
aL2PTDFdWsoXfVs5scZnKZFf5HKChZ5jv/Qvqm3uhpzNiXLvXyce+/rl85CfL91P
19+
/naAVH+RnQKBgCW1txq+10T0wgItXfB1KpBZrU444uDKPpjj//DFFCxiIoDiWDKY
20+
HvDT6mFo7b289qEjXxp8OsAGknDQxqhSsR/ydPjCl0Mn4Vn+PbNhSOF11xFHPi4t
21+
/FSwZmW78o5B+q1IOVr8IqX+CWeFRCzlNTygqBjrCbBGj6LzVmLIiws5AoGBAOD7
22+
GRyqFPpCojHtgauCm2zm20EPxxMx/dHXNpnDWQfEHtFoKAPs/oNbOQK2NMnQLI7Y
23+
j2iA0WU093hV+J3NmdI8rj5r71SogyKcJQI63syo5WYYDCcN5J1tRuYbjiqrJTuv
24+
FIXyDmEM024bStpI7S9f4iAFX5u5p5H+PYhbhx0dAoGBAOlj8Q45yaWlZerW8/jh
25+
Bx2zzieu3ybPg7zSy8v+dDqhck0MYrS5jU1jMOl0fHvTKbWKjbm9nqIeWeTMcJLB
26+
Fb6VyVF2PrwbPlOLVOs3uxcVUf8Z3GH8eDKlI/h9i2DgLAXA2GjQ7VwB19q53zxp
27+
cEjsBvtBtVD6R9DXt7iu6v3x
28+
-----END PRIVATE KEY-----

tools/PortentaMCUBootQSPIFormat.ino renamed to tools/PortentaMCUBootQSPIFormat/PortentaMCUBootQSPIFormat.ino

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ void create_scratch_file(void) {
2626
int size=0;
2727

2828
while(size < 128 * 1024) {
29-
fwrite(buffer, 128, 1, fp);
29+
int ret = fwrite(buffer, 128, 1, fp);
30+
if(ret != 1) {
31+
Serial.println("Error writing scratch file");
32+
break;
33+
}
3034
size += 128;
3135
}
3236

@@ -39,7 +43,11 @@ void create_update_file(void) {
3943
int size=0;
4044

4145
while(size < 768 * 1024) {
42-
fwrite(buffer, 128, 1, fp);
46+
int ret = fwrite(buffer, 128, 1, fp);
47+
if(ret != 1) {
48+
Serial.println("Error writing scratch file");
49+
break;
50+
}
4351
size += 128;
4452
}
4553

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
#include "FlashIAP.h"
2+
#include "bootloader.h"
3+
4+
#ifndef CORE_CM7
5+
#error Update the bootloader by uploading the sketch to the M7 core instead of the M4 core.
6+
#endif
7+
8+
#define BOOTLOADER_ADDR (0x8000000)
9+
mbed::FlashIAP flash;
10+
11+
uint32_t bootloader_data_offset = 0x1F000;
12+
uint8_t* bootloader_data = (uint8_t*)(BOOTLOADER_ADDR + bootloader_data_offset);
13+
14+
void setup() {
15+
Serial.begin(115200);
16+
while (!Serial) {}
17+
18+
uint8_t currentBootloaderVersion = bootloader_data[1];
19+
uint8_t availableBootloaderVersion = (mcuboot_bin + bootloader_data_offset)[1];
20+
21+
Serial.println("Magic Number (validation): " + String(bootloader_data[0], HEX));
22+
Serial.println("Bootloader version: " + String(currentBootloaderVersion));
23+
Serial.println("Clock source: " + getClockSource(bootloader_data[2]));
24+
Serial.println("USB Speed: " + getUSBSpeed(bootloader_data[3]));
25+
Serial.println("Has Ethernet: " + String(bootloader_data[4] == 1 ? "Yes" : "No"));
26+
Serial.println("Has WiFi module: " + String(bootloader_data[5] == 1 ? "Yes" : "No"));
27+
Serial.println("RAM size: " + String(bootloader_data[6]) + " MB");
28+
Serial.println("QSPI size: " + String(bootloader_data[7]) + " MB");
29+
Serial.println("Has Video output: " + String(bootloader_data[8] == 1 ? "Yes" : "No"));
30+
Serial.println("Has Crypto chip: " + String(bootloader_data[9] == 1 ? "Yes" : "No"));
31+
32+
if (availableBootloaderVersion > currentBootloaderVersion) {
33+
Serial.print("\nA new bootloader version is available: v" + String(availableBootloaderVersion));
34+
Serial.println(" (Your version: v" + String(currentBootloaderVersion) + ")");
35+
Serial.println("Do you want to update the bootloader? Y/[n]");
36+
} else if(availableBootloaderVersion < currentBootloaderVersion){
37+
Serial.println("\nA newer bootloader version is already installed: v" + String(currentBootloaderVersion));
38+
Serial.println("Do you want to downgrade the bootloader to v" + String(availableBootloaderVersion) + "? Y/[n]");
39+
} else {
40+
Serial.println("\nThe latest version of the bootloader is already installed (v" + String(currentBootloaderVersion) + ").");
41+
Serial.println("Do you want to update the bootloader anyway? Y/[n]");
42+
}
43+
44+
bool confirmation = false;
45+
while (confirmation == false) {
46+
if (Serial.available()) {
47+
char choice = Serial.read();
48+
switch (choice) {
49+
case 'y':
50+
case 'Y':
51+
applyUpdate(BOOTLOADER_ADDR);
52+
confirmation = true;
53+
break;
54+
case 'n':
55+
case 'N':
56+
confirmation = true;
57+
break;
58+
default:
59+
continue;
60+
}
61+
}
62+
}
63+
}
64+
65+
String getUSBSpeed(uint8_t flag) {
66+
switch (flag){
67+
case 1:
68+
return "USB 2.0/Hi-Speed (480 Mbps)";
69+
case 2:
70+
return "USB 1.1/Full-Speed (12 Mbps)";
71+
default:
72+
return "N/A";
73+
}
74+
}
75+
76+
String getClockSource(uint8_t flag) {
77+
switch (flag){
78+
case 0x8:
79+
return "External oscillator";
80+
case 0x4:
81+
return "External crystal";
82+
case 0x2:
83+
return "Internal clock";
84+
default:
85+
return "N/A";
86+
}
87+
}
88+
89+
void applyUpdate(uint32_t address) {
90+
long len = mcuboot_bin_len;
91+
92+
flash.init();
93+
94+
const uint32_t page_size = flash.get_page_size();
95+
char *page_buffer = new char[page_size];
96+
uint32_t addr = address;
97+
uint32_t next_sector = addr + flash.get_sector_size(addr);
98+
bool sector_erased = false;
99+
size_t pages_flashed = 0;
100+
uint32_t percent_done = 0;
101+
102+
while (true) {
103+
104+
if (page_size * pages_flashed > len) {
105+
break;
106+
}
107+
108+
// Erase this page if it hasn't been erased
109+
if (!sector_erased) {
110+
flash.erase(addr, flash.get_sector_size(addr));
111+
sector_erased = true;
112+
}
113+
114+
// Program page
115+
flash.program(&mcuboot_bin[page_size * pages_flashed], addr, page_size);
116+
117+
addr += page_size;
118+
if (addr >= next_sector) {
119+
next_sector = addr + flash.get_sector_size(addr);
120+
sector_erased = false;
121+
}
122+
123+
if (++pages_flashed % 3 == 0) {
124+
uint32_t percent_done_new = page_size * pages_flashed * 100 / len;
125+
if (percent_done != percent_done_new) {
126+
percent_done = percent_done_new;
127+
Serial.println("Flashed " + String(percent_done) + "%");
128+
}
129+
}
130+
}
131+
Serial.println("Flashed 100%");
132+
133+
delete[] page_buffer;
134+
135+
flash.deinit();
136+
Serial.println("Bootloader update complete. You may now disconnect the board.");
137+
}
138+
139+
void loop() {
140+
delay(1000);
141+
}

0 commit comments

Comments
 (0)