diff --git a/firmware/Makefile b/firmware/Makefile index 65d5a42..25de167 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -225,6 +225,10 @@ endif ifeq ($(USE_OPENBLT),yes) # Reserve start of flash for OpenBLT USE_OPT += -Wl,--defsym=USE_BOOTLOADER=1 + DDEFS += -DUSE_OPENBLT=TRUE + # Shared params + INCDIR += boards/f1_common/openblt + CSRC += boards/f1_common/openblt/shared_params.c endif # diff --git a/firmware/app.ld b/firmware/app.ld index 7909b6d..6beb1a1 100644 --- a/firmware/app.ld +++ b/firmware/app.ld @@ -73,6 +73,20 @@ SECTIONS KEEP(*(.bl.*)) . = ALIGN(4); } > blflash AT > blflash + + /* shared between main FW and OpenBLT */ + .shared (NOLOAD) : + { + . = ALIGN(4); + _sshared = .; + __shared_start__ = _sshared; + *(.shared) + *(.shared.*) + KEEP(*(.shared)) + . = ALIGN(4); + _eshared = .; + __shared_end__ = _eshared; + } > shared } /* Generic rules inclusion.*/ diff --git a/firmware/boards/f1_common/f1_port.cpp b/firmware/boards/f1_common/f1_port.cpp index f91fa76..e1de1ef 100644 --- a/firmware/boards/f1_common/f1_port.cpp +++ b/firmware/boards/f1_common/f1_port.cpp @@ -5,6 +5,13 @@ #include "hal.h" #include "hal_mfs.h" +#if USE_OPENBLT +/* communication with OpenBLT that is plain C, not to modify external file */ +extern "C" { + #include "openblt/shared_params.h" +}; +#endif + // Storage // TODO: runtime detection? static const MFSConfig mfscfg1 = { diff --git a/firmware/boards/f1_common/openblt/STM32F103RB_FLASH.ld b/firmware/boards/f1_common/openblt/STM32F103RB_FLASH.ld index fe1a093..28bd055 100644 --- a/firmware/boards/f1_common/openblt/STM32F103RB_FLASH.ld +++ b/firmware/boards/f1_common/openblt/STM32F103RB_FLASH.ld @@ -31,6 +31,10 @@ /* Entry Point */ ENTRY(Reset_Handler) +/* First 16 bytes of RAM are reserved for shared region + * between FW and bootloader */ +_OpenBLT_Shared_Params_Size = 16; + /* Highest address of the user mode stack */ _estack = 0x20005000; /* end of RAM */ /* Generate a link error if heap and stack don't fit into RAM */ @@ -40,13 +44,26 @@ _Min_Stack_Size = 0x400; /* required amount of stack */ /* Specify the memory areas */ MEMORY { -RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K +SHARED (xrw) : ORIGIN = 0x20000000, LENGTH = _OpenBLT_Shared_Params_Size +RAM (xrw) : ORIGIN = 0x20000000 + _OpenBLT_Shared_Params_Size, LENGTH = 20K - _OpenBLT_Shared_Params_Size FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 8K } /* Define output sections */ SECTIONS { + .shared (NOLOAD) : + { + . = ALIGN(4); + _sshared = .; + __shared_start__ = _sshared; + *(.shared) + *(.shared.*) + KEEP(*(.shared)) + . = ALIGN(4); + _eshared = .; + __shared_end__ = _eshared; + } >SHARED /* The startup code goes first into FLASH */ .isr_vector : { diff --git a/firmware/boards/f1_common/openblt/hooks.c b/firmware/boards/f1_common/openblt/hooks.c index f4ca383..ef8da3c 100644 --- a/firmware/boards/f1_common/openblt/hooks.c +++ b/firmware/boards/f1_common/openblt/hooks.c @@ -2,6 +2,7 @@ * Include files ****************************************************************************************/ #include "boot.h" /* bootloader generic header */ +#include "shared_params.h" /* Shared parameters header */ #include "led.h" /* LED driver header */ #include "stm32f1xx.h" /* STM32 registers and drivers */ #include "stm32f1xx_ll_gpio.h" /* STM32 LL GPIO header */ @@ -29,8 +30,14 @@ void BackDoorInitHook(void) ****************************************************************************************/ blt_bool BackDoorEntryHook(void) { - /* default implementation always activates the bootloader after a reset */ - return BLT_TRUE; + uint8_t value = 0x00; + if (SharedParamsReadByIndex(0, &value) && + (value == 0x01)) { + /* clear */ + SharedParamsWriteByIndex(0, 0x00); + return BLT_TRUE; + } + return BLT_FALSE; } /*** end of BackDoorEntryHook ***/ #endif /* BOOT_BACKDOOR_HOOKS_ENABLE > 0 */ diff --git a/firmware/boards/f1_common/openblt/shared_params.c b/firmware/boards/f1_common/openblt/shared_params.c new file mode 100644 index 0000000..f8e154d --- /dev/null +++ b/firmware/boards/f1_common/openblt/shared_params.c @@ -0,0 +1,250 @@ +/************************************************************************************//** +* \file Demo/ARMCM4_STM32F4_Nucleo_F429ZI_GCC/Prog/shared_params.c +* \brief Shared RAM parameters source file. +* \ingroup Prog_ARMCM4_STM32F4_Nucleo_F429ZI_GCC +* \internal +*---------------------------------------------------------------------------------------- +* C O P Y R I G H T +*---------------------------------------------------------------------------------------- +* Copyright (c) 2021 by Feaser http://www.feaser.com All rights reserved +* +*---------------------------------------------------------------------------------------- +* L I C E N S E +*---------------------------------------------------------------------------------------- +* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +* modify it under the terms of the GNU General Public License as published by the Free +* Software Foundation, either version 3 of the License, or (at your option) any later +* version. +* +* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +* PURPOSE. See the GNU General Public License for more details. +* +* You have received a copy of the GNU General Public License along with OpenBLT. It +* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy. +* +* \endinternal +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include /* Standard definitions (NULL). */ +#include "shared_params.h" /* Shared parameters header. */ + + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +/** \brief Constant parameter buffer identifier. This value is always located as the + * start of the buffer to validate the the RAM contains valid shared parameters. + */ +#define SHARED_PARAMS_BUFFER_ID (0xCAFEBABEu) + + +/**************************************************************************************** +* Type definitions +****************************************************************************************/ +/** \brief Layout of the shared parameters RAM buffer. */ +typedef struct t_shared_params_buffer +{ + /** \brief Fixed buffer identifier to validate that the RAM contains valid shared + * parameters. + */ + uint32_t identifier; + /** \brief Array for the actual parameter data. */ + uint8_t data[SHARED_PARAMS_CFG_BUFFER_DATA_LEN]; + /** \brief Checksum value of all the bytes in the buffer, excluding this checksum + * value of obvious reasons. The checksum is calculated as the Two's + * complement of the sum of the bytes. + */ + uint16_t checksum; +} tSharedParamsBuffer; + +static tSharedParamsBuffer sharedParamsBuffer __attribute__ ((section (".shared"))); + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +static bool SharedParamsValidateBuffer(void); +static void SharedParamsWriteChecksum(void); +static bool SharedParamsVerifyChecksum(void); +static uint16_t SharedParamsCalculateChecksum(void); + + +/************************************************************************************//** +** \brief Initializes the shared RAM parameters module. +** \return none. +** +****************************************************************************************/ +void SharedParamsInit(void) +{ + uint32_t byteIdx; + + /* The shared parameter buffer does not get initialized by the C-startup code. Another + * previously running program could have initialized it, in which case it is ready + * for use and nothing more needs to be done. + */ + if (!SharedParamsValidateBuffer()) + { + /* The shared parameter buffer was not yet initialized by a running program. This + * typically happens after a cold reset where the RAM contents were lost. In this + * case we need to explicitly configure and initialize it, since the C-startup code + * was configured to not do this. + * + * The initialization consists of setting the buffer identifier, zeroing the + * actual parameter data and updating the checksum at the end. + */ + sharedParamsBuffer.identifier = SHARED_PARAMS_BUFFER_ID; + for (byteIdx=0; byteIdx < SHARED_PARAMS_CFG_BUFFER_DATA_LEN; byteIdx++) + { + sharedParamsBuffer.data[byteIdx] = 0; + } + SharedParamsWriteChecksum(); + } +} /*** end of SharedParamsInit ***/ + + +/************************************************************************************//** +** \brief Reads a data byte from the shared parameter buffer at the specified index. +** \param idx Index into the parameter data array. A valid value is between 0 and +** (SHARED_PARAMS_CFG_BUFFER_DATA_LEN - 1). +** \param value Pointer to where the read data value is stored. +** \return True if successful, false otherwise. +** +****************************************************************************************/ +bool SharedParamsReadByIndex(uint32_t idx, uint8_t * value) +{ + bool result = false; + + /* Only continue if the buffer and the specified parameters are valid. */ + if ( (SharedParamsValidateBuffer()) && + (idx < SHARED_PARAMS_CFG_BUFFER_DATA_LEN) && + (value != NULL) ) + { + /* Read the value and update the result. */ + *value = sharedParamsBuffer.data[idx]; + result = true; + } + /* Give the result back to the caller. */ + return result; +} /*** end of SharedParamsReadByIndex ***/ + + +/************************************************************************************//** +** \brief Writes a data byte to the shared parameter buffer at the specified index. +** \param idx Index into the parameter data array. A valid value is between 0 and +** (SHARED_PARAMS_CFG_BUFFER_DATA_LEN - 1). +** \param value Value to write. +** \return True if successful, false otherwise. +** +****************************************************************************************/ +bool SharedParamsWriteByIndex(uint32_t idx, uint8_t value) +{ + bool result = false; + + /* Only continue if the buffer and the specified parameters are valid. */ + if ( (SharedParamsValidateBuffer()) && + (idx < SHARED_PARAMS_CFG_BUFFER_DATA_LEN) ) + { + /* Write the value. */ + sharedParamsBuffer.data[idx] = value; + /* Update the checksum since the contents were just changed. */ + SharedParamsWriteChecksum(); + /* Update the result. */ + result = true; + } + /* Give the result back to the caller. */ + return result; +} /*** end of SharedParamsWriteByIndex ***/ + + +/************************************************************************************//** +** \brief Validates the shared parameter buffer contents by looking at the table +** identifier and verifying its checksum. +** \return True if successful, false otherwise. +** +****************************************************************************************/ +static bool SharedParamsValidateBuffer(void) +{ + bool result = false; + + /* Perform validation. */ + if ( (sharedParamsBuffer.identifier == SHARED_PARAMS_BUFFER_ID) && + (SharedParamsVerifyChecksum()) ) + { + /* The shared parameter buffer is valid, so update the result value. */ + result = true; + } + /* Give the result back to the caller. */ + return result; +} /*** end of SharedParamsValitabeTable ***/ + + +/************************************************************************************//** +** \brief Calculates and writes the checksum into the buffer. +** \return none. +** +****************************************************************************************/ +static void SharedParamsWriteChecksum(void) +{ + /* Calculate and write the checksum. */ + sharedParamsBuffer.checksum = SharedParamsCalculateChecksum(); +} /*** end of SharedParamsWriteChecksum ***/ + + +/************************************************************************************//** +** \brief Calculates and verifies the checksum that is currently present in the +** buffer. +** \return True is the checksum is correct, false otherwise. +** +****************************************************************************************/ +static bool SharedParamsVerifyChecksum(void) +{ + bool result = false; + + /* Calculate and verify the checksum. */ + if (SharedParamsCalculateChecksum() == sharedParamsBuffer.checksum) + { + /* Checksum is correct, so update the result value. */ + result = true; + } + /* Give the result back to the caller. */ + return result; +} /*** end of SharedParamsVerifyChecksum ***/ + + +/************************************************************************************//** +** \brief Calculates and returns the checksum value for the current contents in the +** buffer. The checksum is calculated by taking the sum of all bytes in the +** parameter buffer (excluding the checksum at the end) and them taking the +** two's complement value of it. +** \return The calculated checksum value. +** +****************************************************************************************/ +static uint16_t SharedParamsCalculateChecksum(void) +{ + uint16_t result = 0; + uint32_t byteIdx; + + /* Add the identifier bytes to the checksum. */ + result += (uint8_t)sharedParamsBuffer.identifier; + result += (uint8_t)(sharedParamsBuffer.identifier >> 8u); + result += (uint8_t)(sharedParamsBuffer.identifier >> 16u); + result += (uint8_t)(sharedParamsBuffer.identifier >> 24u); + /* Loop through the parameter data array. */ + for (byteIdx=0; byteIdx /* Standard integer types. */ +#include /* Standard boolean types. */ + + +/**************************************************************************************** +* Configuration macros +****************************************************************************************/ +/** \brief Configuration macro for specifying the size of the data inside the parameter + * buffer. This is the length in bytes of the actual parameter data, so + * excluding the bufferId and checksum. + */ +#define SHARED_PARAMS_CFG_BUFFER_DATA_LEN (16 - 4 - 2) + + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void SharedParamsInit(void); +bool SharedParamsReadByIndex(uint32_t idx, uint8_t * value); +bool SharedParamsWriteByIndex(uint32_t idx, uint8_t value); + + +#endif /* SHARED_PARAMS_H */ +/*********************************** end of shared_params.h ****************************/ diff --git a/firmware/boards/f1_dual_rev1/openblt/blt_conf.h b/firmware/boards/f1_dual_rev1/openblt/blt_conf.h index b1e0232..ec478dc 100644 --- a/firmware/boards/f1_dual_rev1/openblt/blt_conf.h +++ b/firmware/boards/f1_dual_rev1/openblt/blt_conf.h @@ -89,7 +89,7 @@ * also be implemented in a way that disables the backdoor entry altogether. */ /** \brief Enable/disable the backdoor override hook functions. */ -#define BOOT_BACKDOOR_HOOKS_ENABLE (0) +#define BOOT_BACKDOOR_HOOKS_ENABLE (1) /**************************************************************************************** diff --git a/firmware/boards/f1_dual_rev1/wideband_layout.ld b/firmware/boards/f1_dual_rev1/wideband_layout.ld index adc95a8..bd5d7ed 100644 --- a/firmware/boards/f1_dual_rev1/wideband_layout.ld +++ b/firmware/boards/f1_dual_rev1/wideband_layout.ld @@ -2,12 +2,18 @@ * STM32F103xB memory setup. */ +/* OpenBLT code */ +_OpenBLT_Flash_Size = DEFINED(USE_BOOTLOADER) ? 8k : 0; + +/* OpenBLT <-> main FW shared area */ +_OpenBLT_Shared_Params_Size = DEFINED(USE_BOOTLOADER) ? 16 : 0; + MEMORY { /* empty section to keep linker happy */ blflash (rx) : org = 0x08000000, len = 0 - appflash (rx) : org = DEFINED(USE_BOOTLOADER) ? (0x08000000 + 8k) : 0x08000000, len = DEFINED(USE_BOOTLOADER) ? (256k - 8k - 8k) : (256k - 8k) - configflash (rx) : org = 0x08000000 + 256k - 8k, len = 8k + appflash (rx) : org = (0x08000000 + _OpenBLT_Flash_Size), len = (256k - _OpenBLT_Flash_Size - 8k) + configflash (rx) : org = (0x08000000 + 256k - 8k), len = 8k flash1 (rx) : org = 0x00000000, len = 0 flash2 (rx) : org = 0x00000000, len = 0 flash3 (rx) : org = 0x00000000, len = 0 @@ -15,7 +21,8 @@ MEMORY flash5 (rx) : org = 0x00000000, len = 0 flash6 (rx) : org = 0x00000000, len = 0 flash7 (rx) : org = 0x00000000, len = 0 - ram0 (wx) : org = 0x20000200, len = 48k + shared (wx) : org = 0x20000000, len = _OpenBLT_Shared_Params_Size + ram0 (wx) : org = 0x20000000 + _OpenBLT_Shared_Params_Size, len = 48k - _OpenBLT_Shared_Params_Size ram1 (wx) : org = 0x00000000, len = 0 ram2 (wx) : org = 0x00000000, len = 0 ram3 (wx) : org = 0x00000000, len = 0