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
|
|
|
}
|