flash/nor/kinetis: fix FCF handling

Kinetis Flash Configuration Field needs special handling to prevent unwanted
locking of the device. Warn user about any difference between generated
FCF and FCF data in the programmed file. Inform user that re-programming
of already programmed FCF may fail on devices with FTFE flash module.

While on it remove useless setting of is_erased flag after erase.

Change-Id: I3911f436674547fa12ef3886c7d5e8cd889f9e2b
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Fixes: https://sourceforge.net/p/openocd/tickets/270/
Reported-by: Noel Diviney <vk3avm@users.sourceforge.net>
Reviewed-on: http://openocd.zylin.com/5753
Tested-by: jenkins
This commit is contained in:
Tomas Vanek 2020-07-02 10:50:15 +02:00
parent 8d7ca43775
commit fd9a7a8c8a
1 changed files with 34 additions and 22 deletions

View File

@ -389,7 +389,6 @@ static const struct kinetis_type kinetis_types_old[] = {
static bool allow_fcf_writes;
static uint8_t fcf_fopt = 0xff;
static bool fcf_fopt_configured;
static bool create_banks;
@ -1650,8 +1649,6 @@ static int kinetis_erase(struct flash_bank *bank, unsigned int first,
return ERROR_FLASH_OPERATION_FAILED;
}
bank->sectors[i].is_erased = 1;
if (k_bank->prog_base == 0
&& bank->sectors[i].offset <= FCF_ADDRESS
&& bank->sectors[i].offset + bank->sectors[i].size > FCF_ADDRESS + FCF_SIZE) {
@ -1665,7 +1662,8 @@ static int kinetis_erase(struct flash_bank *bank, unsigned int first,
result = kinetis_write_inner(bank, fcf_buffer, FCF_ADDRESS, FCF_SIZE);
if (result != ERROR_OK)
LOG_WARNING("Flash Configuration Field write failed");
bank->sectors[i].is_erased = 0;
else
LOG_DEBUG("Generated FCF written");
}
}
}
@ -1909,6 +1907,7 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer,
int result;
bool set_fcf = false;
bool fcf_in_data_valid = false;
bool fcf_differs = false;
int sect = 0;
struct kinetis_flash_bank *k_bank = bank->driver_priv;
struct kinetis_chip *k_chip = k_bank->k_chip;
@ -1941,31 +1940,45 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer,
&& offset + count >= FCF_ADDRESS + FCF_SIZE;
if (fcf_in_data_valid) {
memcpy(fcf_in_data, buffer + FCF_ADDRESS - offset, FCF_SIZE);
if (memcmp(fcf_in_data + FCF_FPROT, fcf_buffer, 4)) {
fcf_in_data_valid = false;
LOG_INFO("Flash protection requested in programmed file differs from current setting.");
if (memcmp(fcf_in_data, fcf_buffer, 8)) {
fcf_differs = true;
LOG_INFO("Setting of backdoor key is not supported in mode 'kinetis fcf_source protection'.");
}
if (memcmp(fcf_in_data + FCF_FPROT, fcf_buffer + FCF_FPROT, 4)) {
fcf_differs = true;
LOG_INFO("Flash protection requested in the programmed file differs from current setting.");
}
if (fcf_in_data[FCF_FDPROT] != fcf_buffer[FCF_FDPROT]) {
fcf_in_data_valid = false;
LOG_INFO("Data flash protection requested in programmed file differs from current setting.");
fcf_differs = true;
LOG_INFO("Data flash protection requested in the programmed file differs from current setting.");
}
if ((fcf_in_data[FCF_FSEC] & 3) != 2) {
fcf_in_data_valid = false;
LOG_INFO("Device security requested in programmed file!");
} else if (k_chip->flash_support & FS_ECC
&& fcf_in_data[FCF_FSEC] != fcf_buffer[FCF_FSEC]) {
fcf_in_data_valid = false;
LOG_INFO("Device security requested in the programmed file! Write denied.");
} else if (fcf_in_data[FCF_FSEC] != fcf_buffer[FCF_FSEC]) {
fcf_differs = true;
LOG_INFO("Strange unsecure mode 0x%02" PRIx8
"requested in programmed file!",
fcf_in_data[FCF_FSEC]);
" requested in the programmed file, set FSEC = 0x%02" PRIx8
" in the startup code!",
fcf_in_data[FCF_FSEC], fcf_buffer[FCF_FSEC]);
}
if ((k_chip->flash_support & FS_ECC || fcf_fopt_configured)
&& fcf_in_data[FCF_FOPT] != fcf_fopt) {
fcf_in_data_valid = false;
LOG_INFO("FOPT requested in programmed file differs from current setting.");
if (fcf_in_data[FCF_FOPT] != fcf_buffer[FCF_FOPT]) {
fcf_differs = true;
LOG_INFO("FOPT requested in the programmed file differs from current setting, set 'kinetis fopt 0x%02"
PRIx8 "'.", fcf_in_data[FCF_FOPT]);
}
/* If the device has ECC flash, then we cannot re-program FCF */
if (fcf_differs) {
if (k_chip->flash_support & FS_ECC) {
fcf_in_data_valid = false;
LOG_INFO("Cannot re-program FCF. Expect verify errors at FCF (0x400-0x40f).");
} else {
LOG_INFO("Trying to re-program FCF.");
if (!(k_chip->flash_support & FS_PROGRAM_LONGWORD))
LOG_INFO("Flash re-programming may fail on this device!");
}
}
if (!fcf_in_data_valid)
LOG_INFO("Expect verify errors at FCF (0x408-0x40f).");
}
}
@ -3035,7 +3048,6 @@ COMMAND_HANDLER(kinetis_fopt_handler)
if (CMD_ARGC == 1) {
fcf_fopt = (uint8_t)strtoul(CMD_ARGV[0], NULL, 0);
fcf_fopt_configured = true;
} else {
command_print(CMD, "FCF_FOPT 0x%02" PRIx8, fcf_fopt);
}