feat: linker support for firmware in external flash (#5290)
This commit is contained in:
@@ -590,9 +590,17 @@ if(ACCESS_DENIED)
|
||||
target_link_libraries(firmware AccessDenied)
|
||||
endif()
|
||||
|
||||
if(FIRMWARE_STRIP_BOOTLOADER)
|
||||
# Strip bootloader from binary
|
||||
message("-- Strip bootloader from firmware binary")
|
||||
set(OBJCOPY_ARGS -R .bootloader)
|
||||
else()
|
||||
message("-- Bootloader contained in firmware binary")
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
TARGET firmware POST_BUILD
|
||||
COMMAND ${CMAKE_OBJCOPY} -O binary firmware.elf firmware.bin
|
||||
COMMAND ${CMAKE_OBJCOPY} -O binary ${OBJCOPY_ARGS} firmware.elf firmware.bin
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
} > REGION_TEXT AT> REGION_TEXT_STORAGE
|
||||
|
||||
.ARM :
|
||||
{
|
||||
PROVIDE(__exidx_start = .);
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
PROVIDE(__exidx_end = .);
|
||||
} > FLASH
|
||||
} > REGION_TEXT AT> REGION_TEXT_STORAGE
|
||||
|
||||
.reboot_buffer(NOLOAD) :
|
||||
{
|
||||
@@ -26,7 +26,7 @@
|
||||
*(.data .data*) /* .data sections */
|
||||
. = ALIGN(4);
|
||||
_edata = .; /* define a global symbol at data end */
|
||||
} > REGION_DATA AT> FLASH
|
||||
} > REGION_DATA AT> REGION_TEXT_STORAGE
|
||||
|
||||
/* used by the startup to initialize data */
|
||||
_sidata = LOADADDR(.data);
|
||||
|
||||
@@ -7,30 +7,46 @@ INCLUDE definitions.ld
|
||||
/* Define output sections */
|
||||
SECTIONS
|
||||
{
|
||||
/* The startup code goes first into FLASH */
|
||||
.bootloader :
|
||||
{
|
||||
KEEP(*(.bootloader))
|
||||
. = BOOTLOADER_SIZE;
|
||||
} > REGION_BOOTLOADER
|
||||
|
||||
/* The program code and other data goes into FLASH */
|
||||
/* ISR vector to be loaded */
|
||||
.isr_vector :
|
||||
{
|
||||
_sisr_vector = .;
|
||||
KEEP(*(.isr_vector))
|
||||
|
||||
. = ALIGN(4);
|
||||
_eisr_vector = .;
|
||||
} > REGION_ISR_VECT AT> REGION_TEXT_STORAGE
|
||||
|
||||
_isr_load = LOADADDR(.isr_vector);
|
||||
|
||||
/* Main code section */
|
||||
.text :
|
||||
{
|
||||
FILL(0xFFFF)
|
||||
|
||||
CREATE_OBJECT_SYMBOLS
|
||||
|
||||
/* Bootloader code */
|
||||
KEEP(*(.bootloader))
|
||||
|
||||
. = BOOTLOADER_SIZE; /* Set the start of the main program */
|
||||
_stext = .; /* Provide the name for the start of this section */
|
||||
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.isr_vector)) /* Startup code */
|
||||
_stext = .;
|
||||
KEEP(*(.fwversiondata))
|
||||
|
||||
INCLUDE common_text.ld
|
||||
|
||||
. = ALIGN(4);
|
||||
_etext = .; /* define a global symbols at end of code */
|
||||
} > FLASH
|
||||
_etext = .;
|
||||
} > REGION_TEXT AT> REGION_TEXT_STORAGE
|
||||
|
||||
_text_load = LOADADDR(.text);
|
||||
|
||||
/* Firmware bootstrap code to load ISR vector and code sections */
|
||||
.bootstrap :
|
||||
{
|
||||
*(.bootstrap)
|
||||
} > REGION_TEXT_STORAGE
|
||||
|
||||
INCLUDE common_sections.ld
|
||||
}
|
||||
|
||||
@@ -21,6 +21,11 @@ MEMORY
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
|
||||
}
|
||||
|
||||
REGION_ALIAS("REGION_BOOTLOADER", FLASH);
|
||||
REGION_ALIAS("REGION_ISR_VECT", FLASH);
|
||||
REGION_ALIAS("REGION_TEXT", FLASH);
|
||||
REGION_ALIAS("REGION_TEXT_STORAGE", FLASH);
|
||||
|
||||
REGION_ALIAS("REGION_DATA", RAM);
|
||||
REGION_ALIAS("REGION_BSS", RAM);
|
||||
REGION_ALIAS("REGION_RAM", RAM);
|
||||
|
||||
@@ -25,6 +25,11 @@ MEMORY
|
||||
CCM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
|
||||
}
|
||||
|
||||
REGION_ALIAS("REGION_BOOTLOADER", FLASH);
|
||||
REGION_ALIAS("REGION_ISR_VECT", FLASH);
|
||||
REGION_ALIAS("REGION_TEXT", FLASH);
|
||||
REGION_ALIAS("REGION_TEXT_STORAGE", FLASH);
|
||||
|
||||
REGION_ALIAS("REGION_DATA", CCM);
|
||||
REGION_ALIAS("REGION_BSS", CCM);
|
||||
REGION_ALIAS("REGION_RAM", RAM);
|
||||
|
||||
@@ -21,6 +21,11 @@ MEMORY
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K
|
||||
}
|
||||
|
||||
REGION_ALIAS("REGION_BOOTLOADER", FLASH);
|
||||
REGION_ALIAS("REGION_ISR_VECT", FLASH);
|
||||
REGION_ALIAS("REGION_TEXT", FLASH);
|
||||
REGION_ALIAS("REGION_TEXT_STORAGE", FLASH);
|
||||
|
||||
REGION_ALIAS("REGION_DATA", RAM);
|
||||
REGION_ALIAS("REGION_BSS", RAM);
|
||||
REGION_ALIAS("REGION_RAM", RAM);
|
||||
|
||||
@@ -27,6 +27,11 @@ MEMORY
|
||||
SDRAM(xrw) : ORIGIN = SDRAM_START, LENGTH = SDRAM_SIZE
|
||||
}
|
||||
|
||||
REGION_ALIAS("REGION_BOOTLOADER", FLASH);
|
||||
REGION_ALIAS("REGION_ISR_VECT", FLASH);
|
||||
REGION_ALIAS("REGION_TEXT", FLASH);
|
||||
REGION_ALIAS("REGION_TEXT_STORAGE", FLASH);
|
||||
|
||||
REGION_ALIAS("REGION_DATA", CCM);
|
||||
REGION_ALIAS("REGION_BSS", RAM);
|
||||
REGION_ALIAS("REGION_RAM", RAM);
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "timers_driver.h"
|
||||
#include "flash_driver.h"
|
||||
|
||||
#include "hal/watchdog_driver.h"
|
||||
|
||||
#if defined(LIBOPENUI)
|
||||
|
||||
@@ -45,6 +45,7 @@ target_compile_definitions(bootloader PRIVATE BOOT)
|
||||
target_compile_definitions(board_bl PRIVATE BOOT)
|
||||
|
||||
target_link_options(bootloader BEFORE PRIVATE
|
||||
-L${LINKER_DIR}/${TARGET_LINKER_DIR}/bootloader
|
||||
-T${LINKER_DIR}/bootloader.ld
|
||||
-Wl,-Map=bootloader.map,--cref,--no-warn-mismatch,--gc-sections
|
||||
-lm --specs=nano.specs
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#if !defined(SIMU)
|
||||
#include "stm32_hal_ll.h"
|
||||
#include "stm32_hal.h"
|
||||
#include "stm32_timer.h"
|
||||
#endif
|
||||
// #if !defined(SIMU)
|
||||
// #include "stm32_hal_ll.h"
|
||||
// #include "stm32_hal.h"
|
||||
// #include "stm32_timer.h"
|
||||
// #endif
|
||||
|
||||
#include "hal/usb_driver.h"
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
#include "debug.h"
|
||||
|
||||
#include "timers_driver.h"
|
||||
#include "flash_driver.h"
|
||||
|
||||
#include "hal/abnormal_reboot.h"
|
||||
#include "hal/rotary_encoder.h"
|
||||
|
||||
@@ -46,8 +48,6 @@
|
||||
#include "thirdparty/Segger_RTT/RTT/SEGGER_RTT.h"
|
||||
#endif
|
||||
|
||||
#define APP_START_ADDRESS (uint32_t)(FIRMWARE_ADDRESS + BOOTLOADER_SIZE)
|
||||
|
||||
#if defined(EEPROM) || defined(SPI_FLASH)
|
||||
#define MAIN_MENU_LEN 3
|
||||
#else
|
||||
@@ -66,6 +66,12 @@ const uint8_t bootloaderVersion[] __attribute__ ((section(".version"), used)) =
|
||||
{'B', 'O', 'O', 'T', '1', '0'};
|
||||
#endif
|
||||
|
||||
#if defined(SIMU)
|
||||
#define __weak
|
||||
#elif !defined(__weak)
|
||||
#define __weak __attribute__((weak))
|
||||
#endif
|
||||
|
||||
volatile tmr10ms_t g_tmr10ms;
|
||||
volatile uint8_t tenms = 1;
|
||||
|
||||
@@ -444,8 +450,8 @@ int bootloaderMain()
|
||||
// confirmed
|
||||
|
||||
if (memoryType == MEM_FLASH) {
|
||||
firmwareSize = binFiles[vpos].size - BOOTLOADER_SIZE;
|
||||
firmwareAddress = FIRMWARE_ADDRESS + BOOTLOADER_SIZE;
|
||||
firmwareSize = FIRMWARE_LEN(binFiles[vpos].size);
|
||||
firmwareAddress = APP_START_ADDRESS;
|
||||
firmwareWritten = 0;
|
||||
}
|
||||
#if defined(EEPROM)
|
||||
@@ -484,7 +490,7 @@ int bootloaderMain()
|
||||
if (BlockCount == 0) {
|
||||
state = ST_FLASH_DONE; // EOF
|
||||
}
|
||||
else if (memoryType == MEM_FLASH && firmwareWritten >= FLASHSIZE - BOOTLOADER_SIZE) {
|
||||
else if (memoryType == MEM_FLASH && firmwareWritten >= FIRMWARE_MAX_LEN) {
|
||||
state = ST_FLASH_DONE; // Backstop
|
||||
}
|
||||
#if defined(EEPROM)
|
||||
|
||||
@@ -33,6 +33,8 @@ if(NOT NATIVE_BUILD)
|
||||
${STM32CUBE_DIR}/Src/stm32f2xx_hal_i2c.c
|
||||
${STM32CUBE_DIR}/Src/stm32f2xx_hal_pcd.c
|
||||
${STM32CUBE_DIR}/Src/stm32f2xx_hal_pcd_ex.c
|
||||
${STM32CUBE_DIR}/Src/stm32f2xx_hal_flash.c
|
||||
${STM32CUBE_DIR}/Src/stm32f2xx_hal_flash_ex.c
|
||||
)
|
||||
|
||||
target_compile_options(stm32cube_ll PRIVATE -DUSE_FULL_LL_DRIVER)
|
||||
|
||||
@@ -22,168 +22,182 @@
|
||||
#include "stm32_cmsis.h"
|
||||
#include "stm32_hal.h"
|
||||
|
||||
#include "board.h"
|
||||
#include "hal/watchdog_driver.h"
|
||||
|
||||
|
||||
#if defined(STM32H7)
|
||||
#define FLASH_CR FLASH->CR1
|
||||
#define FLASH_SR FLASH->SR1
|
||||
#else
|
||||
#define FLASH_CR FLASH->CR
|
||||
#define FLASH_SR FLASH->SR
|
||||
#endif
|
||||
|
||||
#if !defined(FLASH_CR_START)
|
||||
# define FLASH_CR_START FLASH_CR_STRT
|
||||
#endif
|
||||
|
||||
#if !defined(FLASH_SR_BUSY)
|
||||
# define FLASH_SR_BUSY FLASH_SR_BSY
|
||||
#endif
|
||||
|
||||
void waitFlashIdle()
|
||||
uint32_t stm32_flash_get_size_kb()
|
||||
{
|
||||
do {
|
||||
WDG_RESET();
|
||||
} while (FLASH_SR & FLASH_SR_BUSY);
|
||||
uint32_t flash_size_kb = *(const uint32_t*)FLASHSIZE_BASE;
|
||||
return flash_size_kb;
|
||||
}
|
||||
|
||||
//After reset, write is not allowed in the Flash control register (FLASH_CR) to protect the
|
||||
//Flash memory against possible unwanted operations due, for example, to electric
|
||||
//disturbances. The following sequence is used to unlock this register:
|
||||
//1. Write KEY1 = 0x45670123 in the Flash key register (FLASH_KEYR)
|
||||
//2. Write KEY2 = 0xCDEF89AB in the Flash key register (FLASH_KEYR)
|
||||
//Any wrong sequence will return a bus error and lock up the FLASH_CR register until the
|
||||
//next reset.
|
||||
//The FLASH_CR register can be locked again by software by setting the LOCK bit in the
|
||||
//FLASH_CR register.
|
||||
void unlockFlash()
|
||||
#if defined(STM32F2) || defined(STM32F4)
|
||||
|
||||
uint32_t stm32_flash_get_sector(uint32_t address)
|
||||
{
|
||||
#if defined(STM32H7)
|
||||
FLASH->KEYR1 = FLASH_KEY1;
|
||||
FLASH->KEYR1 = FLASH_KEY2;
|
||||
#else
|
||||
FLASH->KEYR = FLASH_KEY1;
|
||||
FLASH->KEYR = FLASH_KEY2;
|
||||
#endif
|
||||
}
|
||||
uint32_t sector;
|
||||
uint32_t sector_addr = address & 0xFFFFF;
|
||||
|
||||
void lockFlash()
|
||||
{
|
||||
waitFlashIdle();
|
||||
FLASH_CR |= FLASH_CR_LOCK;
|
||||
}
|
||||
|
||||
#define SECTOR_MASK ((uint32_t)0xFFFFFF07)
|
||||
|
||||
void eraseSector(uint32_t sector)
|
||||
{
|
||||
waitFlashIdle();
|
||||
|
||||
#if defined(FLASH_CR_PSIZE)
|
||||
FLASH_CR &= ~FLASH_CR_PSIZE;
|
||||
FLASH_CR |= FLASH_CR_PSIZE_1;
|
||||
#endif
|
||||
FLASH_CR &= SECTOR_MASK;
|
||||
FLASH_CR |= FLASH_CR_SER | (sector << 3);
|
||||
FLASH_CR |= FLASH_CR_START;
|
||||
|
||||
/* Wait for operation to be completed */
|
||||
waitFlashIdle();
|
||||
|
||||
/* if the erase operation is completed, disable the SER Bit */
|
||||
FLASH_CR &= (~FLASH_CR_SER);
|
||||
FLASH_CR &= SECTOR_MASK;
|
||||
}
|
||||
|
||||
void flashWrite(uint32_t * address, const uint32_t * buffer) // page size is 256 bytes
|
||||
{
|
||||
#define SECTOR_ADDRESS (((uint32_t)address) & 0xFFFFF)
|
||||
|
||||
// Please note that there is an offset of 4 between
|
||||
// sector 11 and 12
|
||||
#define FLASH_BANK ((((uint32_t)address) & 0x100000) ? 16 : 0)
|
||||
|
||||
// test for possible flash sector boundary
|
||||
if ((((uint32_t)address) & 0x1FFFF) == 0) {
|
||||
// test first 16KB sectors
|
||||
if (SECTOR_ADDRESS == 0x00000) {
|
||||
eraseSector(0 + FLASH_BANK);
|
||||
}
|
||||
// test 128KB sectors
|
||||
else if (SECTOR_ADDRESS == 0x20000) {
|
||||
eraseSector(5 + FLASH_BANK);
|
||||
}
|
||||
else if (SECTOR_ADDRESS == 0x40000) {
|
||||
eraseSector(6 + FLASH_BANK);
|
||||
}
|
||||
else if (SECTOR_ADDRESS == 0x60000) {
|
||||
eraseSector(7 + FLASH_BANK);
|
||||
}
|
||||
else if (SECTOR_ADDRESS == 0x80000) {
|
||||
eraseSector(8 + FLASH_BANK);
|
||||
}
|
||||
else if (SECTOR_ADDRESS == 0xA0000) {
|
||||
eraseSector(9 + FLASH_BANK);
|
||||
}
|
||||
else if (SECTOR_ADDRESS == 0xC0000) {
|
||||
eraseSector(10 + FLASH_BANK);
|
||||
}
|
||||
else if (SECTOR_ADDRESS == 0xE0000) {
|
||||
eraseSector(11 + FLASH_BANK);
|
||||
}
|
||||
}
|
||||
// test 64KB sector
|
||||
else if (SECTOR_ADDRESS == 0x10000) {
|
||||
eraseSector(4 + FLASH_BANK);
|
||||
}
|
||||
else if ((((uint32_t)address) & 0x3FFF) == 0) {
|
||||
// test other 16KB sectors
|
||||
if (SECTOR_ADDRESS == 0x04000) {
|
||||
eraseSector(1 + FLASH_BANK);
|
||||
}
|
||||
else if (SECTOR_ADDRESS == 0x08000) {
|
||||
eraseSector(2 + FLASH_BANK);
|
||||
}
|
||||
else if (SECTOR_ADDRESS == 0x0C000) {
|
||||
eraseSector(3 + FLASH_BANK);
|
||||
}
|
||||
}
|
||||
|
||||
#undef SECTOR_ADDRESS
|
||||
#undef FLASH_BANK
|
||||
|
||||
for (uint32_t i=0; i<FLASH_PAGESIZE/4; i++) {
|
||||
/* Device voltage range supposed to be [2.7V to 3.6V], the operation will
|
||||
be done by word */
|
||||
|
||||
// Wait for last operation to be completed
|
||||
waitFlashIdle();
|
||||
|
||||
#if defined(FLASH_CR_PSIZE)
|
||||
FLASH_CR &= ~FLASH_CR_PSIZE;
|
||||
FLASH_CR |= FLASH_CR_PSIZE_1;
|
||||
#endif
|
||||
FLASH_CR |= FLASH_CR_PG;
|
||||
|
||||
*address = *buffer;
|
||||
|
||||
/* Wait for operation to be completed */
|
||||
waitFlashIdle();
|
||||
FLASH_CR &= ~FLASH_CR_PG;
|
||||
|
||||
/* Check the written value */
|
||||
if (*address != *buffer) {
|
||||
/* Flash content doesn't match SRAM content */
|
||||
return;
|
||||
}
|
||||
/* Increment FLASH destination address */
|
||||
address += 1;
|
||||
buffer += 1;
|
||||
if (sector_addr < 0x10000) {
|
||||
sector = sector_addr / 0x4000;
|
||||
} else {
|
||||
sector = (sector_addr / 0x20000) + 4;
|
||||
}
|
||||
|
||||
// bank 2
|
||||
if (address & 0x100000) {
|
||||
sector += 12;
|
||||
}
|
||||
|
||||
return sector;
|
||||
}
|
||||
|
||||
static uint32_t _flash_sector_address(uint32_t sector, uint32_t bank)
|
||||
{
|
||||
(void)bank;
|
||||
|
||||
uint32_t addr = FLASH_BASE;
|
||||
if (sector >= 12) {
|
||||
addr += 0x100000;
|
||||
sector -= 12;
|
||||
}
|
||||
|
||||
if (sector <= 4) {
|
||||
addr += sector * 0x4000;
|
||||
} else {
|
||||
addr += (sector - 4) * 0x20000;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
uint32_t stm32_flash_get_sector_size(uint32_t sector)
|
||||
{
|
||||
// bank 2
|
||||
if (sector >= 12) sector -= 12;
|
||||
|
||||
// first 4: 16KB
|
||||
if (sector < 4) return 16 * 1024;
|
||||
// sector 4: 64KB
|
||||
if (sector == 4) return 64 * 1024;
|
||||
// others: 128KB
|
||||
return 128 * 1024;
|
||||
}
|
||||
|
||||
#elif defined(STM32H7) || defined(STM32H7RS)
|
||||
|
||||
uint32_t stm32_flash_get_sector(uint32_t address)
|
||||
{
|
||||
uint32_t sector_addr = address & 0xFFFFF;
|
||||
return sector_addr / FLASH_SECTOR_SIZE;
|
||||
}
|
||||
|
||||
static uint32_t _flash_sector_address(uint32_t sector, uint32_t bank)
|
||||
{
|
||||
uint32_t addr = FLASH_BASE;
|
||||
#if defined(DUAL_BANK)
|
||||
if (bank != FLASH_BANK_1) addr += 0x100000;
|
||||
#endif
|
||||
addr += sector * FLASH_SECTOR_SIZE;
|
||||
return addr;
|
||||
}
|
||||
|
||||
uint32_t stm32_flash_get_sector_size(uint32_t sector)
|
||||
{
|
||||
(void)sector;
|
||||
return FLASH_SECTOR_SIZE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
uint32_t stm32_flash_get_bank(uint32_t address)
|
||||
{
|
||||
#if defined(DUAL_BANK)
|
||||
return ((address & 0x100000) != 0x100000) ? FLASH_BANK_1 : FLASH_BANK_2;
|
||||
#elif defined(FLASH_BANK_1)
|
||||
(void)address;
|
||||
return FLASH_BANK_1;
|
||||
#else
|
||||
(void)address;
|
||||
return 1UL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void stm32_flash_unlock() { HAL_FLASH_Unlock(); }
|
||||
void stm32_flash_lock() { HAL_FLASH_Lock(); }
|
||||
|
||||
int stm32_flash_erase_sector(uint32_t address)
|
||||
{
|
||||
FLASH_EraseInitTypeDef eraseInit;
|
||||
eraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;
|
||||
eraseInit.Sector = stm32_flash_get_sector(address);
|
||||
eraseInit.NbSectors = 1UL;
|
||||
|
||||
#if defined(FLASH_BANK_1)
|
||||
eraseInit.Banks = stm32_flash_get_bank(address);
|
||||
#endif
|
||||
|
||||
#if defined(FLASH_VOLTAGE_RANGE_3)
|
||||
eraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_3;
|
||||
#endif
|
||||
|
||||
uint32_t sector_errors = 0;
|
||||
if (HAL_FLASHEx_Erase(&eraseInit, §or_errors) != HAL_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(STM32H7)
|
||||
#define FLASH_PROG_WORDS FLASH_NB_32BITWORD_IN_FLASHWORD
|
||||
#define _FLASH_PROGRAM(address, p_data) \
|
||||
HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, address, (uintptr_t)p_data)
|
||||
#elif defined(STM32H7RS)
|
||||
#define FLASH_PROG_WORDS 4UL
|
||||
#define _FLASH_PROGRAM(address, p_data) \
|
||||
HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, address, (uintptr_t)p_data)
|
||||
#else
|
||||
#define FLASH_PROG_WORDS 1UL
|
||||
#define _FLASH_PROGRAM(address, p_data) \
|
||||
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, *p_data)
|
||||
#endif
|
||||
|
||||
int stm32_flash_program(uint32_t address, uint8_t* data, uint32_t len)
|
||||
{
|
||||
uint32_t* p_data = (uint32_t*)data;
|
||||
uint32_t end_addr = address + len;
|
||||
|
||||
while (address < end_addr) {
|
||||
if (_FLASH_PROGRAM(address, p_data) != HAL_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
address += sizeof(uint32_t) * FLASH_PROG_WORDS;
|
||||
p_data += FLASH_PROG_WORDS;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Legacy API
|
||||
|
||||
#define FLASH_PAGESIZE 256
|
||||
|
||||
void unlockFlash() { stm32_flash_unlock(); }
|
||||
void lockFlash() { stm32_flash_lock(); }
|
||||
|
||||
void flashWrite(uint32_t* address, const uint32_t* buffer)
|
||||
{
|
||||
// check first if the address is on a sector boundary
|
||||
uint32_t sector = stm32_flash_get_sector((uintptr_t)address);
|
||||
uint32_t bank = stm32_flash_get_bank((uintptr_t)address);
|
||||
|
||||
if ((uintptr_t)address == _flash_sector_address(sector, bank)) {
|
||||
if (stm32_flash_erase_sector((uintptr_t)address) < 0) return;
|
||||
}
|
||||
|
||||
stm32_flash_program((uintptr_t)address, (uint8_t*)buffer, FLASH_PAGESIZE);
|
||||
}
|
||||
|
||||
// TODO: move this somewhere else, as it depends on firmware layout
|
||||
uint32_t isFirmwareStart(const uint8_t * buffer)
|
||||
{
|
||||
const uint32_t * block = (const uint32_t *)buffer;
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t stm32_flash_get_size_kb();
|
||||
uint32_t stm32_flash_get_sector(uint32_t address);
|
||||
uint32_t stm32_flash_get_sector_size(uint32_t sector);
|
||||
uint32_t stm32_flash_get_bank(uint32_t address);
|
||||
|
||||
void stm32_flash_unlock();
|
||||
void stm32_flash_lock();
|
||||
|
||||
int stm32_flash_erase_sector(uint32_t address);
|
||||
int stm32_flash_program(uint32_t address, uint8_t* data, uint32_t len);
|
||||
|
||||
// Legacy API
|
||||
|
||||
uint32_t isFirmwareStart(const uint8_t * buffer);
|
||||
uint32_t isBootloaderStart(const uint8_t * buffer);
|
||||
|
||||
void unlockFlash();
|
||||
void lockFlash();
|
||||
|
||||
void flashWrite(uint32_t* address, const uint32_t* buffer);
|
||||
|
||||
@@ -51,8 +51,12 @@ PACK(typedef struct {
|
||||
extern HardwareOptions hardwareOptions;
|
||||
|
||||
#define FLASHSIZE 0x200000
|
||||
#define FLASH_PAGESIZE 256
|
||||
#define BOOTLOADER_SIZE 0x20000
|
||||
#define FIRMWARE_ADDRESS 0x08000000
|
||||
#define FIRMWARE_LEN(fsize) (fsize - BOOTLOADER_SIZE)
|
||||
#define FIRMWARE_MAX_LEN (FLASHSIZE - BOOTLOADER_SIZE)
|
||||
#define APP_START_ADDRESS (uint32_t)(FIRMWARE_ADDRESS + BOOTLOADER_SIZE)
|
||||
|
||||
#define MB *1024*1024
|
||||
#define LUA_MEM_EXTRA_MAX (2 MB) // max allowed memory usage for Lua bitmaps (in bytes)
|
||||
@@ -100,14 +104,6 @@ enum {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Flash Write driver
|
||||
#define FLASH_PAGESIZE 256
|
||||
void unlockFlash();
|
||||
void lockFlash();
|
||||
void flashWrite(uint32_t * address, const uint32_t * buffer);
|
||||
uint32_t isFirmwareStart(const uint8_t * buffer);
|
||||
uint32_t isBootloaderStart(const uint8_t * buffer);
|
||||
|
||||
#if defined(INTERNAL_MODULE_PXX1) || defined(INTERNAL_MODULE_PXX2)
|
||||
#define HARDWARE_INTERNAL_RAS
|
||||
#endif
|
||||
|
||||
@@ -32,8 +32,12 @@
|
||||
#include "hal/watchdog_driver.h"
|
||||
|
||||
#define FLASHSIZE 0x200000
|
||||
#define FLASH_PAGESIZE 256
|
||||
#define BOOTLOADER_SIZE 0x20000
|
||||
#define FIRMWARE_ADDRESS 0x08000000
|
||||
#define FIRMWARE_LEN(fsize) (fsize - BOOTLOADER_SIZE)
|
||||
#define FIRMWARE_MAX_LEN (FLASHSIZE - BOOTLOADER_SIZE)
|
||||
#define APP_START_ADDRESS (uint32_t)(FIRMWARE_ADDRESS + BOOTLOADER_SIZE)
|
||||
|
||||
#define MB *1024*1024
|
||||
#define LUA_MEM_EXTRA_MAX (2 MB) // max allowed memory usage for Lua bitmaps (in bytes)
|
||||
@@ -53,14 +57,6 @@ void boardOff();
|
||||
#define LEN_CPU_UID (3*8+2)
|
||||
void getCPUUniqueID(char * s);
|
||||
|
||||
// Flash Write driver
|
||||
#define FLASH_PAGESIZE 256
|
||||
void unlockFlash();
|
||||
void lockFlash();
|
||||
void flashWrite(uint32_t * address, const uint32_t * buffer);
|
||||
uint32_t isFirmwareStart(const uint8_t * buffer);
|
||||
uint32_t isBootloaderStart(const uint8_t * buffer);
|
||||
|
||||
enum {
|
||||
PCBREV_NV14 = 0,
|
||||
PCBREV_EL18 = 1,
|
||||
|
||||
@@ -31,8 +31,12 @@
|
||||
#include "hal/watchdog_driver.h"
|
||||
|
||||
#define FLASHSIZE 0x200000
|
||||
#define FLASH_PAGESIZE 256
|
||||
#define BOOTLOADER_SIZE 0x20000
|
||||
#define FIRMWARE_ADDRESS 0x08000000
|
||||
#define FIRMWARE_LEN(fsize) (fsize - BOOTLOADER_SIZE)
|
||||
#define FIRMWARE_MAX_LEN (FLASHSIZE - BOOTLOADER_SIZE)
|
||||
#define APP_START_ADDRESS (uint32_t)(FIRMWARE_ADDRESS + BOOTLOADER_SIZE)
|
||||
|
||||
#define MB *1024*1024
|
||||
#define LUA_MEM_EXTRA_MAX (2 MB) // max allowed memory usage for Lua bitmaps (in bytes)
|
||||
@@ -52,14 +56,6 @@ void boardOff();
|
||||
#define LEN_CPU_UID (3*8+2)
|
||||
void getCPUUniqueID(char * s);
|
||||
|
||||
// Flash Write driver
|
||||
#define FLASH_PAGESIZE 256
|
||||
void unlockFlash();
|
||||
void lockFlash();
|
||||
void flashWrite(uint32_t * address, const uint32_t * buffer);
|
||||
uint32_t isFirmwareStart(const uint8_t * buffer);
|
||||
uint32_t isBootloaderStart(const uint8_t * buffer);
|
||||
|
||||
// SDRAM driver
|
||||
extern "C" void SDRAM_Init();
|
||||
|
||||
|
||||
@@ -41,8 +41,12 @@ void rotaryEncoderCheck();
|
||||
#else
|
||||
#define FLASHSIZE 0x80000 // 512k
|
||||
#endif
|
||||
#define FLASH_PAGESIZE 256
|
||||
#define BOOTLOADER_SIZE 0x8000
|
||||
#define FIRMWARE_ADDRESS 0x08000000
|
||||
#define FIRMWARE_LEN(fsize) (fsize - BOOTLOADER_SIZE)
|
||||
#define FIRMWARE_MAX_LEN (FLASHSIZE - BOOTLOADER_SIZE)
|
||||
#define APP_START_ADDRESS (uint32_t)(FIRMWARE_ADDRESS + BOOTLOADER_SIZE)
|
||||
|
||||
#define LUA_MEM_MAX (0) // max allowed memory usage for complete Lua (in bytes), 0 means unlimited
|
||||
|
||||
@@ -71,14 +75,6 @@ enum {
|
||||
PCBREV_X7_40 = 1,
|
||||
};
|
||||
|
||||
// Flash Write driver
|
||||
#define FLASH_PAGESIZE 256
|
||||
void unlockFlash();
|
||||
void lockFlash();
|
||||
void flashWrite(uint32_t * address, const uint32_t * buffer);
|
||||
uint32_t isFirmwareStart(const uint8_t * buffer);
|
||||
uint32_t isBootloaderStart(const uint8_t * buffer);
|
||||
|
||||
// Pulses driver
|
||||
#define INTERNAL_MODULE_ON() gpio_set(INTMODULE_PWR_GPIO)
|
||||
#define INTERNAL_MODULE_OFF() gpio_clear(INTMODULE_PWR_GPIO)
|
||||
|
||||
Reference in New Issue
Block a user