Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SNU - Second Stage Bootloader for WiFi NINA enabled boards #512

Merged
merged 10 commits into from
Jul 1, 2020
1 change: 1 addition & 0 deletions boards.txt
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ mkrwifi1010.build.vid=0x2341
mkrwifi1010.build.pid=0x8054
mkrwifi1010.bootloader.tool=openocd
mkrwifi1010.bootloader.file=mkrwifi1010/samd21_sam_ba_arduino_mkrwifi1010.bin
mkrwifi1010.arduinoota.extraflags=-d

# Arduino NANO 33 IoT
# --------------------
Expand Down
106 changes: 106 additions & 0 deletions libraries/SNU/examples/Usage/Usage.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
Usage
This example demonstrates how to use the SAMD SNU library to update a
sketch on an Arduino MKRWiFi1010 board using the board and nothing else.
It prints out the date and time the sketch was compiled at
to both Serial and Serial1.

Arduino MKRWiFi1010 board

Steps to update sketch via NINA WiFi/BT module:

1) Upload this sketch or another sketch that includes the SNU library
via #include <SNU.h>

2) Update the sketch as desired. For this example the sketch prints out
the compiled date and time so no updates are needed.

3) In the IDE select: Sketch -> Export compiled Binary

4) Use WiFiStorage.download(url, "UPDATE.BIN") function to download the
new binary from a remote webserver.

5) Reboot the board; the update will be applied seamlessly

created 14 December 2018
by Martino Facchin
*/

/*
Include the SNU library

This will add some code to the sketch before setup() is called
to check if the WiFi module is present and UPDATE.bin exists.

If UPDATE.bin is present, the file is used to update the sketch
running on the board. After this UPDATE.bin is deleted from NINA memory.
*/
#include <SNU.h>
#include <WiFiNINA.h>

#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
/////// Wifi Settings ///////
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password
char url[] = SECRET_OTA_URL;

int status = WL_IDLE_STATUS;

String message;

void setup() {
Serial.begin(9600);
Serial1.begin(9600);

// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while (true);
}

// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
}

// wait a bit
delay(1000);

message += "Sketch compile date and time: ";
message += __DATE__;
message += " ";
message += __TIME__;

// print out the sketch compile date and time on the serial port
Serial.println(message);
Serial1.println(message);

Serial.println("Type \"download\" in the Serial Monitor to start downloading the update");
}

void loop() {
String command = Serial.readStringUntil('\n');

if (command.indexOf("download") >= 0) {

Serial.println("Downloading update file");
WiFiStorage.download(url, "UPDATE.BIN");

WiFiStorageFile update = WiFiStorage.open("/fs/UPDATE.BIN");
if (update.available()) {
Serial.println("Download complete, please restart or type \"restart\" to apply the update");
Serial.println("Filesize: " + String(update.available()));
} else {
Serial.println("Download failed, please retry :(");
}
}

if (command.indexOf("restart") >= 0) {
NVIC_SystemReset();
}
}
3 changes: 3 additions & 0 deletions libraries/SNU/examples/Usage/arduino_secrets.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#define SECRET_SSID ""
#define SECRET_PASS ""
#define SECRET_OTA_URL "http://downloads.arduino.cc/misc/WiFi1010_blinkRBG.bin"
117 changes: 117 additions & 0 deletions libraries/SNU/extras/NiNaBoot/NiNaBoot.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
Copyright (c) 2017 Arduino LLC. All right reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <WiFiNINA.h>
#include <FlashStorage.h>

#ifdef ARDUINO_SAMD_MKRVIDOR4000
#include <VidorPeripherals.h>
#endif /* ARDUINO_SAMD_MKRVIDOR4000 */

#ifdef ARDUINO_SAMD_MKRVIDOR4000
#define NINA_GPIO0 FPGA_NINA_GPIO0
#define NINA_RESETN FPGA_SPIWIFI_RESET
#endif /* ARDUINO_SAMD_MKRVIDOR4000 */

#define SDU_START 0x2000
#define SDU_SIZE 0x4000

#define SKETCH_START (uint32_t*)(SDU_START + SDU_SIZE)

#define UPDATE_FILE "/fs/UPDATE.BIN"

FlashClass flash;

// Initialize C library
extern "C" void __libc_init_array(void);

int main() {
init();

__libc_init_array();

delay(1);

#if defined(ARDUINO_SAMD_MKRVIDOR4000)
FPGA.begin();
/* NINA select SPI mode and enable (by setting RESETN = '1') */
FPGA.pinMode (NINA_GPIO0, OUTPUT);
FPGA.digitalWrite(NINA_GPIO0, HIGH);
FPGA.pinMode (NINA_RESETN, OUTPUT);
FPGA.digitalWrite(NINA_RESETN, HIGH);
#elif defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT)
/* NINA select SPI mode and enable (by setting RESETN = '1') */
pinMode (NINA_GPIO0, OUTPUT);
digitalWrite(NINA_GPIO0, HIGH);
pinMode (NINA_RESETN, OUTPUT);
digitalWrite(NINA_RESETN, HIGH);
#endif

if (WiFi.status() == WL_NO_SHIELD) {
goto boot;
}

if (WiFiStorage.exists(UPDATE_FILE)) {

WiFiStorageFile updateFile = WiFiStorage.open(UPDATE_FILE);
uint32_t updateSize = updateFile.size();
bool updateFlashed = false;

if (updateSize > SDU_SIZE) {
// skip the SDU section
updateFile.seek(SDU_SIZE);
updateSize -= SDU_SIZE;

uint32_t flashAddress = (uint32_t)SKETCH_START;

// erase the pages
flash.erase((void*)flashAddress, updateSize);

uint8_t buffer[128];

// write the pages
for (uint32_t i = 0; i < updateSize; i += sizeof(buffer)) {
updateFile.read(buffer, sizeof(buffer));

flash.write((void*)flashAddress, buffer, sizeof(buffer));

flashAddress += sizeof(buffer);
}

updateFlashed = true;
}

updateFile.close();

if (updateFlashed) {
updateFile.erase();
}
}

boot:
// jump to the sketch
__set_MSP(*SKETCH_START);

//Reset vector table address
SCB->VTOR = ((uint32_t)(SKETCH_START) & SCB_VTOR_TBLOFF_Msk);

// address of Reset_Handler is written by the linker at the beginning of the .text section (see linker script)
uint32_t resetHandlerAddress = (uint32_t) * (SKETCH_START + 1);
// jump to reset handler
asm("bx %0"::"r"(resetHandlerAddress));
}
26 changes: 26 additions & 0 deletions libraries/SNU/extras/NiNaBoot/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/sh -x

ARDUINO=arduino
SKETCH_NAME="NiNaBoot.ino"
SKETCH="$PWD/$SKETCH_NAME"
BUILD_PATH="$PWD/build"
OUTPUT_PATH="../../src/boot"

if [[ "$OSTYPE" == "darwin"* ]]; then
ARDUINO="/Applications/Arduino.app/Contents/MacOS/Arduino"
fi

buildSDUBootSketch() {
BOARD=$1
DESTINATION=$2

$ARDUINO --verify --board $BOARD --preserve-temp-files --pref build.path="$BUILD_PATH" $SKETCH
cat "$BUILD_PATH/$SKETCH_NAME.bin" | xxd -include -len 0x4000 > $DESTINATION
rm -rf "$BUILD_PATH"
}

mkdir -p "$OUTPUT_PATH"

buildSDUBootSketch "arduino:samd:mkrwifi1010" "$OUTPUT_PATH/mkrwifi1010.h"
buildSDUBootSketch "arduino:samd:mkrvidor4000" "$OUTPUT_PATH/mkrvidor4000.h"
buildSDUBootSketch "arduino:samd:nano_33_iot" "$OUTPUT_PATH/nano33iot.h"
17 changes: 17 additions & 0 deletions libraries/SNU/keywords.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#######################################
# Syntax Coloring Map For SNU
#######################################

#######################################
# Datatypes (KEYWORD1)
#######################################

SNU KEYWORD1

#######################################
# Methods and Functions (KEYWORD2)
#######################################

#######################################
# Constants (LITERAL1)
#######################################
9 changes: 9 additions & 0 deletions libraries/SNU/library.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name=SNU
version=1.0.0
author=Arduino
maintainer=Arduino <info@arduino.cc>
sentence=Update the sketch on your board with NiNa W10 wifi module
paragraph=Requires a board with NiNa W10 module onboard
category=Other
url=http://www.arduino.cc/en/Reference/SNU
architectures=megaAVR, samd
34 changes: 34 additions & 0 deletions libraries/SNU/src/SNU.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
Copyright (c) 2017 Arduino LLC. All right reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <Arduino.h>

#include "SNU.h"

__attribute__ ((section(".sketch_boot")))
unsigned char sduBoot[0x4000] = {
#if defined(ARDUINO_SAMD_MKRWIFI1010)
#include "boot/mkrwifi1010.h"
#elif defined(ARDUINO_SAMD_MKRVIDOR4000)
#include "boot/mkrvidor4000.h"
#elif defined(ARDUINO_SAMD_NANO_33_IOT)
#include "boot/nano33iot.h"
#else
#error "Unsupported board!"
#endif
};
24 changes: 24 additions & 0 deletions libraries/SNU/src/SNU.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
Copyright (c) 2017 Arduino LLC. All right reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef _SFU_H_INCLUDED
#define _SFU_H_INCLUDED

// nothing for now

#endif
Loading