Add persist RAM area for passing data across resets; implement booting from a partition specified in the persist RAM area

This commit is contained in:
Michael Ehrenreich
2022-04-28 21:05:09 +02:00
parent f29c4d182e
commit bda583b94c
7 changed files with 126 additions and 27 deletions

View File

@ -76,6 +76,7 @@ set(COMMON_SOURCES
defines.h
main.cpp
system_stm32f1xx.c
persist/persist.c
)
#
@ -216,7 +217,11 @@ add_custom_target(greyhash ALL SOURCES greyhash.hex greyhash.bin)
add_custom_target(flash-greyhash COMMAND st-flash --reset write greyhash.bin ${A_FIRMWARE_APP_BASE} SOURCES greyhash.bin DEPENDS greyhash.bin)
add_executable(ab_boot.elf ab_boot/ab_boot.c system_stm32f1xx.c)
add_executable(ab_boot.elf
ab_boot/ab_boot.c
system_stm32f1xx.c
persist/persist.c
)
target_link_options(ab_boot.elf PRIVATE ${COMMON_LINKER_FLAGS} ${AB_BOOT_FIRMWARE_LINKER_FLAGS})
target_link_libraries(ab_boot.elf stm32_hal)
target_compile_options(ab_boot.elf PRIVATE )

View File

@ -1,31 +1,51 @@
#include <stdint.h>
#include <stdbool.h>
#include "stm32f1xx_hal.h"
#include "ab_boot.h"
#include "persist/persist.h"
int main()
{
struct ab_boot_config *config = (struct ab_boot_config *)CONFIG_START;
uint32_t *bootp;
if (config->boot_partition >= FLASH_START &&
config->boot_partition < FLASH_END &&
(config->boot_partition & 3) == 0)
{
bootp = (uint32_t *)config->boot_partition;
}
else
{
bootp = (uint32_t *)APP_A_START;
}
uint32_t sp = bootp[0];
uint32_t entry = bootp[1];
static inline void __attribute__((noreturn)) boot_image(uint32_t sp, uint32_t entry) {
asm volatile(
" mov sp, %0 \n"
" bx %1 \n"
" blx %1 \n"
"1: b 1b \n"
:
: "r" (sp), "r" (entry)
);
__builtin_unreachable();
}
static bool is_valid_boot_address(uint32_t *bootp)
{
return (uint32_t)bootp >= FLASH_START &&
(uint32_t)bootp < FLASH_END &&
((uint32_t)bootp & 3) == 0;
}
int main()
{
struct ab_boot_config *flash_config = (struct ab_boot_config *)CONFIG_START;
struct ab_boot_config *config = NULL;
if (is_persist_valid() &&
is_valid_boot_address(persist.ab_boot_config.boot_partition))
{
// Invalidate persist
persist.checksum = 0;
config = &persist.ab_boot_config;
}
else if (is_valid_boot_address(flash_config->boot_partition))
{
config = flash_config;
}
uint32_t *bootp;
if (config)
bootp = config->boot_partition;
else
bootp = (uint32_t *)APP_A_START;
uint32_t sp = bootp[0];
uint32_t entry = bootp[1];
boot_image(sp, entry);
}

View File

@ -17,5 +17,5 @@
struct ab_boot_config
{
uint32_t boot_partition;
uint32_t *boot_partition;
};

View File

@ -39,7 +39,8 @@ _Min_Stack_Size = 0x400; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 48K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 47K
PERSIST (rw) : ORIGIN = 0x2000BC00, LENGTH = 1K
FLASH (rx) : ORIGIN = _App_Base, LENGTH = _App_Length
CONFIG(r) : ORIGIN = 0x0803f800, LENGTH = 2K
}
@ -155,6 +156,14 @@ SECTIONS
/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of RAM area */
.persist :
{
. = ALIGN(4);
persist = .;
. += LENGTH(PERSIST);
_epersist = .;
} > PERSIST
/* Remove information from the standard libraries */
/DISCARD/ :
{

View File

@ -27,6 +27,8 @@
#include <cstring>
#include "stm32f1xx_hal.h"
#include "ab_boot/ab_boot.h"
#include "persist/persist.h"
#include "defines.h"
#include "config.h"
@ -1364,22 +1366,36 @@ void MX_ADC2_Init()
__HAL_ADC_ENABLE(&hadc2);
}
#ifdef FEATURE_BUTTON
void poweroff()
void shutdown()
{
// if (abs(speed) < 20) { // wait for the speed to drop, then shut down -> this is commented out for SAFETY reasons
buzzer.pattern = 0;
left.enable = false;
right.enable = 0;
right.enable = false;
for (int i = 0; i < 8; i++) {
buzzer.freq = (uint8_t)i;
HAL_Delay(50);
}
}
#ifdef FEATURE_BUTTON
void poweroff()
{
shutdown();
HAL_GPIO_WritePin(OFF_PORT, OFF_PIN, GPIO_PIN_RESET);
for (int i = 0; i < 5; i++)
HAL_Delay(1000);
// }
}
#endif
#ifdef FEATURE_CAN
void reboot_new_image(uint32_t *bootp)
{
shutdown();
request_boot_image(bootp);
HAL_NVIC_SystemReset();
}
#endif

10
persist/persist.c Normal file
View File

@ -0,0 +1,10 @@
#include <assert.h>
#include "persist.h"
#include "ab_boot/ab_boot.h"
// keep this in sync with the linker script
#define PERSIST_SIZE 1024
extern struct persist_data persist;
static_assert(sizeof(persist) < PERSIST_SIZE);

39
persist/persist.h Normal file
View File

@ -0,0 +1,39 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "ab_boot/ab_boot.h"
struct persist_data {
struct ab_boot_config ab_boot_config;
uint32_t checksum;
};
extern struct persist_data persist;
static inline uint32_t calculate_persist_checksum() {
uint32_t checksum = 0;
uint32_t *pd = (uint32_t *)&persist;
for (int i = 0; i < (sizeof(persist) - 4) / 4; i++) {
checksum += pd[i];
checksum = (checksum >> 3) | (checksum << 29);
}
checksum = ~checksum;
return checksum;
}
static inline void update_persist_checksum() {
persist.checksum = calculate_persist_checksum();
}
static inline bool is_persist_valid() {
return calculate_persist_checksum() == persist.checksum;
}
static inline void request_boot_image(uint32_t *bootp) {
persist.ab_boot_config.boot_partition = bootp;
update_persist_checksum();
}