-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'edge' into flex-stacker-gparser-full-fix
- Loading branch information
Showing
17 changed files
with
583 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Flex-Stacker Firmware | ||
|
||
This directory has the code for the Flex-Stacker. | ||
|
||
## Relevant build system targets | ||
|
||
### Cross-build | ||
When cross-compiling the firmware (using the `stm32-cross` cmake preset, running `cmake --build ./build-stm32-cross`), you can | ||
- Build the firmware: `cmake --build ./build-stm32-cross --target flex-stacker` | ||
- Build the firmware, connect to a debugger, and upload it: `cmake --build ./build-stm32-cross --target flex-stacker-debug` | ||
- Lint the firmware: `cmake --build ./build-stm32-cross --target flex-stacker-lint` | ||
- Format the firmware: `cmake --build ./build-stm32-cross --target flex-stacker-format` | ||
- Flash the firmware to a board: `cmake --build ./build-stm32-cross --target flex-stacker-flash` | ||
- Flash the firmware __and__ the startup application to a board: `cmake --build ./build-stm32-cross --target flex-stacker-image-flash` | ||
- Builds flex-stacker-image.hex, suitable for use with stm's programmer: `cmake --build ./build-stm32-cross --target flex-stacker-image-hex` | ||
- Builds flex-stacker-image.bin, suitable for some other programmers: `cmake --build ./build-stm32-cross --target flex-stacker-image-bin` | ||
- Build the startup app, which is also packaged into the image files: `cmake --build ./build-stm32-cross --target flex-stacker-startup` | ||
- Delete all of the contents on a flex-stacker MCU, and wipe any memory protection: `cmake --build ./build-stm32-cross --target flex-stacker-clear` | ||
|
||
The default board revision is currently a1 (EVT). You can change the revision to the NFF board by running cmake `stm32-cross` preset again with | ||
`cmake --preset stm32-cross -DSTACKER_REVISION=nff .` | ||
before re-building the firmware. | ||
|
||
### Debugging | ||
There's a target called `flex-stacker-debug` that will build the firmware and then spin up a gdb, spin up an openocd, and connect the two; load some useful python scripts; connect to an st-link that should be already plugged in; automatically upload the firmware, and drop you at a breakpoint at boot time. This should all download itself and be ready as soon as `cmake --preset=stm32-cross .` completes, with one exception: Gdb python support is incredibly weird and will somehow always find your python2 that the system has, no matter how hard you try to avoid this. The scripts should work fine, but you have to install setuptools so `pkg_resources` is available, since this isn't really something we want to "install" by downloading it to some random directory and dropping it in gdb's embedded python interpreter's package path, so do the lovely | ||
|
||
`wget https://bootstrap.pypa.io/pip/2.7/get-pip.py` | ||
`python2.7 ./get-pip.py` | ||
|
||
You do not have to sudo this, and should not sudo it, it works perfectly fine as a user install. | ||
|
||
Once you spin this up, it provides peripheral register names and access through https://github.com/1udo6arre/svd-tools. | ||
That means you can do stuff like | ||
`help svd` - get info on svd commands (you don't have to do the `svd /path/to/svd`, that's done automatically) | ||
`svd get nvic` - print all the nvic registers | ||
|
||
### Host-build | ||
When compiling the firmware using your local compiler (using the `stm32-host` cmake preset, running `cmake --build ./build-stm32-host`), you can | ||
- Build tests: `cmake --build ./build-stm32-host --target flex-stacker-tests` | ||
- Run tests: `cmake --build ./build-stm32-host --target test` | ||
- Format tests: `cmake --build ./build-stm32-host --target flex-stacker-format` | ||
- Build simulator: `cmake --build ./build-stm32-host --target flex-stacker-simulator` | ||
- Build and Test: `cmake --build ./build-stm32-host --target flex-stacker-build-and-test` | ||
|
||
## File Structure | ||
- `./tests/` contains the test-specific entrypoints and actual test code | ||
- `./firmware` contains the code that only runs on the device itself | ||
- `./simulator` contains the code that runs a local simulator | ||
- `./src` contains the code that can be either cross- or host-compiled, and therefore can and should be tested | ||
|
||
## Style | ||
|
||
We enforce style with [clang-format](https://clang.llvm.org/docs/ClangFormat.html), using the [google C++ style](https://google.github.io/styleguide/cppguide.html). We lint using [clang-tidy](https://clang.llvm.org/extra/clang-tidy/). The configurations for these tools are in the root of the repo (they're hidden files on Unix-likes, `.clang-tidy` and `.clang-format`). | ||
|
||
We use [Catch2](https://github.com/catchorg/Catch2) for testing. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
stm32-modules/flex-stacker/firmware/system/freertos_system_task.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
#include "firmware/freertos_tasks.hpp" | ||
#include "firmware/system_policy.hpp" | ||
#include "flex-stacker/system_task.hpp" | ||
|
||
namespace system_control_task { | ||
|
||
enum class Notifications : uint8_t { | ||
INCOMING_MESSAGE = 1, | ||
}; | ||
|
||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) | ||
static tasks::FirmwareTasks::SystemQueue | ||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) | ||
_queue(static_cast<uint8_t>(Notifications::INCOMING_MESSAGE), | ||
"System Queue"); | ||
|
||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) | ||
static auto _top_task = system_task::SystemTask(_queue, nullptr); | ||
|
||
auto run(tasks::FirmwareTasks::QueueAggregator* aggregator) -> void { | ||
auto* handle = xTaskGetCurrentTaskHandle(); | ||
_queue.provide_handle(handle); | ||
aggregator->register_queue(_queue); | ||
_top_task.provide_aggregator(aggregator); | ||
|
||
auto policy = SystemPolicy(); | ||
while (true) { | ||
_top_task.run_once(policy); | ||
} | ||
} | ||
|
||
}; // namespace system_control_task |
60 changes: 60 additions & 0 deletions
60
stm32-modules/flex-stacker/firmware/system/system_hardware.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
#include "firmware/system_hardware.h" | ||
#include "stm32g4xx_hal.h" | ||
#include "stm32g4xx_hal_rcc.h" | ||
#include "stm32g4xx_hal_cortex.h" | ||
#include "stm32g4xx_hal_tim.h" | ||
|
||
/** Local defines */ | ||
// This is the start of the sys memory region for the STM32G491 | ||
// from the reference manual and STM application note AN2606 | ||
#define SYSMEM_START 0x1fff0000 | ||
#define SYSMEM_BOOT (SYSMEM_START + 4) | ||
|
||
// address 4 in the bootable region is the address of the first instruction that | ||
// should run, aka the data that should be loaded into $pc. | ||
const uint32_t *const sysmem_boot_loc = (uint32_t*)SYSMEM_BOOT; | ||
|
||
/** PUBLIC FUNCTION IMPLEMENTATION */ | ||
|
||
void system_hardware_enter_bootloader(void) { | ||
|
||
// We have to uninitialize as many of the peripherals as possible, because the bootloader | ||
// expects to start as the system comes up | ||
|
||
// The HAL has ways to turn off all the core clocking and the clock security system | ||
HAL_RCC_DisableLSECSS(); | ||
HAL_RCC_DeInit(); | ||
|
||
// systick should be off at boot | ||
SysTick->CTRL = 0; | ||
SysTick->LOAD = 0; | ||
SysTick->VAL = 0; | ||
|
||
/* Clear Interrupt Enable Register & Interrupt Pending Register */ | ||
for (int i=0;i<8;i++) | ||
{ | ||
NVIC->ICER[i]=0xFFFFFFFF; | ||
NVIC->ICPR[i]=0xFFFFFFFF; | ||
} | ||
|
||
// We have to make sure that the processor is mapping the system memory region to address 0, | ||
// which the bootloader expects | ||
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); | ||
// and now we're ready to set the system up to start executing system flash. | ||
// arm cortex initialization means that | ||
// address 0 in the bootable region is the address where the processor should start its stack | ||
// which we have to do as late as possible because as soon as we do this the c and c++ runtime | ||
// environment is no longer valid | ||
__set_MSP(*((uint32_t*)SYSMEM_START)); | ||
|
||
// finally, jump to the bootloader. we do this in inline asm because we need | ||
// this to be a naked call (no caller-side prep like stacking return addresses) | ||
// and to have a naked function you need to define it as a function, not a | ||
// function pointer, and we don't statically know the address here since it is | ||
// whatever's contained in that second word of the bsystem memory region. | ||
asm volatile ( | ||
"bx %0" | ||
: // no outputs | ||
: "r" (*sysmem_boot_loc) | ||
: "memory" ); | ||
} |
59 changes: 59 additions & 0 deletions
59
stm32-modules/flex-stacker/firmware/system/system_policy.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
#include "firmware/system_policy.hpp" | ||
|
||
#include <array> | ||
#include <iterator> | ||
#include <ranges> | ||
|
||
#include "firmware/system_hardware.h" | ||
#include "firmware/system_serial_number.h" | ||
#include "flex-stacker/errors.hpp" | ||
|
||
// NOLINTNEXTLINE(readability-convert-member-functions-to-static) | ||
auto SystemPolicy::enter_bootloader() -> void { | ||
system_hardware_enter_bootloader(); | ||
} | ||
|
||
// NOLINTNEXTLINE(readability-convert-member-functions-to-static) | ||
auto SystemPolicy::set_serial_number( | ||
std::array<char, SYSTEM_SERIAL_NUMBER_LENGTH> system_serial_number) | ||
-> errors::ErrorCode { | ||
writable_serial to_write_struct = {0}; | ||
// convert bytes to uint64_t for system_set_serial_number | ||
// write to 8 chars to each of first 3 addresses on last page of flash | ||
for (uint8_t address = 0; address < ADDRESSES; address++) { | ||
auto *input = | ||
std::next(system_serial_number.begin(), address * ADDRESS_LENGTH); | ||
auto *limit = std::next(input, ADDRESS_LENGTH); | ||
uint64_t to_write = 0; | ||
for (ssize_t byte_index = sizeof(to_write) - 1; | ||
input != limit && byte_index >= 0; | ||
std::advance(input, 1), byte_index--) { | ||
to_write |= (static_cast<uint64_t>(*input) << (byte_index * 8)); | ||
} | ||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index) | ||
to_write_struct.contents[address] = to_write; | ||
} | ||
if (!system_set_serial_number(&to_write_struct)) { | ||
return errors::ErrorCode::SYSTEM_SERIAL_NUMBER_HAL_ERROR; | ||
} | ||
return errors::ErrorCode::NO_ERROR; | ||
} | ||
|
||
// NOLINTNEXTLINE(readability-convert-member-functions-to-static) | ||
auto SystemPolicy::get_serial_number() | ||
-> std::array<char, SYSTEM_SERIAL_NUMBER_LENGTH> { | ||
std::array<char, SYSTEM_SERIAL_NUMBER_LENGTH> serial_number_array = { | ||
"EMPTYSN"}; | ||
for (uint8_t address = 0; address < ADDRESSES; address++) { | ||
uint64_t written_serial_number = system_get_serial_number(address); | ||
// int to bytes | ||
auto *output = | ||
std::next(serial_number_array.begin(), address * ADDRESS_LENGTH); | ||
auto *limit = std::next(output, ADDRESS_LENGTH); | ||
for (ssize_t iter = sizeof(written_serial_number) - 1; | ||
iter >= 0 && output != limit; iter--, std::advance(output, 1)) { | ||
*output = (written_serial_number >> (iter * 8)); | ||
} | ||
} | ||
return serial_number_array; | ||
} |
47 changes: 47 additions & 0 deletions
47
stm32-modules/flex-stacker/firmware/system/system_serial_number.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#include <stdlib.h> | ||
|
||
#include "firmware/system_serial_number.h" | ||
|
||
#include "stm32g4xx_hal.h" | ||
#include "stm32g4xx_hal_def.h" | ||
#include "stm32g4xx_hal_flash.h" | ||
#include "stm32g4xx_hal_flash_ex.h" | ||
|
||
static const uint32_t PAGE_ADDRESS = 0x0807F800; //last page in flash memory, 0x0807F800 for 512K (FF board) FLASH | ||
static const uint32_t PAGE_INDEX = 255; //last page index in flash memory | ||
static const uint8_t ADDRESS_SIZE = 8; | ||
|
||
bool system_set_serial_number(struct writable_serial* to_write) { | ||
FLASH_EraseInitTypeDef pageToErase = { | ||
.TypeErase = FLASH_TYPEERASE_PAGES, | ||
.Banks = FLASH_BANK_1, | ||
.Page = PAGE_INDEX, | ||
.NbPages = 1}; | ||
uint32_t pageErrorPtr = 0; //pointer to variable that contains the configuration information on faulty page in case of error | ||
uint32_t ProgramAddress1 = PAGE_ADDRESS; | ||
uint32_t ProgramAddress2 = PAGE_ADDRESS + ADDRESS_SIZE; | ||
uint32_t ProgramAddress3 = PAGE_ADDRESS + (2 * ADDRESS_SIZE); | ||
|
||
HAL_StatusTypeDef status = HAL_FLASH_Unlock(); | ||
if (status == HAL_OK) { | ||
status = HAL_FLASHEx_Erase(&pageToErase, &pageErrorPtr); | ||
if (status == HAL_OK) { | ||
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, ProgramAddress1, to_write->contents[0]); | ||
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, ProgramAddress2, to_write->contents[1]); | ||
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, ProgramAddress3, to_write->contents[2]); | ||
if (status == HAL_OK) { | ||
status = HAL_FLASH_Lock(); | ||
} | ||
} | ||
else { | ||
// Safe to drop status because this always succeeds | ||
(void) HAL_FLASH_Lock(); | ||
} | ||
} | ||
return (status == HAL_OK); | ||
} | ||
|
||
uint64_t system_get_serial_number(uint8_t address) { | ||
uint32_t AddressToRead = PAGE_ADDRESS + (address * ADDRESS_SIZE); | ||
return *(uint64_t*)AddressToRead; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
stm32-modules/include/flex-stacker/firmware/system_hardware.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#ifndef SYSTEM_HARDWARE_H__ | ||
#define SYSTEM_HARDWARE_H__ | ||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif // __cplusplus | ||
|
||
#include <stdbool.h> | ||
|
||
/** | ||
* @brief Enter the bootloader. This function never returns. | ||
*/ | ||
void system_hardware_enter_bootloader(void); | ||
|
||
#ifdef __cplusplus | ||
} // extern "C" | ||
#endif // __cplusplus | ||
#endif // _SYSTEM_HARDWARE_H__ |
24 changes: 24 additions & 0 deletions
24
stm32-modules/include/flex-stacker/firmware/system_policy.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#pragma once | ||
|
||
#include <array> | ||
|
||
#include "firmware/system_hardware.h" | ||
#include "firmware/system_serial_number.h" | ||
#include "flex-stacker/errors.hpp" | ||
#include "systemwide.h" | ||
|
||
class SystemPolicy { | ||
private: | ||
static constexpr std::size_t SYSTEM_SERIAL_NUMBER_LENGTH = | ||
SYSTEM_WIDE_SERIAL_NUMBER_LENGTH; | ||
static constexpr uint8_t ADDRESS_LENGTH = 8; | ||
static constexpr uint8_t ADDRESSES = | ||
SYSTEM_SERIAL_NUMBER_LENGTH / ADDRESS_LENGTH; | ||
|
||
public: | ||
auto enter_bootloader() -> void; | ||
auto set_serial_number( | ||
std::array<char, SYSTEM_SERIAL_NUMBER_LENGTH> system_serial_number) | ||
-> errors::ErrorCode; | ||
auto get_serial_number() -> std::array<char, SYSTEM_SERIAL_NUMBER_LENGTH>; | ||
}; |
Oops, something went wrong.