Skip to content

Commit 7eb793a

Browse files
sandeepmistryfacchinm
authored andcommitted
Add initial SAMD Bootloader Updater library
1 parent 6564319 commit 7eb793a

File tree

7 files changed

+976
-0
lines changed

7 files changed

+976
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
Update Bootloader
3+
4+
This sketch checks if you Arduino SAMD board is running the latest bootloader.
5+
6+
If it is not, it prompts you to update it.
7+
8+
Circuit:
9+
- MKR Vidor 4000
10+
11+
This example code is in the public domain.
12+
*/
13+
14+
15+
#include <SAMD_BootloaderUpdater.h>
16+
17+
void setup() {
18+
19+
Serial.begin(9600);
20+
while (!Serial);
21+
22+
Serial.println("Welcome to the Arduino SAMD bootloader updater");
23+
Serial.println("----------------------------------------------");
24+
Serial.println();
25+
26+
retry:
27+
Serial.print("Checking if bootloader requires an update ... ");
28+
if (SAMD_BootloaderUpdater.needsUpdate()) {
29+
Serial.println("bootloader is already the latest version");
30+
Serial.println();
31+
Serial.println("Update is not required :)");
32+
33+
while (1);
34+
}
35+
36+
Serial.println("bootloader is NOT running the latest");
37+
Serial.println();
38+
Serial.println();
39+
Serial.println("Would you like to proceed with updating it? (y/N)");
40+
Serial.println();
41+
42+
String input = readLine();
43+
input.toLowerCase();
44+
45+
if (input != "y") {
46+
Serial.println("That's all folks!");
47+
while (1);
48+
}
49+
50+
pinMode(LED_BUILTIN, OUTPUT);
51+
52+
Serial.println("WARNING: DO NOT UNPLUG the USB cable during the update!!!");
53+
Serial.println();
54+
Serial.println("Updating bootloader ...");
55+
Serial.println();
56+
57+
if (!SAMD_BootloaderUpdater.update(onUpdateProgress)) {
58+
Serial.println("oh no! the bootloader failed to update :(");
59+
Serial.println();
60+
goto retry;
61+
}
62+
63+
Serial.println();
64+
Serial.println("The bootloader was successfully updated \\o/");
65+
Serial.println();
66+
Serial.println("Your board will now start blinking in joy :)");
67+
}
68+
69+
void onUpdateProgress(float percentage)
70+
{
71+
// toggle the LED
72+
digitalWrite(LED_BUILTIN, digitalRead(LED_BUILTIN) ? LOW : HIGH);
73+
74+
// print out the percentage
75+
Serial.print(percentage);
76+
Serial.println("%");
77+
}
78+
79+
void loop() {
80+
digitalWrite(LED_BUILTIN, HIGH);
81+
delay(100);
82+
83+
digitalWrite(LED_BUILTIN, LOW);
84+
delay(100);
85+
}
86+
87+
String readLine() {
88+
String line;
89+
90+
while (1) {
91+
if (Serial.available()) {
92+
char c = Serial.read();
93+
94+
if (c == '\r') {
95+
// ignore
96+
} else if (c == '\n') {
97+
break;
98+
}
99+
100+
line += c;
101+
}
102+
}
103+
104+
line.trim();
105+
106+
return line;
107+
}
108+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/sh -x
2+
3+
ARDUINO=arduino
4+
BOOTLOADER_DIR=" ../../../bootloaders"
5+
OUTPUT_PATH="../src/bootloaders"
6+
7+
if [[ "$OSTYPE" == "darwin"* ]]; then
8+
ARDUINO="/Applications/Arduino.app/Contents/MacOS/Arduino"
9+
fi
10+
11+
ls $BOOTLOADER_DIR/mkrvidor4000
12+
cat $BOOTLOADER_DIR/mkrvidor4000/samd21_sam_ba_arduino_mkrvidor4000.bin | xxd -i > $OUTPUT_PATH/mkrvidor4000.h
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
################################################
2+
# Syntax Coloring Map For SAMD_BootloaderUpdater
3+
################################################
4+
5+
################################################
6+
# Datatypes (KEYWORD1)
7+
################################################
8+
9+
################################################
10+
# Methods and Functions (KEYWORD2)
11+
################################################
12+
13+
needsUpdate KEYWORD2
14+
update KEYWORD2
15+
16+
#######################################
17+
# Instances (KEYWORD2)
18+
#######################################
19+
20+
SAMD_BootloaderUpdater KEYWORD2
21+
22+
#######################################
23+
# Constants (LITERAL1)
24+
#######################################
25+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name=SAMD_BootloaderUpdater
2+
version=1.0
3+
author=Arduino
4+
maintainer=Arduino <info@arduino.cc>
5+
sentence=Update the bootloader running on your Arduino SAMD board to the latest.
6+
paragraph=
7+
category=Other
8+
url=
9+
architectures=samd,samd_beta
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
This file is part of the SAMD Bootloader Updater library.
3+
Copyright (c) 2018 Arduino SA. All rights reserved.
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
#include "SAMD_BootloaderUpdater.h"
21+
22+
#define PAGE_SIZE (64)
23+
#define PAGES (4096)
24+
#define MAX_FLASH (PAGE_SIZE * PAGES)
25+
#define ROW_SIZE (PAGE_SIZE * 4)
26+
27+
__attribute__((aligned (4)))
28+
uint8_t booloaderData[8192] = {
29+
#if defined(ARDUINO_SAMD_MKRVIDOR4000)
30+
#include "bootloaders/mkrvidor4000.h"
31+
#else
32+
#error "Unsupported board!"
33+
#endif
34+
};
35+
36+
#define BOOTLOADER_START 0x00000000
37+
#define USER_ROW_START 0x00804000
38+
39+
extern "C" {
40+
// these functions must be in RAM (.data) and NOT inlined
41+
// as they erase and copy the sketch data in flash
42+
43+
__attribute__ ((long_call, noinline, section (".data#")))
44+
static void eraseFlash(uint32_t address, int length)
45+
{
46+
for (int i = 0; i < length; i += ROW_SIZE) {
47+
NVMCTRL->ADDR.reg = ((uint32_t)((uint32_t)address + i)) / 2;
48+
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER;
49+
50+
while (!NVMCTRL->INTFLAG.bit.READY);
51+
}
52+
}
53+
54+
__attribute__ ((long_call, noinline, section (".data#")))
55+
static void readFlash(uint32_t src, void* dest, int length)
56+
{
57+
memcpy(dest, (void*)src, length);
58+
}
59+
60+
__attribute__ ((long_call, noinline, section (".data#")))
61+
static void writeFlash(uint32_t dest, const void* src, int length)
62+
{
63+
volatile uint32_t* d = (uint32_t*)dest;
64+
const volatile uint32_t* s = (const uint32_t*)src;
65+
66+
for (int i = 0; i < length; i += 4) {
67+
*d++ = *s++;
68+
69+
while (!NVMCTRL->INTFLAG.bit.READY);
70+
}
71+
}
72+
}
73+
74+
bool SAMD_BootloaderUpdaterClass::needsUpdate()
75+
{
76+
return (memcmp(BOOTLOADER_START, booloaderData, sizeof(booloaderData)) == 0);
77+
}
78+
79+
int SAMD_BootloaderUpdaterClass::update(void(*progressCallback)(float))
80+
{
81+
// enable auto page writes
82+
NVMCTRL->CTRLB.bit.MANW = 0;
83+
84+
// copy the user row, and set the BOOTPROT size to 0
85+
uint32_t userRow[PAGE_SIZE / sizeof(uint32_t)];
86+
readFlash(USER_ROW_START, userRow, sizeof(userRow));
87+
userRow[0] |= 0x00000007;
88+
89+
// erase the user row and flash the update value
90+
eraseFlash(USER_ROW_START, sizeof(userRow));
91+
writeFlash(USER_ROW_START, userRow, sizeof(userRow));
92+
93+
if (progressCallback) {
94+
progressCallback(0.0);
95+
}
96+
97+
// erase and copy the flash row by row
98+
for (size_t i = 0; i < sizeof(booloaderData); i += ROW_SIZE) {
99+
eraseFlash(BOOTLOADER_START + i, ROW_SIZE);
100+
writeFlash(BOOTLOADER_START + i, &booloaderData[i], ROW_SIZE);
101+
102+
if (progressCallback) {
103+
progressCallback((i + ROW_SIZE) * 100.0 / sizeof(booloaderData));
104+
}
105+
}
106+
107+
return needsUpdate() ? 1 : 0;
108+
}
109+
110+
SAMD_BootloaderUpdaterClass SAMD_BootloaderUpdater;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
This file is part of the SAMD Bootloader Updater library.
3+
Copyright (c) 2018 Arduino SA. All rights reserved.
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
#ifndef _SAMD_BOOTLOADER_UPDATER_H_
21+
#define _SAMD_BOOTLOADER_UPDATER_H_
22+
23+
#include <Arduino.h>
24+
25+
class SAMD_BootloaderUpdaterClass {
26+
public:
27+
bool needsUpdate();
28+
29+
int update(void(*progressCallback)(float));
30+
};
31+
32+
extern SAMD_BootloaderUpdaterClass SAMD_BootloaderUpdater;
33+
34+
#endif

0 commit comments

Comments
 (0)