Skip to content

Commit 408578a

Browse files
authored
Merge pull request #1 from sebromero/nanoBLwithSD
Refactor the updaters back into one sketch
2 parents a4a984d + e1f3665 commit 408578a

File tree

6 files changed

+240
-301
lines changed

6 files changed

+240
-301
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
/*
2+
* This sketch allows to support Soft Devices on the Arduino Nano 33 BLE (Sense).
3+
*
4+
* To be able to support Soft Devices, the bootloader first needs to be updated.
5+
* The new bootloader is fully backwards compatible with standard sketches.
6+
* -----------------------------------------------------------------------
7+
*
8+
* INSTRUCTIONS
9+
*
10+
* 1) Upload this sketch on the Nano 33 BLE to download the new bootloader into the flash.
11+
* You can choose whether to update only the bootloader or the bootloader plus SoftDevice.
12+
* Make a choice through the Serial monitor.
13+
*
14+
* 2) After flashing the bootloader the sketch asks if you want to upload the SoftDevice.
15+
* This is required for the OpenMV firmware to work.
16+
* After completion, the board will reboot and enter the bootloader mode.
17+
*
18+
* 3) Now you can upload a sketch that uses the SoftDevice at 0x26000, using the following bossac command
19+
*
20+
* /path/to/bossac -d --port=yourPort --offset=0x16000 -U -i -e -w /path/to/sketch.bin -R
21+
*
22+
* Or you can still upload a standard sketch from the IDE at 0x10000. This will of course overwrite the SoftDevice.
23+
* So if you want to run a SoftDevice-related sketch, always remember to upload this sketch before and re-flash the SoftDevice.
24+
*
25+
* To create a custom SoftDevice follow this procedure:
26+
*
27+
* 1) Convert your SoftDevice binary to a SoftDevice.h .
28+
* The nRF5-SDK website provides a SoftDevice.hex, so run the following commands:
29+
*
30+
* objcopy --input-target=ihex --output-target=binary --gap-fill 0xff SoftDevice.hex SoftDevice.bin
31+
* xxd -i SoftDevice.bin > SoftDevice.h
32+
*
33+
* 2) Copy the content of the generated header file to SoftDevice.h
34+
*
35+
* 3) Run this sketch again and flash the SoftDevice.
36+
*/
37+
38+
#include "FlashIAP.h"
39+
#include "MBR.h"
40+
#include "bootloader.h"
41+
#include "nrf_nvmc.h"
42+
#include "SoftDevice.h"
43+
44+
#define SOFTDEVICE_ADDR (0xA0000)
45+
#define SOFTDEVICE_INFO_ADDR (0xFF000)
46+
#define MBR_ADDR (0x0)
47+
#define BOOTLOADER_ADDR (0xE0000)
48+
#define UICR_BOOT_ADDR (0x10001014)
49+
50+
#define BOOTLOADER_CRC 0x5E797B91
51+
#define BOOTLOADER_SIZE nano33_bootloader_hex_len
52+
const unsigned int magic = 0x5f27a93d;
53+
54+
mbed::FlashIAP flash;
55+
56+
bool hasLatestBootloader(){
57+
//Compute bootloader CRC32
58+
uint32_t crc32 = getCurrentBootloaderCrc();
59+
return crc32 == BOOTLOADER_CRC;
60+
}
61+
62+
bool getUserConfirmation(){
63+
while (true){
64+
if (Serial.available()){
65+
char choice = Serial.read();
66+
switch (choice){
67+
case 'y':
68+
case 'Y':
69+
return true;
70+
case 'n':
71+
case 'N':
72+
return false;
73+
default:
74+
continue;
75+
}
76+
}
77+
}
78+
}
79+
80+
void applyUpdate(uint32_t address, const unsigned char payload[], long len, uint32_t bin_pointer = 0) {
81+
uint32_t flash_pointer = 0;
82+
const uint32_t page_size = flash.get_page_size();
83+
char *page_buffer = new char[page_size];
84+
uint32_t addr = address;
85+
86+
uint32_t sector_size = flash.get_sector_size(addr);
87+
uint32_t next_sector = addr + sector_size;
88+
bool sector_erased = false;
89+
size_t pages_flashed = 0;
90+
uint32_t percent_done = 0;
91+
92+
while (true) {
93+
94+
if (flash_pointer >= len) {
95+
break;
96+
}
97+
98+
flash.erase(addr + flash_pointer, sector_size);
99+
100+
if ((len - flash_pointer) < sector_size) {
101+
sector_size = len - flash_pointer;
102+
}
103+
104+
// Program page
105+
flash.program(&payload[bin_pointer], addr + flash_pointer, sector_size);
106+
Serial.print("Flash Address = ");
107+
Serial.println(addr + flash_pointer, HEX);
108+
109+
bin_pointer = bin_pointer + sector_size;
110+
flash_pointer = flash_pointer + sector_size;
111+
112+
uint32_t percent_done = flash_pointer * 100 / len;
113+
Serial.println("Flashed " + String(percent_done) + "%");
114+
}
115+
Serial.println();
116+
117+
delete[] page_buffer;
118+
}
119+
120+
void updateBootloader(){
121+
Serial.println("This sketch modifies the Nano33 bootloader to support Soft Devices.");
122+
Serial.println();
123+
124+
flash.init();
125+
126+
Serial.println("Flashing MBR...");
127+
applyUpdate(MBR_ADDR, MBR_bin, MBR_bin_len);
128+
129+
Serial.println("Flashing bootloader...");
130+
applyUpdate(BOOTLOADER_ADDR, nano33_bootloader_hex, nano33_bootloader_hex_len);
131+
132+
Serial.print("Bootloader 32bit CRC is: ");
133+
uint32_t crc32 = getTargetBootloaderCrc();
134+
Serial.println(crc32, HEX);
135+
136+
Serial.println("Writing in UICR memory the address of the new bootloader...");
137+
nrf_nvmc_write_word(UICR_BOOT_ADDR, BOOTLOADER_ADDR);
138+
139+
flash.deinit();
140+
141+
Serial.println();
142+
Serial.println("Bootloader update successfully completed!\n");
143+
}
144+
145+
void updateSoftDevice(){
146+
flash.init();
147+
148+
Serial.println("Storing SoftDevice length info at 0xFF000...");
149+
writeSoftDeviceLen(SOFTDEVICE_INFO_ADDR);
150+
151+
Serial.println("Flashing SoftDevice...");
152+
applyUpdate(SOFTDEVICE_ADDR, Softdevice_bin, Softdevice_bin_len - 4096, 4096);
153+
154+
flash.deinit();
155+
156+
Serial.println();
157+
Serial.println("SoftDevice update complete! The board is restarting...");
158+
NVIC_SystemReset();
159+
}
160+
161+
void setup() {
162+
Serial.begin(115200);
163+
while (!Serial) {}
164+
165+
if(!hasLatestBootloader()){
166+
Serial.println("Your bootloader version is outdated (update required for Soft Device support).");
167+
Serial.println("Would you like to update it? Y/N");
168+
169+
if(getUserConfirmation()){
170+
updateBootloader();
171+
}
172+
}
173+
174+
if(hasLatestBootloader()){
175+
Serial.println("Would you like to install the Soft Device (required for OpenMV)? Y/N");
176+
if(getUserConfirmation()){
177+
updateSoftDevice();
178+
}
179+
}
180+
181+
Serial.println("Done. You may now disconnect the board.");
182+
}
183+
184+
uint32_t getTargetBootloaderCrc() {
185+
uint32_t mask = 0;
186+
uint32_t crc = 0xFFFFFFFF;
187+
uint32_t b = 0;
188+
uint8_t bootByte = 0;
189+
190+
int iterations = BOOTLOADER_SIZE;
191+
192+
for (int i=0; i<iterations; i=i+4) {
193+
b = 0;
194+
for (int j=0; j<4; j++) {
195+
mask = 0;
196+
bootByte = nano33_bootloader_hex[i+j];
197+
mask = mask + (uint32_t)bootByte;
198+
mask = mask << 8*j;
199+
b = b | mask;
200+
}
201+
crc = crc ^ b;
202+
}
203+
return crc;
204+
}
205+
206+
uint32_t getCurrentBootloaderCrc() {
207+
uint32_t b = 0;
208+
uint32_t crc = 0xFFFFFFFF;
209+
210+
int iterations = ceil(BOOTLOADER_SIZE/4);
211+
212+
int addr = BOOTLOADER_ADDR;
213+
214+
for (int i=0; i<iterations; i++) {
215+
//Read 32 bit from flash
216+
flash.read(&b, addr, sizeof(b));
217+
//Serial.println(b, HEX);
218+
//Update crc
219+
crc = crc ^ b;
220+
//Update pointer
221+
addr = addr + 4;
222+
}
223+
return crc;
224+
}
225+
226+
void writeSoftDeviceLen(uint32_t address) {
227+
uint32_t sd_addr = SOFTDEVICE_ADDR;
228+
flash.erase(address, 16);
229+
//Write flag to let Bootloader understand that SoftDevice binary must be moved
230+
flash.program(&magic, address, 4);
231+
//Write address where the SoftDevice binary has been written
232+
flash.program(&sd_addr, address + 4, 4);
233+
//Write SoftDevice binary length
234+
unsigned int sd_len = Softdevice_bin_len - 4096;
235+
flash.program(&sd_len, address + 8, 4);
236+
}
237+
238+
void loop() {
239+
delay(1000);
240+
}

libraries/Nano33_System/examples/Nano33_updateBootloader/Nano33_updateBootloader.ino

-137
This file was deleted.

0 commit comments

Comments
 (0)