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:
parent
1f0983c2ab
commit
155bfd9aeb
|
@ -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)) {
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue