summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2022-06-02 13:43:46 +1000
committerDamien George <damien@micropython.org>2022-06-02 14:30:51 +1000
commit87ca431f3fa3fc87094526e33b77c50d6f968100 (patch)
tree97031bcb3bd8c8227692dabbd41ca895e859792a
parentd84ebc31f7f00edb47dd417dff6adfd47a880c1e (diff)
stm32/boards/LEGO_HUB_NO6: Implement robust filesystem-load updates.
Signed-off-by: Damien George <damien@micropython.org>
-rw-r--r--ports/stm32/boards/LEGO_HUB_NO6/board_init.c38
-rw-r--r--ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h2
2 files changed, 39 insertions, 1 deletions
diff --git a/ports/stm32/boards/LEGO_HUB_NO6/board_init.c b/ports/stm32/boards/LEGO_HUB_NO6/board_init.c
index 8b2c0ce1b..37a80bc91 100644
--- a/ports/stm32/boards/LEGO_HUB_NO6/board_init.c
+++ b/ports/stm32/boards/LEGO_HUB_NO6/board_init.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2021 Damien P. George
+ * Copyright (c) 2021-2022 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -75,6 +75,7 @@ void board_init(void) {
#if BUILDING_MBOOT
+#include "drivers/memory/spiflash.h"
#include "mboot/mboot.h"
#include "boardctrl.h"
#include "adc.h"
@@ -88,6 +89,14 @@ void board_init(void) {
#define PATTERN_N (0x01296ad2)
#define PATTERN_S (0x0064104c)
+// Location and value for the SPI flash update key. If this key exists at the defined
+// location then mboot will attempt to do a filesystem-load update of the main firmware.
+// This makes the update robust to power failures: if the update does not complete then
+// it will be restarted the next time it powers up. Only when it fully completes will
+// this key be erased, and then the application can run.
+#define SPIFLASH_UPDATE_KEY_ADDR (1020 * 1024)
+#define SPIFLASH_UPDATE_KEY_VALUE (0x12345678)
+
static void board_led_pattern(int reset_mode, uint16_t brightness) {
static const uint32_t pixels[] = {
0,
@@ -162,9 +171,36 @@ int board_mboot_get_reset_mode(uint32_t *initial_r0) {
mp_hal_delay_ms(50);
}
mp_hal_delay_ms(300);
+ } else {
+ // Button not pressed, check flash for update key and start an update if the key exists.
+
+ // Initialise the external SPI flash.
+ MBOOT_SPIFLASH_SPIFLASH->config = MBOOT_SPIFLASH_CONFIG;
+ mp_spiflash_init(MBOOT_SPIFLASH_SPIFLASH);
+
+ // Read in the key.
+ uint32_t buf;
+ mp_spiflash_read(MBOOT_SPIFLASH_SPIFLASH, SPIFLASH_UPDATE_KEY_ADDR, 4, (uint8_t *)&buf);
+
+ if (buf == SPIFLASH_UPDATE_KEY_VALUE) {
+ // The key has the correct value, so read in the FS-load elements and enter the bootloader.
+ mp_spiflash_read(MBOOT_SPIFLASH_SPIFLASH, SPIFLASH_UPDATE_KEY_ADDR + 4, ELEM_DATA_SIZE, ELEM_DATA_START);
+ *initial_r0 = MBOOT_INITIAL_R0_KEY_FSLOAD;
+ reset_mode = BOARDCTRL_RESET_MODE_BOOTLOADER;
+ }
}
board_led_pattern(0, 0);
return reset_mode;
}
+void board_mboot_state_change(int state, uint32_t arg) {
+ if (state == MBOOT_STATE_FSLOAD_END) {
+ // The FS-load update completed (either with success or failure), so erase the
+ // update key and write the result of the FS-load operation into flash.
+ mp_spiflash_erase_block(MBOOT_SPIFLASH_SPIFLASH, SPIFLASH_UPDATE_KEY_ADDR);
+ mp_spiflash_write(MBOOT_SPIFLASH_SPIFLASH, SPIFLASH_UPDATE_KEY_ADDR + 4, 4, (const uint8_t *)&arg);
+ }
+ mboot_state_change_default(state, arg);
+}
+
#endif
diff --git a/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h b/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h
index 8aa9da951..cab46fa02 100644
--- a/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h
+++ b/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h
@@ -153,6 +153,7 @@
#define MBOOT_BOARD_EARLY_INIT(initial_r0) board_init()
#define MBOOT_BOARD_CLEANUP board_mboot_cleanup
#define MBOOT_BOARD_GET_RESET_MODE board_mboot_get_reset_mode
+#define MBOOT_BOARD_STATE_CHANGE board_mboot_state_change
/******************************************************************************/
// Function declarations
@@ -167,4 +168,5 @@ void board_mboot_cleanup(int reset_mode);
void board_mboot_led_init(void);
void board_mboot_led_state(int led, int state);
int board_mboot_get_reset_mode(uint32_t *initial_r0);
+void board_mboot_state_change(int state, uint32_t arg);
void *btstack_chipset_cc256x_instance(void);