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/**************************************************************************************
20 * INCLUDE
21 **************************************************************************************/
22
23#include <FlashStorage.h>
24#include <Arduino_MKRMEM.h>
25
26/**************************************************************************************
27 * DEFINE
28 **************************************************************************************/
29
30#define SFU_START    0x2000
31#define SFU_SIZE     0x8000
32
33#define SKETCH_START (uint32_t*)(SFU_START + SFU_SIZE)
34
35/**************************************************************************************
36 * GLOBAL CONSTANTS
37 **************************************************************************************/
38
39static char const UPDATE_FILE_NAME[] = "UPDATE.BIN";
40
41/**************************************************************************************
42 * GLOBAL VARIABLES
43 **************************************************************************************/
44
45FlashClass mcu_flash;
46
47/**************************************************************************************
48 * FUNCTION DECLARATION
49 **************************************************************************************/
50
51extern "C" void __libc_init_array(void);
52
53/**************************************************************************************
54 * MAIN
55 **************************************************************************************/
56
57int main()
58{
59  init();
60
61  __libc_init_array();
62
63  delay(1);
64
65  /* Initialize W25Q16DV flash chip found on Arduino MKRMEM Shield */
66  flash.begin();
67
68  /* Mount and verify filesystem */
69  if ((SPIFFS_OK == filesystem.mount()) && (SPIFFS_OK == filesystem.check()))
70  {
71    /* Open update file */
72    filesystem.clearerr();
73    File file = filesystem.open(UPDATE_FILE_NAME, READ_ONLY);
74    if(SPIFFS_OK == filesystem.err())
75    { 
76      bool update_success = false;
77      /* Determine the size of the update file */
78      int file_size = file.lseek(0, END);
79      if (file_size > SFU_SIZE)
80      {
81        /* Skip the SFU section */
82        file.lseek(SFU_SIZE, START);
83        file_size -= SFU_SIZE;
84
85        /* Erase the MCU flash */
86        uint32_t flash_address = (uint32_t)SKETCH_START;
87        mcu_flash.erase((void*)flash_address, file_size);
88
89        /* Write the MCU flash */
90        uint8_t buffer[512];
91        for (int b = 0; b < file_size; b += sizeof(buffer))
92        {
93          file.read(buffer, sizeof(buffer));
94          mcu_flash.write((void*)flash_address, buffer, sizeof(buffer));
95          flash_address += sizeof(buffer);
96        }
97        update_success = true;
98      }
99      file.close();
100      if (update_success) { filesystem.remove(UPDATE_FILE_NAME); }
101      filesystem.unmount();
102    }
103  }
104
105  /* Jump to the sketch */
106  __set_MSP(*SKETCH_START);
107
108  /* Reset vector table address */
109  SCB->VTOR = ((uint32_t)(SKETCH_START) & SCB_VTOR_TBLOFF_Msk);
110
111  /* Address of Reset_Handler is written by the linker at the beginning of the .text section (see linker script) */
112  uint32_t resetHandlerAddress = (uint32_t) * (SKETCH_START + 1);
113  /* Jump to reset handler */
114  asm("bx %0"::"r"(resetHandlerAddress));
115}
116