Skip to content

Commit

Permalink
Overhaul F0 bootloader
Browse files Browse the repository at this point in the history
This overhauls the F0 bootloader and associated tooling. The original
bootloader's command can IDs were incompatible with CANopen's address
assignment and so the instigator for this patch was to reassign them to
the reserved unused addresses in CANopen's protocol. While I was there
I've fixed a number of other issues too:
- Fixed linker scripts and memory layout.
- Fixed memory region addressing, using linker defined symbols instead
  of ints.
- Improved compatibility with the protocol that this bootloader is based
  on, AN3154
- Fixed a number of buffer overflows and off-by-one errors in the
  protocol
- Rearranged the metadata section to not have 1kb of empty space in
  every image. This speeds up bootloader image write time.
- Enabled CRC hardware acceleration.
- Added a python based unit test suite
- Overhauled the python write script to be used as a library as well
- Fixed type issues
- Reduced oresat common dependencies
  • Loading branch information
ThirteenFish committed May 21, 2024
1 parent c57c419 commit 2d0ecd2
Show file tree
Hide file tree
Showing 14 changed files with 1,167 additions and 871 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,7 @@ build*/

# Vagrant
/.vagrant/

# Python
__pycache__
.direnv
4 changes: 4 additions & 0 deletions common/can_bootloader.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ uint8_t m0_firmware_temp_buffer[M0_FIRMWARE_UPDATE_WRITE_CHUNK_SIZE];
#endif


#define ORESAT_F0_FLASH_START_ADDRESS 0x08000000
#define ORESAT_F0_FIRMWARE_CRC_ADDRESS 0x0800A7F4
#define ORESAT_F0_FIRMWARE_CODE_ADDRESS 0x0800A804

/**
* Used to fully initialize a can_bootloader_config_t structure.
*
Expand Down
43 changes: 25 additions & 18 deletions common/include/oresat_f0.h
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
#ifndef COMMON_INCLUDE_ORESAT_F0_H_
#define COMMON_INCLUDE_ORESAT_F0_H_

/* TODO: It'd be nice to derive these values from the linker script as the authoratative source */
#define ORESAT_F0_FLASH_START_ADDRESS 0x08000000

#define ORESAT_F0_FIRMWARE_CRC_ADDRESS 0x0800A000
#define ORESAT_F0_FIRMWARE_LENGTH_ADDRESS (ORESAT_F0_FIRMWARE_CRC_ADDRESS + 0x4)
#define ORESAT_F0_FIRMWARE_VERSION_ADDRESS (ORESAT_F0_FIRMWARE_CRC_ADDRESS + 0x8)
#define ORESAT_F0_FIRMWARE_CODE_ADDRESS (ORESAT_F0_FIRMWARE_CRC_ADDRESS + 0x400)
#define ORESAT_F0_FIRMWARE_CODE_END_ADDRESS 0x0803C000

#define ORESAT_F0_FIRMWARE_MAXIMUM_LENGTH (ORESAT_F0_FIRMWARE_CODE_END_ADDRESS - ORESAT_F0_FIRMWARE_CRC_ADDRESS)


#ifdef __cplusplus
extern "C" {
#endif

extern int __flash0_base__;
extern size_t __flash0_size__;
extern int __flash0_end__;
extern int __flash1_base__;
extern size_t __flash1_size__;
extern int __flash1_end__;
// See STM32F091xC-bootloader.ld/STM32F4091xC-app.ld for definitions and
// rules_memory.ld for declarations.
extern uint8_t __flash0_base__[];
extern uint8_t __flash0_end__[];
extern uint8_t __flash1_base__[];
extern uint8_t __flash1_end__[];
extern uint8_t __flash2_base__[];
extern uint8_t __flash2_end__[];
extern uint8_t __ram0_base__[];
extern uint8_t __ram0_end__[];
extern uint8_t __ram1_base__[];
extern uint8_t __ram1_end__[];

// The __*_size__ symbols are weird. The contents aren't relevent, it's the
// address, converted to a number, which is the represented region size.
extern const void __flash0_size__;
extern const void __flash1_size__;
extern const void __flash2_size__;
extern const void __ram0_size__;
extern const void __ram1_size__;
#define FLASH0_SIZE ((const uint32_t)(&__flash0_size__))
#define FLASH1_SIZE ((const uint32_t)(&__flash1_size__))
#define FLASH2_SIZE ((const uint32_t)(&__flash2_size__))
#define RAM0_SIZE ((const uint32_t)(&__ram0_size__))
#define RAM1_SIZE ((const uint32_t)(&__ram1_size__))

#ifdef __cplusplus
}
Expand Down
15 changes: 10 additions & 5 deletions common/oresat_f0.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@


/**
* This function should be called on applications using the STM32F091xC-app.ld linker script and using the bootloader to run them.
* This function is called by applications using the STM32F091xC-app.ld
* linker script and using the bootloader to run them. It overwrites a weak
* symbol from ChibiOS's CRT0 and so will be called late in the init sequence.
*/
void __late_init(void) {
/* Relocate by software the vector table to the internal SRAM at 0x20000000 ***/
/* Copy the vector table from the Flash (mapped at the base of the application
load address 0x08003000) to the base address of the SRAM at 0x20000000. */
// Relocate by software the vector table to the internal SRAM at 0x20000000.
// The vector table comes from flash, mapped at the base of the application
// region, load address __flash2_base__ (0x0800A800).
//
// The SRAM then gets remapped to 0x00000000 to function as the real vector
// table

memcpy((void *)0x20000000, (void *)ORESAT_F0_FIRMWARE_CODE_ADDRESS, 0xC0);
memcpy(__ram0_base__, __flash2_base__, 0xC0);
__DSB();
/* Remap SRAM at 0x00000000 */
SYSCFG->CFGR1 |= SYSCFG_CFGR1_MEM_MODE;
Expand Down
52 changes: 17 additions & 35 deletions ld/STM32F091xC-app.ld
Original file line number Diff line number Diff line change
@@ -1,34 +1,16 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/*
* STM32F091xC memory setup.
*/
/* STM32F091xC memory setup. It has 256k flash (128 2k pages) and 32k SRAM */
MEMORY
{
flash0 (rx) : org = 0x08000000, len = 40k /* Bootloader */
flash1 (rx) : org = 0x0800A400, len = 199k /* Application */
flash2 (rx) : org = 0x00000000, len = 0
flash1 (rx) : org = 0x0800A000, len = 2k /* Metadata */
flash2 (rx) : org = 0x0800A800, len = 214k /* Application */
flash3 (rx) : org = 0x00000000, len = 0
flash4 (rx) : org = 0x00000000, len = 0
flash5 (rx) : org = 0x00000000, len = 0
flash6 (rx) : org = 0x00000000, len = 0
flash7 (rx) : org = 0x00000000, len = 0
ram0 (wx) : org = 0x20000000, len = 32k
ram1 (wx) : org = 0x20000400, len = 31k
ram0 (wx) : org = 0x20000000, len = 32708 /* 32k - 4 (bootloader magic) */
ram1 (wx) : org = 0x20000400, len = 31k /* 32k - 1k (fw vector table) */
ram2 (wx) : org = 0x00000000, len = 0
ram3 (wx) : org = 0x00000000, len = 0
ram4 (wx) : org = 0x00000000, len = 0
Expand All @@ -41,27 +23,27 @@ MEMORY
and a load region (_LMA suffix).*/

/* Flash region to be used for exception vectors.*/
REGION_ALIAS("VECTORS_FLASH", flash1);
REGION_ALIAS("VECTORS_FLASH_LMA", flash1);
REGION_ALIAS("VECTORS_FLASH", flash2);
REGION_ALIAS("VECTORS_FLASH_LMA", flash2);

/* Flash region to be used for constructors and destructors.*/
REGION_ALIAS("XTORS_FLASH", flash1);
REGION_ALIAS("XTORS_FLASH_LMA", flash1);
REGION_ALIAS("XTORS_FLASH", flash2);
REGION_ALIAS("XTORS_FLASH_LMA", flash2);

/* Flash region to be used for code text.*/
REGION_ALIAS("TEXT_FLASH", flash1);
REGION_ALIAS("TEXT_FLASH_LMA", flash1);
REGION_ALIAS("TEXT_FLASH", flash2);
REGION_ALIAS("TEXT_FLASH_LMA", flash2);

/* Flash region to be used for read only data.*/
REGION_ALIAS("RODATA_FLASH", flash1);
REGION_ALIAS("RODATA_FLASH_LMA", flash1);
REGION_ALIAS("RODATA_FLASH", flash2);
REGION_ALIAS("RODATA_FLASH_LMA", flash2);

/* Flash region to be used for various.*/
REGION_ALIAS("VARIOUS_FLASH", flash1);
REGION_ALIAS("VARIOUS_FLASH_LMA", flash1);
REGION_ALIAS("VARIOUS_FLASH", flash2);
REGION_ALIAS("VARIOUS_FLASH_LMA", flash2);

/* Flash region to be used for RAM(n) initialization data.*/
REGION_ALIAS("RAM_INIT_FLASH_LMA", flash1);
REGION_ALIAS("RAM_INIT_FLASH_LMA", flash2);

/* RAM region to be used for Main stack. This stack accommodates the processing
of all exceptions and interrupts.*/
Expand All @@ -73,7 +55,7 @@ REGION_ALIAS("PROCESS_STACK_RAM", ram1);

/* RAM region to be used for data segment.*/
REGION_ALIAS("DATA_RAM", ram1);
REGION_ALIAS("DATA_RAM_LMA", flash1);
REGION_ALIAS("DATA_RAM_LMA", flash2);

/* RAM region to be used for BSS segment.*/
REGION_ALIAS("BSS_RAM", ram1);
Expand Down
28 changes: 5 additions & 23 deletions ld/STM32F091xC-bootloader.ld
Original file line number Diff line number Diff line change
@@ -1,34 +1,16 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/*
* STM32F091xC memory setup.
*/
/* STM32F091xC memory setup. It has 256k flash (128 2k pages) and 32k SRAM */
MEMORY
{
flash0 (rx) : org = 0x08000000, len = 40k /* Bootloader */
flash1 (rx) : org = 0x0800A400, len = 199k /* Application */
flash2 (rx) : org = 0x00000000, len = 0
flash1 (rx) : org = 0x0800A000, len = 2k /* Metadata */
flash2 (rx) : org = 0x0800A800, len = 214k /* Application */
flash3 (rx) : org = 0x00000000, len = 0
flash4 (rx) : org = 0x00000000, len = 0
flash5 (rx) : org = 0x00000000, len = 0
flash6 (rx) : org = 0x00000000, len = 0
flash7 (rx) : org = 0x00000000, len = 0
ram0 (wx) : org = 0x20000000, len = 32k
ram1 (wx) : org = 0x20000400, len = 31k
ram0 (wx) : org = 0x20000000, len = 32708 /* 32k - 4 for bootloader magic */
ram1 (wx) : org = 0x20000400, len = 31k /* 32k - 1k for vector table */
ram2 (wx) : org = 0x00000000, len = 0
ram3 (wx) : org = 0x00000000, len = 0
ram4 (wx) : org = 0x00000000, len = 0
Expand Down
7 changes: 1 addition & 6 deletions src/f0/app_bootloader/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

# Compiler options here.
ifeq ($(USE_OPT),)
USE_OPT = -Og -ggdb -fomit-frame-pointer -falign-functions=16
USE_OPT = -Og -ggdb -falign-functions=16
endif

# C specific options here (added to USE_OPT).
Expand Down Expand Up @@ -106,8 +106,6 @@ DEPDIR := $(APP_ROOT)/.dep
BOARDDIR = $(PROJ_ROOT)/boards/$(BOARD)

# Project specific files.
#include $(PROJ_SRC)/oresat.mk
include $(PROJ_SRC)/bootloader.mk
include $(PROJ_SRC)/util.mk

# Licensing files.
Expand All @@ -125,9 +123,6 @@ include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk
# Auto-build files in ./source recursively.
include $(CHIBIOS)/tools/mk/autobuild.mk
# Other files (optional).
#include $(CHIBIOS)/test/lib/test.mk
#include $(CHIBIOS)/test/rt/rt_test.mk
#include $(CHIBIOS)/test/oslib/oslib_test.mk
include $(CHIBIOS)/os/hal/lib/streams/streams.mk

# Define linker script file here
Expand Down
Loading

0 comments on commit 2d0ecd2

Please sign in to comment.