2018-11-16 04:40:06 -08:00
|
|
|
/**
|
|
|
|
* @file mpu_util.cpp
|
|
|
|
*
|
|
|
|
* @date Jul 27, 2014
|
2020-01-13 18:57:43 -08:00
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2020
|
2018-11-16 04:40:06 -08:00
|
|
|
*/
|
|
|
|
|
2021-05-09 06:19:20 -07:00
|
|
|
#include "hal.h"
|
2020-04-25 13:32:32 -07:00
|
|
|
#include "flash_int.h"
|
2018-11-16 04:40:06 -08:00
|
|
|
|
2021-05-09 06:19:20 -07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-05-28 22:05:29 -07:00
|
|
|
bool allowFlashWhileRunning() {
|
|
|
|
// Allow flash-while-running if dual bank mode is enabled, and we're a 2MB device (ie, no code located in second bank)
|
|
|
|
return determineDevice() == DeviceType::DualBank2MB;
|
|
|
|
}
|
|
|
|
|
2021-05-09 06:19:20 -07:00
|
|
|
// See ST AN4826
|
2019-02-06 22:06:39 -08:00
|
|
|
size_t flashSectorSize(flashsector_t sector) {
|
2021-05-09 06:19:20 -07:00
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
2021-05-18 14:40:59 -07:00
|
|
|
// On 1MB devices, sectors 8-11 don't exist, therefore have zero size.
|
|
|
|
if (flashSize() == 1024) {
|
|
|
|
if (sector > 7 && sector < 12) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-09 06:19:20 -07:00
|
|
|
// 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;
|
2019-02-06 22:06:39 -08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-02-04 18:36:38 -08:00
|
|
|
uintptr_t getFlashAddrFirstCopy() {
|
2021-05-09 06:19:20 -07:00
|
|
|
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;
|
|
|
|
}
|
2020-02-04 18:36:38 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
uintptr_t getFlashAddrSecondCopy() {
|
2021-05-09 06:19:20 -07:00
|
|
|
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;
|
|
|
|
}
|
2020-02-04 18:36:38 -08:00
|
|
|
}
|
2021-07-20 10:20:34 -07:00
|
|
|
|
|
|
|
#define FLASH_ACR (*(volatile uint32_t *)(FLASH_BASE + 0x00))
|
|
|
|
#define FLASH_KEYR (*(volatile uint32_t *)(FLASH_BASE + 0x04))
|
|
|
|
#define FLASH_OPTKEYR (*(volatile uint32_t *)(FLASH_BASE + 0x08))
|
|
|
|
#define FLASH_SR (*(volatile uint32_t *)(FLASH_BASE + 0x0C))
|
|
|
|
#define FLASH_CR (*(volatile uint32_t *)(FLASH_BASE + 0x10))
|
|
|
|
#define FLASH_OPTCR (*(volatile uint32_t *)(FLASH_BASE + 0x14))
|
|
|
|
|
|
|
|
#define FLASH_OPTCR_STRT (1 << 1)
|
|
|
|
|
|
|
|
#define FLASH_OPTKEY1 (0x08192A3B)
|
|
|
|
#define FLASH_OPTKEY2 (0x4C5D6E7F)
|
|
|
|
|
2021-07-20 11:15:58 -07:00
|
|
|
static void flash_wait_complete(void)
|
|
|
|
{
|
|
|
|
while ((FLASH_SR & FLASH_SR_BSY) == FLASH_SR_BSY)
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void stm32f7_flash_mass_erase_dual_block(void)
|
|
|
|
{
|
|
|
|
FLASH_CR |= FLASH_CR_MER1 | FLASH_CR_MER2;
|
|
|
|
FLASH_CR |= FLASH_CR_STRT;
|
|
|
|
flash_wait_complete();
|
|
|
|
FLASH_CR &= ~(FLASH_CR_MER1 | FLASH_CR_MER2);
|
|
|
|
}
|
|
|
|
|
|
|
|
// todo: at the moment this does not work :(
|
|
|
|
// https://github.com/rusefi/rusefi/issues/2996
|
2021-07-20 10:20:34 -07:00
|
|
|
void sys_dual_bank(void) {
|
|
|
|
uint32_t reg;
|
|
|
|
|
|
|
|
/* Unlock OPTCR */
|
|
|
|
FLASH_OPTKEYR = FLASH_OPTKEY1;
|
|
|
|
FLASH_OPTKEYR = FLASH_OPTKEY2;
|
|
|
|
|
|
|
|
/* Disable protection + Switch to dual bank */
|
|
|
|
reg = FLASH_OPTCR;
|
|
|
|
reg &= ~0x000FF00;
|
|
|
|
reg |= 0x0000AA00;
|
|
|
|
reg &= ~(FLASH_OPTCR_nDBANK);
|
|
|
|
FLASH_OPTCR = reg;
|
|
|
|
FLASH_OPTCR |= FLASH_OPTCR_STRT;
|
2021-07-20 11:15:58 -07:00
|
|
|
/*
|
|
|
|
* see https://github.com/danielinux/stm32f7-dualbank-tool/issues/1
|
|
|
|
stm32f7_flash_mass_erase_dual_block();
|
|
|
|
*/
|
2021-07-20 10:20:34 -07:00
|
|
|
}
|
|
|
|
|