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
129
230/* Key code for writing PRCR register. */
331#define BSP_PRV_PRCR_KEY (0xA500U )
634
735#define BSP_PRV_BITS_PER_WORD (32 )
836
9-
10- #define POST_APPLICATION_ADDR (0x10000 )
1137#define SKETCH_FLASH_OFFSET (64 * 1024 )
1238
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+
1353void 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
1790
1891 int app_valid = (((*(uint32_t *) SKETCH_FLASH_OFFSET + POST_APPLICATION_ADDR) & 0xFF000000 ) == 0x20000000 );
1992 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
2296 boot5 (SKETCH_FLASH_OFFSET + POST_APPLICATION_ADDR);
2397 } else {
24- Serial.print (" Application not found" );
98+ #ifdef PORTENTA_C33_SFU_DEBUG_OTA
99+ DEBUG_INFO (" Application not found" );
100+ #endif
25101 }
26102}
27103
@@ -36,7 +112,7 @@ void boot5(uint32_t address) {
36112 R_BSP_MODULE_STOP (FSP_IP_USBHS, 0 );
37113 R_SYSTEM->PRCR = (uint16_t ) BSP_PRV_PRCR_LOCK;
38114
39- /* Disable MSP monitoring. */
115+ /* Disable MSP monitoring. */
40116#if BSP_FEATURE_TZ_HAS_TRUSTZONE
41117 __set_MSPLIM (0 );
42118#else
@@ -64,3 +140,68 @@ void boot5(uint32_t address) {
64140 void (* programResetHandler)(void ) = (void (*)(void )) programResetHandlerAddress;
65141 programResetHandler ();
66142}
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