1
+ /*
2
+ Portenta C33 - 2nd stage bootloader
3
+
4
+ The sketch checks for available update files on QSPI system partion
5
+ or SD card and try to update the Sketch
6
+
7
+ Build (release) with arduino-cli:
8
+ # arduino-cli compile --export-binaries --clean --verbose -b arduino-git:renesas:portenta_c33 --build-property "build.extra_flags=-DNO_USB -DPORTENTA_C33_SFU_BUILD"
9
+ Build (debug) with arduino-cli:
10
+ # arduino-cli compile --export-binaries --clean --verbose -b arduino-git:renesas:portenta_c33 --build-property "build.extra_flags=-DNO_USB -DPORTENTA_C33_SFU_DEBUG_OTA -DPORTENTA_C33_SFU_BUILD"
11
+ Export loader binary:
12
+ # xxd -i build/arduino-git.renesas.portenta_c33/loader.ino.bin | grep -E '0x' > ../../src/c33.h
13
+
14
+ This example code is in the public domain.
15
+ */
16
+ #include < BlockDevice.h>
17
+ #include < MBRBlockDevice.h>
18
+ #include < CodeFlashBlockDevice.h>
19
+ #include < FATFileSystem.h>
20
+ #include " ota.h"
21
+
22
+ #ifdef PORTENTA_C33_SFU_SDCARD_OTA
23
+ #include < SDCardBlockDevice.h>
24
+ #endif
25
+
26
+ #ifdef PORTENTA_C33_SFU_DEBUG_OTA
27
+ #include < Arduino_DebugUtils.h>
28
+ #endif
1
29
2
30
/* Key code for writing PRCR register. */
3
31
#define BSP_PRV_PRCR_KEY (0xA500U )
6
34
7
35
#define BSP_PRV_BITS_PER_WORD (32 )
8
36
9
-
10
- #define POST_APPLICATION_ADDR (0x10000 )
11
37
#define SKETCH_FLASH_OFFSET (64 * 1024 )
12
38
39
+ #define FULL_UPDATE_FILE_PATH " /ota/UPDATE.BIN"
40
+ #define FULL_UPDATE_FILE_PATH_OTA FULL_UPDATE_FILE_PATH " .OTA"
41
+
42
+ #define VERSION 1
43
+
44
+ #ifdef PORTENTA_C33_SFU_SDCARD_OTA
45
+ SDCardBlockDevice sd (PIN_SDHI_CLK, PIN_SDHI_CMD, PIN_SDHI_D0, PIN_SDHI_D1, PIN_SDHI_D2, PIN_SDHI_D3, PIN_SDHI_CD, PIN_SDHI_WP);
46
+ #endif
47
+
48
+ BlockDevice* qspi = BlockDevice::get_default_instance();
49
+ CodeFlashBlockDevice& cf = CodeFlashBlockDevice::getInstance();
50
+ MBRBlockDevice sys_bd (qspi, 1 );
51
+ FATFileSystem sys_fs (" ota" );
52
+
13
53
void setup () {
14
- Serial.begin (9600 );
15
- // while(!Serial){}
16
- Serial.println (" 2nd stage bootloader" );
54
+
55
+ #ifdef PORTENTA_C33_SFU_DEBUG_OTA
56
+ Serial.begin (115200 );
57
+ while (!Serial);
58
+ Debug.setDebugOutputStream (&Serial);
59
+ Debug.setDebugLevel (DBG_VERBOSE);
60
+ DEBUG_INFO (" SFU version: %d" , VERSION);
61
+ #endif
62
+
63
+ qspi->init ();
64
+ int err = sys_fs.mount (&sys_bd);
65
+ if (!err) {
66
+ #ifdef PORTENTA_C33_SFU_DEBUG_OTA
67
+ DEBUG_INFO (" Try QSPI OTA" );
68
+ #endif
69
+ try_ota ();
70
+ } else {
71
+ #ifdef PORTENTA_C33_SFU_DEBUG_OTA
72
+ DEBUG_ERROR (" Cannot mount QSPI filesystem. Error: %d" , err);
73
+ #endif
74
+ }
75
+
76
+ #ifdef PORTENTA_C33_SFU_SDCARD_OTA
77
+ sd.init ();
78
+ err = sys_fs.mount (&sd);
79
+ if (!err) {
80
+ #ifdef PORTENTA_C33_SFU_DEBUG_OTA
81
+ DEBUG_INFO (" Try SD OTA" );
82
+ #endif
83
+ try_ota ();
84
+ } else {
85
+ #ifdef PORTENTA_C33_SFU_DEBUG_OTA
86
+ DEBUG_ERROR (" Cannot mount SDCARD filesystem. Error: %d" , err);
87
+ #endif
88
+ }
89
+ #endif
17
90
18
91
int app_valid = (((*(uint32_t *) SKETCH_FLASH_OFFSET + POST_APPLICATION_ADDR) & 0xFF000000 ) == 0x20000000 );
19
92
if (app_valid) {
20
- Serial.print (" Booting application @" );
21
- Serial.print (SKETCH_FLASH_OFFSET + POST_APPLICATION_ADDR, HEX);
93
+ #ifdef PORTENTA_C33_SFU_DEBUG_OTA
94
+ DEBUG_INFO (" Booting application @ 0x%x" , SKETCH_FLASH_OFFSET + POST_APPLICATION_ADDR);
95
+ #endif
22
96
boot5 (SKETCH_FLASH_OFFSET + POST_APPLICATION_ADDR);
23
97
} else {
24
- Serial.print (" Application not found" );
98
+ #ifdef PORTENTA_C33_SFU_DEBUG_OTA
99
+ DEBUG_INFO (" Application not found" );
100
+ #endif
25
101
}
26
102
}
27
103
@@ -36,7 +112,7 @@ void boot5(uint32_t address) {
36
112
R_BSP_MODULE_STOP (FSP_IP_USBHS, 0 );
37
113
R_SYSTEM->PRCR = (uint16_t ) BSP_PRV_PRCR_LOCK;
38
114
39
- /* Disable MSP monitoring. */
115
+ /* Disable MSP monitoring. */
40
116
#if BSP_FEATURE_TZ_HAS_TRUSTZONE
41
117
__set_MSPLIM (0 );
42
118
#else
@@ -64,3 +140,68 @@ void boot5(uint32_t address) {
64
140
void (* programResetHandler)(void ) = (void (*)(void )) programResetHandlerAddress;
65
141
programResetHandler ();
66
142
}
143
+
144
+ int try_ota (void ) {
145
+ FILE *update_file;
146
+ FILE *target_file;
147
+
148
+ update_file = fopen (FULL_UPDATE_FILE_PATH_OTA, " rb" );
149
+ if (update_file) {
150
+ #ifdef PORTENTA_C33_SFU_DEBUG_OTA
151
+ DEBUG_INFO (" Compressed update file found" );
152
+ #endif
153
+ target_file = fopen (FULL_UPDATE_FILE_PATH, " wb" );
154
+ if (!target_file) {
155
+ #ifdef PORTENTA_C33_SFU_DEBUG_OTA
156
+ DEBUG_ERROR (" Error creating file for decompression" );
157
+ #endif
158
+ return -1 ;
159
+ }
160
+ int err = verify_decompress (update_file, target_file);
161
+ fclose (update_file);
162
+ fclose (target_file);
163
+ remove (FULL_UPDATE_FILE_PATH_OTA);
164
+ } else {
165
+ #ifdef PORTENTA_C33_SFU_DEBUG_OTA
166
+ DEBUG_INFO (" Compressed update file not found" );
167
+ #endif
168
+ }
169
+
170
+ update_file = fopen (FULL_UPDATE_FILE_PATH, " rb" );
171
+ if (update_file) {
172
+ #ifdef PORTENTA_C33_SFU_DEBUG_OTA
173
+ DEBUG_INFO (" Update file found" );
174
+ #endif
175
+ int err = verify_flash (update_file);
176
+ fclose (update_file);
177
+ remove (FULL_UPDATE_FILE_PATH);
178
+ } else {
179
+ #ifdef PORTENTA_C33_SFU_DEBUG_OTA
180
+ DEBUG_INFO (" Update file not found" );
181
+ #endif
182
+ }
183
+ }
184
+
185
+ int verify_decompress (FILE* update_file, FILE* target_file) {
186
+ int err = verify_header (update_file);
187
+ if (err) {
188
+ #ifdef PORTENTA_C33_SFU_DEBUG_OTA
189
+ DEBUG_ERROR (" Error during header verification: %d" , err);
190
+ #endif
191
+ return err;
192
+ }
193
+ err = decompress (update_file, target_file, nullptr );
194
+ return err;
195
+ }
196
+
197
+ int verify_flash (FILE* file) {
198
+ int err = verify_sketch (file);
199
+ if (err != 0 ) {
200
+ #ifdef PORTENTA_C33_SFU_DEBUG_OTA
201
+ DEBUG_ERROR (" Error during sketch verification: %d" , err);
202
+ #endif
203
+ return err;
204
+ }
205
+ err = flash (file, &cf, SKETCH_FLASH_OFFSET + POST_APPLICATION_ADDR);
206
+ return err;
207
+ }
0 commit comments