Support STM32F7 1MB devices (#2659)

* modify linker script for 1MB devices

* handle null flash address

* actually support 1MB F7

* comment
This commit is contained in:
Matthew Kennedy 2021-05-09 06:19:20 -07:00 committed by GitHub
parent 1f0983c2ab
commit 155bfd9aeb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 107 additions and 14 deletions

View File

@ -86,8 +86,12 @@ void writeToFlashIfPending() {
// Erase and write a copy of the configuration at the specified address
template <typename TStorage>
int eraseAndFlashCopy(flashaddr_t storageAddress, const TStorage& data)
{
int eraseAndFlashCopy(flashaddr_t storageAddress, const TStorage& data) {
// error already reported, return
if (!storageAddress) {
return FLASH_RETURN_SUCCESS;
}
auto err = intFlashErase(storageAddress, sizeof(TStorage));
if (FLASH_RETURN_SUCCESS != err) {
firmwareError(OBD_PCM_Processor_Fault, "Failed to erase flash at %#010x", storageAddress);
@ -145,6 +149,12 @@ typedef enum {
static persisted_configuration_state_e doReadConfiguration(flashaddr_t address) {
efiPrintf("readFromFlash %x", address);
// error already reported, return
if (!address) {
return CRC_FAILED;
}
intFlashRead(address, (char *) &persistentState, sizeof(persistentState));
if (!isValidCrc(&persistentState)) {

View File

@ -15,7 +15,7 @@
*/
/*
* STM32F76xxI generic setup.
* STM32F7 memory setup.
*
* RAM0 - Data, Heap.
* RAM3 - Main Stack, Process Stack, BSS, NOCACHE, ETH.
@ -27,7 +27,7 @@
MEMORY
{
bl : org = 0x08000000, len = 16k /* bootloader section */
flash0 (rx) : org = DEFINED(BOOTLOADER) ? 0x08008000 : 0x08000000, len = DEFINED(BOOTLOADER) ? 1992k : 2048k
flash0 (rx) : org = DEFINED(BOOTLOADER) ? 0x08008000 : 0x08000000, len = DEFINED(BOOTLOADER) ? 736k : 768k /* change address & length if bootloader */
flash1 (rx) : org = 0x00200000, len = 2M /* Flash as ITCM */ /* TODO: do we need BOOTLOADER logic here? */
flash2 (rx) : org = 0x00000000, len = 0
flash3 (rx) : org = 0x00000000, len = 0

View File

@ -8,7 +8,7 @@ HW_LAYER_EMS_CPP += $(PROJECT_DIR)/hw_layer/ports/stm32/stm32f7/mpu_util.cpp \
DDEFS += -DSTM32F767xx
MCU = cortex-m7
LDSCRIPT = $(PROJECT_DIR)/hw_layer/ports/stm32/stm32f7/STM32F76xxI.ld
LDSCRIPT = $(PROJECT_DIR)/hw_layer/ports/stm32/stm32f7/STM32F7.ld
ALLCSRC += $(CHIBIOS)/os/hal/boards/ST_NUCLEO144_F767ZI/board.c
CONFDIR = $(PROJECT_DIR)/hw_layer/ports/stm32/stm32f7/cfg

View File

@ -5,23 +5,106 @@
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#include "hal.h"
#include "flash_int.h"
static bool isDualBank() {
// cleared bit indicates dual bank
return (FLASH->OPTCR & FLASH_OPTCR_nDBANK) == 0;
}
static uint16_t flashSize() {
return *reinterpret_cast<const volatile uint16_t*>(FLASHSIZE_BASE);
}
enum class DeviceType {
DualBank1MB,
DualBank2MB,
SingleBank1MB,
SingleBank2MB,
Unknown
};
static DeviceType determineDevice() {
bool db = isDualBank();
uint16_t fs = flashSize();
if (db) {
if (fs == 1024) {
return DeviceType::DualBank1MB;
} else if (fs == 2048) {
return DeviceType::DualBank2MB;
}
} else {
if (fs == 1024) {
// Unsupported scenario! Not enough space for program plus two config copies
firmwareError(OBD_PCM_Processor_Fault, "1MB single bank MCU detected: please clear nDBANK option bit and reinstall FW.");
return DeviceType::SingleBank1MB;
} else if (fs == 2048) {
return DeviceType::SingleBank2MB;
}
}
firmwareError(OBD_PCM_Processor_Fault, "Unrecognized flash memory layout db=%d, size=%d", db, fs);
return DeviceType::Unknown;
}
// See ST AN4826
size_t flashSectorSize(flashsector_t sector) {
// sectors 0..11 are the 1st memory bank (1Mb), and 12..23 are the 2nd (the same structure).
if (sector <= 3 || (sector >= 12 && sector <= 15))
return 32 * 1024;
else if (sector == 4 || sector == 16)
return 128 * 1024;
else if ((sector >= 5 && sector <= 11) || (sector >= 17 && sector <= 23))
return 256 * 1024;
// 1MB devices have 8 sectors per bank
// 2MB devices have 12 sectors per bank
// However, the second bank always starts at index 12 (1MB devices have a 4 sector discontinuity between banks)
if (sector >= 12) {
// The second bank has the same structure as the first
return flashSectorSize(sector - 12);
}
// Pages are twice the size when in single bank mode
size_t dbMul = isDualBank() ? 1 : 2;
if (sector <= 3)
return 16 * 1024 * dbMul;
else if (sector == 4)
return 64 * 1024 * dbMul;
else if (sector >= 5)
return 128 * 1024 * dbMul;
return 0;
}
uintptr_t getFlashAddrFirstCopy() {
return 0x08100000;
switch (determineDevice()) {
case DeviceType::DualBank1MB:
// Sector 18, second to last 128K sector
return 0x080C0000;
case DeviceType::SingleBank1MB:
// Sector 7, last 256K sector
return 0x080C0000;
case DeviceType::DualBank2MB: /* falls thru */
case DeviceType::SingleBank2MB:
// Start of the second megabyte
// Sector 12 for dual bank
// Sector 8 for single bank
return 0x08100000;
default:
return 0;
}
}
uintptr_t getFlashAddrSecondCopy() {
return 0x08140000;
switch (determineDevice()) {
case DeviceType::DualBank1MB:
// Sector 19, last 128K sector, 128K after the first copy
return 0x080E0000;
case DeviceType::DualBank2MB:
// Sector 14, 32K after the first copy
return 0x08108000;
case DeviceType::SingleBank2MB:
// Sector 9, 256K after the first copy
return 0x08140000;
case DeviceType::SingleBank1MB:
// We can't fit a second copy in this config, fall thru to failure case
default:
return 0;
}
}