Skip to content

Commit

Permalink
don't go through runtime initializers when there is no OTA command
Browse files Browse the repository at this point in the history
Leave that to the main app instead, so we don't reset peripherals twice.
  • Loading branch information
afflux committed Dec 17, 2024
1 parent def00ba commit ecea8bd
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 27 deletions.
1 change: 1 addition & 0 deletions ota/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ target_compile_definitions(ota PUBLIC
PICO_RP2040_B2_SUPPORTED=1
PICO_PRINTF_SUPPORT_FLOAT=0
PICO_PRINTF_SUPPORT_LONG_LONG=0
PICO_RUNTIME_INIT_AEABI_MEM_OPS=00098
LIB_PICO_PRINTF_NONE=1
LFS_READONLY=1
LFS_NO_DEBUG=1
Expand Down
75 changes: 48 additions & 27 deletions ota/ota.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <hardware/sync.h>
#include <hardware/flash.h>
#include <pico/time.h>
#include <pico/runtime_init.h>
#include <hardware/gpio.h>
#include <hardware/uart.h>
#include <hardware/watchdog.h>
Expand Down Expand Up @@ -54,26 +55,33 @@ void dumphex(uint32_t x) {
}

extern OTACmdPage _ota_cmd;
void do_ota() {
static uint32_t blockToErase;


bool has_ota() {
if (*__FS_START__ == *__FS_END__) {
return;
return false;
}
if (!lfsMount(*__FS_START__, 4096, *__FS_END__ - *__FS_START__)) {
uart_puts(uart0, "mount failed\n");
return;
return false;
}

// We are very naughty and record the last block read, since it should be the actual data block of the
// OTA structure. We'll erase it behind the scenes to avoid bringing in all of LittleFS write infra.
uint32_t blockToErase;
if (!lfsReadOTA(&_ota_cmd, &blockToErase)) {
return;
return false;
}

if (memcmp(_ota_cmd.sign, "Pico OTA", 8)) {
return; // No signature
return false; // No signature
}

return true;
}



void do_ota() {
uint32_t crc = 0xffffffff;
const uint8_t *data = (const uint8_t *)&_ota_cmd;
for (uint32_t i = 0; i < offsetof(OTACmdPage, crc32); i++) {
Expand Down Expand Up @@ -159,31 +167,18 @@ void do_ota() {

// Do a hard reset just in case the start up sequence is not the same
watchdog_reboot(0, 0, 100);
while (true) {
tight_loop_contents();
}
}


#pragma GCC push_options
#pragma GCC optimize("O0")
int main(int a, char **b) {
(void) a;
(void) b;

#ifdef DEBUG
uart_init(uart0, 115200);
gpio_set_function(0, GPIO_FUNC_UART);
gpio_set_function(1, GPIO_FUNC_UART);
uart_set_hw_flow(uart0, false, false);
uart_set_format(uart0, 8, 1, UART_PARITY_NONE);
#endif

do_ota();

__attribute__((noreturn))
void boot_normal() {
#ifdef __riscv
extern void __mainapp();
__mainapp();

// Should never get here!
return 0;
#else
// Reset the interrupt/etc. vectors to the real app. Will be copied to RAM in app's runtime_init
scb_hw->vtor = (uint32_t)0x10003000;
Expand All @@ -194,10 +189,36 @@ int main(int a, char **b) {
register void (*fcn)(void) = (void (*)(void)) *(uint32_t *)0x10003004;
sp = (uint32_t *)_sp;
fcn();
(void)sp;
#endif

__builtin_unreachable();
}

void check_ota() {
if (!has_ota()) {
boot_normal();
}
}
PICO_RUNTIME_INIT_FUNC_RUNTIME(check_ota, "00099");

int main(int a, char **b) {
(void) a;
(void) b;

// Should never get here!
return *sp;
#ifdef DEBUG
uart_init(uart0, 115200);
gpio_set_function(0, GPIO_FUNC_UART);
gpio_set_function(1, GPIO_FUNC_UART);
uart_set_hw_flow(uart0, false, false);
uart_set_format(uart0, 8, 1, UART_PARITY_NONE);
#endif

// if we arrive here, it looks like we have an OTA command in the LittleFS
do_ota();

// fallback to normal boot if do_ota() failed, e.g. due to CRC failure or corruption
boot_normal();
}
#pragma GCC pop_options

Expand Down

0 comments on commit ecea8bd

Please sign in to comment.