24
24
#include <hardware/sync.h>
25
25
#include <hardware/flash.h>
26
26
#include <pico/time.h>
27
+ #include <pico/runtime_init.h>
27
28
#include <hardware/gpio.h>
28
29
#include <hardware/uart.h>
29
30
#include <hardware/watchdog.h>
@@ -54,26 +55,33 @@ void dumphex(uint32_t x) {
54
55
}
55
56
56
57
extern OTACmdPage _ota_cmd ;
57
- void do_ota () {
58
+ static uint32_t blockToErase ;
59
+
60
+
61
+ bool has_ota () {
58
62
if (* __FS_START__ == * __FS_END__ ) {
59
- return ;
63
+ return false ;
60
64
}
61
65
if (!lfsMount (* __FS_START__ , 4096 , * __FS_END__ - * __FS_START__ )) {
62
- uart_puts (uart0 , "mount failed\n" );
63
- return ;
66
+ return false;
64
67
}
65
68
66
69
// We are very naughty and record the last block read, since it should be the actual data block of the
67
70
// OTA structure. We'll erase it behind the scenes to avoid bringing in all of LittleFS write infra.
68
- uint32_t blockToErase ;
69
71
if (!lfsReadOTA (& _ota_cmd , & blockToErase )) {
70
- return ;
72
+ return false ;
71
73
}
72
74
73
75
if (memcmp (_ota_cmd .sign , "Pico OTA" , 8 )) {
74
- return ; // No signature
76
+ return false ; // No signature
75
77
}
76
78
79
+ return true;
80
+ }
81
+
82
+
83
+
84
+ void do_ota () {
77
85
uint32_t crc = 0xffffffff ;
78
86
const uint8_t * data = (const uint8_t * )& _ota_cmd ;
79
87
for (uint32_t i = 0 ; i < offsetof(OTACmdPage , crc32 ); i ++ ) {
@@ -159,31 +167,18 @@ void do_ota() {
159
167
160
168
// Do a hard reset just in case the start up sequence is not the same
161
169
watchdog_reboot (0 , 0 , 100 );
170
+ while (true) {
171
+ tight_loop_contents ();
172
+ }
162
173
}
163
174
164
-
165
175
#pragma GCC push_options
166
176
#pragma GCC optimize("O0")
167
- int main (int a , char * * b ) {
168
- (void ) a ;
169
- (void ) b ;
170
-
171
- #ifdef DEBUG
172
- uart_init (uart0 , 115200 );
173
- gpio_set_function (0 , GPIO_FUNC_UART );
174
- gpio_set_function (1 , GPIO_FUNC_UART );
175
- uart_set_hw_flow (uart0 , false, false);
176
- uart_set_format (uart0 , 8 , 1 , UART_PARITY_NONE );
177
- #endif
178
-
179
- do_ota ();
180
-
177
+ __attribute__((noreturn ))
178
+ void boot_normal () {
181
179
#ifdef __riscv
182
180
extern void __mainapp ();
183
181
__mainapp ();
184
-
185
- // Should never get here!
186
- return 0 ;
187
182
#else
188
183
// Reset the interrupt/etc. vectors to the real app. Will be copied to RAM in app's runtime_init
189
184
scb_hw -> vtor = (uint32_t )0x10003000 ;
@@ -194,10 +189,43 @@ int main(int a, char **b) {
194
189
register void (* fcn )(void ) = (void (* )(void )) * (uint32_t * )0x10003004 ;
195
190
sp = (uint32_t * )_sp ;
196
191
fcn ();
192
+ (void )sp ;
193
+ #endif
194
+
195
+ __builtin_unreachable ();
196
+ }
197
+
198
+ void check_ota () {
199
+ // this runs before the full runtime and hardware is initialized to prevent
200
+ // initialization happening again in the application. Care must be taken that
201
+ // no uninitialized peripheral or part of the runtime is used.
202
+ // If necessary, init routines can be moved before check_ota() by adjusting
203
+ // their PICO_RUNTIME_INIT_* in CMakeLists.txt.
204
+ // refer to this source for existing init routines:
205
+ // https://github.com/raspberrypi/pico-sdk/blob/2.1.0/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h
206
+ if (!has_ota ()) {
207
+ boot_normal ();
208
+ }
209
+ }
210
+ PICO_RUNTIME_INIT_FUNC_RUNTIME (check_ota , "00099" );
211
+
212
+ int main (int a , char * * b ) {
213
+ (void ) a ;
214
+ (void ) b ;
197
215
198
- // Should never get here!
199
- return * sp ;
216
+ #ifdef DEBUG
217
+ uart_init (uart0 , 115200 );
218
+ gpio_set_function (0 , GPIO_FUNC_UART );
219
+ gpio_set_function (1 , GPIO_FUNC_UART );
220
+ uart_set_hw_flow (uart0 , false, false);
221
+ uart_set_format (uart0 , 8 , 1 , UART_PARITY_NONE );
200
222
#endif
223
+
224
+ // if we arrive here, it looks like we have an OTA command in the LittleFS
225
+ do_ota ();
226
+
227
+ // fallback to normal boot if do_ota() failed, e.g. due to CRC failure or corruption
228
+ boot_normal ();
201
229
}
202
230
#pragma GCC pop_options
203
231
0 commit comments