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:
@ -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 )
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -17,5 +17,5 @@
|
||||
|
||||
struct ab_boot_config
|
||||
{
|
||||
uint32_t boot_partition;
|
||||
uint32_t *boot_partition;
|
||||
};
|
||||
|
@ -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/ :
|
||||
{
|
||||
|
26
main.cpp
26
main.cpp
@ -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
10
persist/persist.c
Normal 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
39
persist/persist.h
Normal 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();
|
||||
}
|
Reference in New Issue
Block a user