Skip to content

Commit 0f502c7

Browse files
authored
Merge pull request #549 from giulcioffi/SBU
Add Second Stage Bootloader (SBU) for MKRNB 1500
2 parents 3f464a0 + 6e4b0ac commit 0f502c7

File tree

10 files changed

+2955
-1
lines changed

10 files changed

+2955
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#include <MKRNB.h>
2+
#include <SBU.h>
3+
4+
static char const BINARY[] =
5+
{
6+
#include "Binary.h"
7+
};
8+
9+
static char const CHECK_FILE[] =
10+
{
11+
"OK"
12+
};
13+
14+
static constexpr char CHECK_FILE_NAME[] = "UPDATE.OK";
15+
16+
NBFileUtils fileUtils;
17+
bool update_available = false;
18+
19+
void setup() {
20+
Serial.begin(9600);
21+
while(!Serial) { }
22+
23+
unsigned long const start = millis();
24+
for(unsigned long now = millis(); !Serial && ((now - start) < 5000); now = millis()) { };
25+
26+
Serial.print("Accessing SARA Filesystem... ");
27+
if(!fileUtils.begin(false)) {
28+
Serial.println("failed.");
29+
return;
30+
31+
}
32+
Serial.println("OK");
33+
Serial.print("Writing \"UPDATE.BIN\" ... ");
34+
35+
uint32_t bytes_to_write = sizeof(BINARY);
36+
Serial.print("Size of BINARY: ");
37+
Serial.println(bytes_to_write);
38+
int index = 0;
39+
bool append = false;
40+
int new_bytes = 0;
41+
//int bytes_written = 0;
42+
43+
for (int i=0; i<(bytes_to_write/512); i++) {
44+
auto new_bytes = fileUtils.downloadFile("UPDATE.BIN", BINARY+index, 512, append);
45+
if (new_bytes != 512) {
46+
Serial.print("New_bytes = ");
47+
Serial.print(new_bytes);
48+
Serial.println(" != 512");
49+
}
50+
index = index + new_bytes;
51+
append = true;
52+
}
53+
if ((bytes_to_write%512)!=0) {
54+
auto new_bytes = fileUtils.downloadFile("UPDATE.BIN", BINARY+index, bytes_to_write%512, append);
55+
if (new_bytes != bytes_to_write%512) {
56+
Serial.print("Last bytes read = ");
57+
Serial.print(new_bytes);
58+
Serial.print(". They should have been ");
59+
Serial.println(bytes_to_write%512);
60+
}
61+
index = index + new_bytes;
62+
}
63+
64+
if(index != bytes_to_write) {
65+
Serial.print("Written only ");
66+
Serial.println(index); //bytes_written
67+
Serial.print(bytes_to_write);
68+
Serial.println(" should have been written. System is restarting...");
69+
delay(100);
70+
NVIC_SystemReset();
71+
72+
} else {
73+
Serial.print("Download complete! ");
74+
Serial.print(index);
75+
Serial.println(" bytes written");
76+
77+
auto status = 0;
78+
while (status != 2) {
79+
status = fileUtils.createFile(CHECK_FILE_NAME, CHECK_FILE, 2);
80+
delay(100);
81+
}
82+
83+
Serial.println("Please type \"restart\" to apply the update");
84+
update_available = true;
85+
}
86+
87+
}
88+
89+
void loop() {
90+
if (update_available == true) {
91+
String command = Serial.readStringUntil('\n');
92+
if (command.indexOf("restart") >= 0) {
93+
NVIC_SystemReset();
94+
}
95+
}
96+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
Usage
3+
This example demonstrates how to use the SAMD SBU library to update a
4+
sketch on any Arduino MKR board via the storage on the SARA-R410M module.
5+
This sketch prints out the current date and time.
6+
Steps to update sketch:
7+
1) Upload this sketch or another sketch that includes the SBU library
8+
2) Update the sketch as desired. For this example the sketch prints out
9+
the compiled date and time.
10+
3) In the IDE select: Sketch -> Export compiled Binary
11+
4) Open the location of the sketch and convert the .bin file to a C byte array.
12+
cat SKETCH.bin | xxd --include > Binary.h
13+
5) Copy Binary.h file from the sketch's folder to the SBU_LoadBinary sketch
14+
and load it to the SARA-R410M via SBU_LoadBinary sketch.
15+
*/
16+
17+
/*
18+
Include the SBU library
19+
20+
This will add some code to the sketch before setup() is called
21+
to check if UPDATE.BIN and UPDATE.OK are present on the storage of
22+
the SARA-R410M module. If this check is positive UPDATE.BIN is used to update
23+
the sketch running on the board.
24+
After this UPDATE.BIN and UPDATE.OK are deleted from the flash.
25+
*/
26+
27+
28+
#include <SBU.h>
29+
30+
void setup()
31+
{
32+
Serial.begin(9600);
33+
while (!Serial) { }
34+
// wait a bit
35+
delay(1000);
36+
String message;
37+
message += "Sketch compile date and time: ";
38+
message += __DATE__;
39+
message += " ";
40+
message += __TIME__;
41+
// print out the sketch compile date and time on the serial port
42+
Serial.println(message);
43+
}
44+
45+
void loop()
46+
{
47+
// add you own code here
48+
}
+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
Copyright (c) 2020 Arduino LLC. All right reserved.
3+
4+
This library is free software; you can redistribute it and/or
5+
modify it under the terms of the GNU Lesser General Public
6+
License as published by the Free Software Foundation; either
7+
version 2.1 of the License, or (at your option) any later version.
8+
9+
This library is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
See the GNU Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public
15+
License along with this library; if not, write to the Free Software
16+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
*/
18+
19+
#include <FlashStorage.h>
20+
#include <MKRNB.h>
21+
22+
#define SBU_START 0x2000
23+
#define SBU_SIZE 0x8000
24+
25+
#define SKETCH_START (uint32_t*)(SBU_START + SBU_SIZE)
26+
27+
static constexpr char UPDATE_FILE_NAME[] = "UPDATE.BIN";
28+
static constexpr char CHECK_FILE_NAME[] = "UPDATE.OK";
29+
30+
FlashClass mcu_flash;
31+
32+
NBFileUtils fileUtils(true);
33+
34+
extern "C" void __libc_init_array(void);
35+
36+
int main()
37+
{
38+
init();
39+
40+
__libc_init_array();
41+
42+
delay(1);
43+
44+
constexpr size_t blockSize = 512;
45+
fileUtils.begin();
46+
47+
bool update_success = false;
48+
49+
// Try to update only if update file
50+
// has been download successfully.
51+
52+
if (fileUtils.listFile(CHECK_FILE_NAME)) {
53+
uint32_t updateSize = fileUtils.listFile(UPDATE_FILE_NAME);
54+
uint32_t tot_bytes = 0;
55+
uint32_t read_bytes = 0;
56+
57+
if (updateSize > SBU_SIZE) {
58+
updateSize = updateSize - SBU_SIZE;
59+
size_t cycles = (updateSize / blockSize);
60+
size_t spare_bytes = (updateSize % blockSize);
61+
/* Erase the MCU flash */
62+
uint32_t flash_address = (uint32_t)SKETCH_START;
63+
mcu_flash.erase((void*)flash_address, updateSize);
64+
65+
for (auto i = 0; i < cycles; i++) {
66+
uint8_t block[blockSize] { 0 };
67+
digitalWrite(LED_BUILTIN, LOW);
68+
read_bytes = fileUtils.readBlock(UPDATE_FILE_NAME, (i * blockSize) + SBU_SIZE, blockSize, block);
69+
digitalWrite(LED_BUILTIN, HIGH);
70+
mcu_flash.write((void*)flash_address, block, read_bytes);
71+
flash_address += read_bytes;
72+
tot_bytes += read_bytes;
73+
}
74+
75+
if (spare_bytes){
76+
uint8_t block[spare_bytes] { 0 };
77+
digitalWrite(LED_BUILTIN, LOW);
78+
read_bytes = fileUtils.readBlock(UPDATE_FILE_NAME, tot_bytes + SBU_SIZE, spare_bytes, block);
79+
digitalWrite(LED_BUILTIN, HIGH);
80+
mcu_flash.write((void*)flash_address, block, read_bytes);
81+
flash_address += read_bytes;
82+
}
83+
update_success = true;
84+
}
85+
if (update_success) {
86+
fileUtils.deleteFile(UPDATE_FILE_NAME);
87+
fileUtils.deleteFile(CHECK_FILE_NAME);
88+
}
89+
}
90+
91+
boot:
92+
/* Jump to the sketch */
93+
__set_MSP(*SKETCH_START);
94+
95+
/* Reset vector table address */
96+
SCB->VTOR = ((uint32_t)(SKETCH_START) & SCB_VTOR_TBLOFF_Msk);
97+
98+
/* Address of Reset_Handler is written by the linker at the beginning of the .text section (see linker script) */
99+
uint32_t resetHandlerAddress = (uint32_t) * (SKETCH_START + 1);
100+
/* Jump to reset handler */
101+
asm("bx %0"::"r"(resetHandlerAddress));
102+
}

libraries/SBU/extras/SBUBoot/build.sh

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/bin/sh -x
2+
3+
#Sara R410M
4+
ARDUINO=arduino
5+
SKETCH_NAME="SBUBoot.ino"
6+
SKETCH="$PWD/$SKETCH_NAME"
7+
BUILD_PATH="$PWD/build"
8+
OUTPUT_PATH="../../src/boot"
9+
10+
if [[ "$OSTYPE" == "darwin"* ]]; then
11+
ARDUINO="/Applications/Arduino.app/Contents/MacOS/Arduino"
12+
fi
13+
14+
buildSBUBootSketch() {
15+
BOARD=$1
16+
DESTINATION=$2
17+
18+
$ARDUINO --verify --board $BOARD --preserve-temp-files --pref build.path="$BUILD_PATH" $SKETCH
19+
cat "$BUILD_PATH/$SKETCH_NAME.bin" | xxd -include > $DESTINATION
20+
rm -rf "$BUILD_PATH"
21+
}
22+
23+
buildSBUBootSketch "arduino:samd:mkrnb1500" "$OUTPUT_PATH/mkrnb1500.h"

libraries/SBU/keywords.txt

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#######################################
2+
# Syntax Coloring Map For SBU
3+
#######################################
4+
5+
#######################################
6+
# Datatypes (KEYWORD1)
7+
#######################################
8+
9+
SBU KEYWORD1
10+
11+
#######################################
12+
# Methods and Functions (KEYWORD2)
13+
#######################################
14+
15+
#######################################
16+
# Constants (LITERAL1)
17+
#######################################

libraries/SBU/library.properties

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name=SBU
2+
version=1.0.0
3+
author=Arduino
4+
maintainer=Arduino <[email protected]>
5+
sentence=Update the sketch on your Arduino MKRNB1500 from SARA-R410M flash.
6+
paragraph=
7+
category=Other
8+
url=
9+
architectures=samd

libraries/SBU/src/SBU.cpp

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
Copyright (c) 2020 Arduino LLC. All right reserved.
3+
4+
This library is free software; you can redistribute it and/or
5+
modify it under the terms of the GNU Lesser General Public
6+
License as published by the Free Software Foundation; either
7+
version 2.1 of the License, or (at your option) any later version.
8+
9+
This library is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
See the GNU Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public
15+
License along with this library; if not, write to the Free Software
16+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
*/
18+
19+
#include <Arduino.h>
20+
21+
#include "SBU.h"
22+
23+
__attribute__ ((section(".sketch_boot")))
24+
unsigned char SBU_BOOT[0x8000] = {
25+
#if defined(ARDUINO_SAMD_MKRNB1500)
26+
#include "boot/mkrnb1500.h"
27+
#else
28+
#error "Unsupported board!"
29+
#endif
30+
};

libraries/SBU/src/SBU.h

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
Copyright (c) 2020 Arduino LLC. All right reserved.
3+
4+
This library is free software; you can redistribute it and/or
5+
modify it under the terms of the GNU Lesser General Public
6+
License as published by the Free Software Foundation; either
7+
version 2.1 of the License, or (at your option) any later version.
8+
9+
This library is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
See the GNU Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public
15+
License along with this library; if not, write to the Free Software
16+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
*/
18+
19+
#ifndef _SBU_H_INCLUDED
20+
#define _SBU_H_INCLUDED
21+
22+
/* Nothing to do */
23+
24+
#endif /* _SBU_H_INCLUDED */

0 commit comments

Comments
 (0)