New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Firmware swapping #6450
Firmware swapping #6450
Changes from 42 commits
647cde9
529c71c
0b6d336
019812f
aa235e7
2ac7dc7
52e0c8b
675c879
e692a47
2778f72
fda0cd0
b35a4ec
bf998ac
d1769bc
5223f4a
a2f738b
41ff852
cc1ccd9
1ef2ba7
d1de5b5
aeddcbe
6027cd4
01ecff6
ce13450
de9143d
adf699d
cb26788
cf1a085
3e9fdc3
8bb151f
511a852
0b8f264
7eeafc5
6e99a86
f3c0b13
0c83e30
600d964
281c1c8
f7021b8
9648d6a
5b3cb9f
98ace9e
1f54964
487f8af
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,24 @@ export CFLAGS_OPT ?= -Os | |
export CFLAGS += $(CFLAGS_CPU) $(CFLAGS_LINK) $(CFLAGS_DBG) $(CFLAGS_OPT) | ||
|
||
export ASFLAGS += $(CFLAGS_CPU) $(CFLAGS_DBG) | ||
|
||
# If the FW_SLOTS flag is set, we will generate a linker script at compile-time | ||
# reflecting the FW_IMAGE_OFFSET and FW_IMAGE_LENGTH values defined in the | ||
# target project's Makefile. | ||
ifeq ($(FW_SLOTS),1) | ||
ifeq ($(FW_SLOT),1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The idea actually is to limit to 2. The next step is to try to get always slot 1 as the bootable slot, download images to slot 2 and then swap both images. The complexity of having several slots is that you need to know before compiling where are you going to put them (e.g. to know where they are the current images to don't overwrite them). |
||
LINKER_SCRIPT = $(CPU_MODEL)_slot1.ld | ||
endif | ||
ifeq ($(FW_SLOT),2) | ||
LINKER_SCRIPT = $(CPU_MODEL)_slot2.ld | ||
endif | ||
endif | ||
|
||
# If we compile a bootloader, set the correct linker script | ||
ifeq ($(BOOTLOADER),1) | ||
export LINKER_SCRIPT = $(CPU_MODEL)-bootloader.ld | ||
endif | ||
|
||
export LINKFLAGS += -L$(RIOTCPU)/$(CPU)/ldscripts -L$(RIOTCPU)/cortexm_common/ldscripts | ||
export LINKER_SCRIPT ?= $(CPU_MODEL).ld | ||
export LINKFLAGS += -T$(LINKER_SCRIPT) -Wl,--fatal-warnings | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
FEATURES_PROVIDED += periph_pm | ||
FEATURES_PROVIDED += periph_slots | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No new line at EOF :-) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -96,21 +96,27 @@ | |
#endif | ||
#endif | ||
|
||
#ifndef FW_SLOTS | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So there's no clock configuration when using OTA? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, we can consider it as an issue. If the clock is initialised again it doesn't boot. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't like this... AFAIK the clock can be initialized several times but there might be registers which might need to be set to the "default" value. EDIT: maybe a different initialization cpu is cleaner. Maybe for the bootloader only the internal oscillator and not all peripherals are needed. |
||
static void clk_init(void); | ||
#endif | ||
|
||
void cpu_init(void) | ||
{ | ||
/* initialize the Cortex-M core */ | ||
cortexm_init(); | ||
|
||
/* initialize system clocks */ | ||
#ifndef FW_SLOTS | ||
clk_init(); | ||
#endif | ||
/* trigger static peripheral initialization */ | ||
periph_init(); | ||
} | ||
|
||
/** | ||
* @brief Configure the clock system of the stm32f1 | ||
*/ | ||
#ifndef FW_SLOTS | ||
static void clk_init(void) | ||
{ | ||
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */ | ||
|
@@ -162,3 +168,4 @@ static void clk_init(void) | |
while ((RCC->CR & RCC_CR_HSIRDY) != 0) {} | ||
#endif | ||
} | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
* Copyright (C) 2013 INRIA | ||
* Copyright (C) 2013, 2016 Inria | ||
* Copyright (C) 2014 Freie Universität Berlin | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser General | ||
|
@@ -18,6 +18,7 @@ | |
* | ||
* @author Alaeddine Weslati <alaeddine.weslati@intia.fr> | ||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de> | ||
* @author Francisco Acosta <francisco.acosta@inria.fr> | ||
*/ | ||
|
||
#ifndef CPU_CONF_H | ||
|
@@ -35,13 +36,123 @@ | |
extern "C" { | ||
#endif | ||
|
||
/** | ||
* @brief Flash page configuration | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. how about factoring the firmware upgrade stuff out of cpu_conf.h? CPU specific defines, like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What defines do you mean specifically? I agree we could move |
||
* @{ | ||
*/ | ||
#define FLASHPAGE_SIZE (2048U) | ||
|
||
#if defined(CPU_MODEL_STM32F103CB) || defined(CPU_MODEL_STM32F103RB) | ||
#define FLASHPAGE_NUMOF (64U) | ||
#elif defined(CPU_MODEL_STM32F103RE) | ||
#define FLASHPAGE_NUMOF (256U) | ||
#endif | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tip: we solved this in one project by defining them in the linker file and the define was just pointing there. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK I will try that. |
||
/** @} */ | ||
|
||
/** | ||
* @brief Offset to reset handler on VTOR | ||
* @{ | ||
*/ | ||
#define VTOR_RESET_HANDLER 0x4 /** One pointer after the beginning */ | ||
/** @} */ | ||
|
||
#if defined(CPU_MODEL_STM32F103RE) | ||
/* | ||
* @brief Flash partitioning for FW slots | ||
* @{ | ||
*/ | ||
|
||
#ifndef FW_METADATA_SPACE | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think all of this should be project specific and not coded in |
||
#define FW_METADATA_SPACE (0x100) | ||
#endif | ||
|
||
#define MAX_FW_SLOTS (2) | ||
#define FW_SLOT_PAGES (120) | ||
#define BOOTLOADER_SPACE (0x4000) | ||
#define FW_SLOT_SIZE FLASHPAGE_SIZE * FW_SLOT_PAGES | ||
#define FW_SLOT_1 FLASH_BASE + BOOTLOADER_SPACE | ||
#define FW_SLOT_1_END FW_SLOT_1 + FW_SLOT_SIZE | ||
#define FW_SLOT_1_PAGE (8) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can some of these be calculated from others? Feels like there's redundant information, especially in combination with FLASHPAGE_SIZE. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes I can try, I just did a straightforward define. |
||
#define FW_SLOT_2 FW_SLOT_1_END | ||
#define FW_SLOT_2_END FW_SLOT_2 + FW_SLOT_SIZE | ||
#define FW_SLOT_2_PAGE (128) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as for the Makefile, I suggest to use FW_SLOT(x) to allow flexibility. Maybe you find a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, as I said before the goal is to limit this to 2 slots so we don't need to deal with such complexity... |
||
|
||
#ifdef FW_SLOTS | ||
#if FW_SLOT == 1 | ||
#define CURRENT_FIRMWARE_ADDR FW_SLOT_1 | ||
#define CURRENT_FIRMWARE_PAGE FW_SLOT_1_PAGE | ||
#define CURRENT_FIRMWARE_END FW_SLOT_1_END | ||
#endif | ||
|
||
#if FW_SLOT == 2 | ||
#define CURRENT_FIRMWARE_ADDR FW_SLOT_2 | ||
#define CURRENT_FIRMWARE_PAGE FW_SLOT_2_PAGE | ||
#define CURRENT_FIRMWARE_END FW_SLOT_2_END | ||
#endif | ||
|
||
#endif /* FW_SLOTS */ | ||
|
||
/** @} */ | ||
|
||
/** | ||
* @brief Get FW internal address for a given slot | ||
* | ||
* @param[in] slot FW slot | ||
* | ||
* @return FW slot address | ||
*/ | ||
static inline uint32_t get_slot_address(uint8_t slot) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest to move this to the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree! |
||
{ | ||
switch (slot) { | ||
case 1: | ||
return FW_SLOT_1; | ||
break; | ||
|
||
case 2: | ||
return FW_SLOT_2; | ||
break; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
/** | ||
* @brief Get internal page for a given slot | ||
* | ||
* @param[in] slot FW slot | ||
* | ||
* @return FW slot page | ||
*/ | ||
static inline uint32_t get_slot_page(uint8_t slot) | ||
{ | ||
switch (slot) { | ||
case 1: | ||
return FW_SLOT_1_PAGE; | ||
break; | ||
|
||
case 2: | ||
return FW_SLOT_2_PAGE; | ||
break; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
#endif /* defined(CPU_MODEL_STM32F103RE) */ | ||
/** @} */ | ||
|
||
/** | ||
* @brief ARM Cortex-M specific CPU configuration | ||
* @{ | ||
*/ | ||
#define CPU_DEFAULT_IRQ_PRIO (1U) | ||
#define CPU_IRQ_NUMOF (60U) | ||
#define CPU_FLASH_BASE FLASH_BASE | ||
#define CPU_DEFAULT_IRQ_PRIO (1U) | ||
#define CPU_IRQ_NUMOF (60U) | ||
|
||
#ifdef FW_SLOTS | ||
#define CPU_FLASH_BASE (CURRENT_FIRMWARE_ADDR + FW_METADATA_SPACE) | ||
#else | ||
#define CPU_FLASH_BASE FLASH_BASE | ||
#endif | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The flash base doesn't change for the MCU, the address of the firmware changes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will change with #6638 . |
||
/** @} */ | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Copyright (C) 2015 Freie Universität Berlin | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
*/ | ||
|
||
/** | ||
* @addtogroup cpu_stm32f1 | ||
* @{ | ||
* | ||
* @file | ||
* @brief Memory definitions for the STM32F103RE | ||
* | ||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de> | ||
* | ||
* @} | ||
*/ | ||
|
||
MEMORY | ||
{ | ||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 16K | ||
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 64K | ||
cpuid (r) : ORIGIN = 0x1ffff7e8, LENGTH = 12 | ||
} | ||
|
||
_cpuid_address = ORIGIN(cpuid); | ||
|
||
INCLUDE cortexm_base.ld |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Copyright (C) 2017 Inria | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
*/ | ||
|
||
/** | ||
* @addtogroup cpu_stm32f1 | ||
* @{ | ||
* | ||
* @file | ||
* @brief Memory definitions for the STM32F103RE Slot 0 | ||
* | ||
* @author Francisco Acosta <francisco.acosta@inria.fr> | ||
* | ||
* @} | ||
*/ | ||
|
||
MEMORY | ||
{ | ||
rom (rx) : ORIGIN = 0x08004100, LENGTH = 0x3C000 | ||
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 64K | ||
cpuid (r) : ORIGIN = 0x1ffff7e8, LENGTH = 12 | ||
} | ||
|
||
_cpuid_address = ORIGIN(cpuid); | ||
|
||
INCLUDE cortexm_base.ld |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Copyright (C) 2017 Inria | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
*/ | ||
|
||
/** | ||
* @addtogroup cpu_stm32f1 | ||
* @{ | ||
* | ||
* @file | ||
* @brief Memory definitions for the STM32F103RE Slot 1 | ||
* | ||
* @author Francisco Acosta <francisco.acosta@inria.fr> | ||
* | ||
* @} | ||
*/ | ||
|
||
MEMORY | ||
{ | ||
rom (rx) : ORIGIN = 0x08040100, LENGTH = 0x3C000 | ||
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 64K | ||
cpuid (r) : ORIGIN = 0x1ffff7e8, LENGTH = 12 | ||
} | ||
|
||
_cpuid_address = ORIGIN(cpuid); | ||
|
||
INCLUDE cortexm_base.ld |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/generate-metadata | ||
/git-fetch-tweetnacl | ||
tweetnacl |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
RIOTBASE := ../../.. | ||
RIOT_INCLUDE = $(RIOTBASE)/sys/include | ||
SHA256_DIR := $(RIOTBASE)/sys/hashes | ||
SHA256_INCLUDE := $(RIOT_INCLUDE)/hashes | ||
METADATA_SRC := generate-metadata.c $(SHA256_DIR)/sha256.c | ||
METADATA_HDR := $(RIOT_INCLUDE)/fw_slots.h $(RIOT_INCLUDE)/hashes/sha256.h | ||
|
||
CFLAGS += -g -O3 -Wall -Wextra -pedantic -std=c99 | ||
|
||
all: bin bin/generate-metadata | ||
|
||
bin: | ||
mkdir bin | ||
|
||
bin/generate-metadata: | ||
$(CC) $(CFLAGS) -I$(RIOT_INCLUDE) $(METADATA_SRC) -o $@ | ||
|
||
clean: | ||
rm -rf bin/generate-metadata |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: missing space