1/*
2  Copyright (c) 2017 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 <WiFiNINA.h>
20#include <FlashStorage.h>
21
22#define SDU_START    0x2000
23#define SDU_SIZE     0x4000
24
25#define SKETCH_START (uint32_t*)(SDU_START + SDU_SIZE)
26
27#define UPDATE_FILE "/fs/UPDATE.BIN"
28
29FlashClass flash;
30
31// Initialize C library
32extern "C" void __libc_init_array(void);
33
34int main() {
35  init();
36
37  __libc_init_array();
38
39  delay(1);
40
41  // NINA - SPI boot
42  pinMode(NINA_GPIO0, OUTPUT);
43  digitalWrite(NINA_GPIO0, HIGH);
44
45  // disable NINA
46  pinMode(NINA_RESETN, OUTPUT);
47  digitalWrite(NINA_RESETN, HIGH);
48
49  if (WiFi.status() == WL_NO_SHIELD) {
50    goto boot;
51  }
52
53  if (WiFiStorage.exists(UPDATE_FILE)) {
54
55    WiFiStorageFile updateFile = WiFiStorage.open(UPDATE_FILE);
56    uint32_t updateSize = updateFile.size();
57    bool updateFlashed = false;
58
59    if (updateSize > SDU_SIZE) {
60      // skip the SDU section
61      updateFile.seek(SDU_SIZE);
62      updateSize -= SDU_SIZE;
63
64      uint32_t flashAddress = (uint32_t)SKETCH_START;
65
66      // erase the pages
67      flash.erase((void*)flashAddress, updateSize);
68
69      uint8_t buffer[128];
70
71      // write the pages
72      for (uint32_t i = 0; i < updateSize; i += sizeof(buffer)) {
73        updateFile.read(buffer, sizeof(buffer));
74
75        flash.write((void*)flashAddress, buffer, sizeof(buffer));
76
77        flashAddress += sizeof(buffer);
78      }
79
80      updateFlashed = true;
81    }
82
83    updateFile.close();
84
85    if (updateFlashed) {
86      updateFile.erase();
87    }
88  }
89
90boot:
91  // jump to the sketch
92  __set_MSP(*SKETCH_START);
93
94  //Reset vector table address
95  SCB->VTOR = ((uint32_t)(SKETCH_START) & SCB_VTOR_TBLOFF_Msk);
96
97  // address of Reset_Handler is written by the linker at the beginning of the .text section (see linker script)
98  uint32_t resetHandlerAddress = (uint32_t) * (SKETCH_START + 1);
99  // jump to reset handler
100  asm("bx %0"::"r"(resetHandlerAddress));
101}
102