aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTomas Vanek <vanekt@fbl.cz>2016-07-17 16:22:47 +0200
committerAndreas Fritiofson <andreas.fritiofson@gmail.com>2016-08-14 09:10:06 +0100
commit6d5b4d709cb05e8daf0350ac507b928da95d0abb (patch)
treec4cb5f4b88d3ca9be5d458a9d8533fb6aeec3dad /src
parent8285ec4cb06b8809761717a6ac420112ea7b2908 (diff)
flash Kinetis: Detect RESET/WDOG loop, fix detection of secured MCU
Kinetis driver checks MDM STAT register to detect secured state of MCU. Original version often reported a blank device as secured one. Change #3010 has not fixed all false reports. After changes in arm_adi_v5 infrastructure secured devices was not detected at all. New algorithm uses multiple MDM STAT reads and counts MDM_STAT_SYSSEC and MDM_STAT_FREADY bits. Both secured MCU and MCU locked-up in RESET/WDOG loop are detected reliably. Detection is run in both kx.cfg and klx.cfg from examine-start event, not examine-end as before. Event is configured only for non hla adapter. Minor fix in klx.cfg: commented out adapter_khz 24000 in reset-init. Such frequency is not supported in VLPR CPU mode and with JTAG. Change-Id: I2ec2b68c45bde9898159cd15fbdcbcfa538c41d9 Signed-off-by: Tomas Vanek <vanekt@fbl.cz> Reviewed-on: http://openocd.zylin.com/3547 Tested-by: jenkins Reviewed-by: Steven Stallion <stallion@squareup.com> Reviewed-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/flash/nor/kinetis.c80
1 files changed, 43 insertions, 37 deletions
diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c
index 0f639758..5c3ff0d6 100644
--- a/src/flash/nor/kinetis.c
+++ b/src/flash/nor/kinetis.c
@@ -227,6 +227,8 @@ struct kinetis_flash_bank {
} flash_support;
};
+#define MDM_AP 1
+
#define MDM_REG_STAT 0x00
#define MDM_REG_CTRL 0x04
#define MDM_REG_ID 0xfc
@@ -261,7 +263,7 @@ static int kinetis_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint3
int retval;
LOG_DEBUG("MDM_REG[0x%02x] <- %08" PRIX32, reg, value);
- retval = dap_queue_ap_write(dap_ap(dap, 1), reg, value);
+ retval = dap_queue_ap_write(dap_ap(dap, MDM_AP), reg, value);
if (retval != ERROR_OK) {
LOG_DEBUG("MDM: failed to queue a write request");
return retval;
@@ -281,7 +283,7 @@ static int kinetis_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32
{
int retval;
- retval = dap_queue_ap_read(dap_ap(dap, 1), reg, result);
+ retval = dap_queue_ap_read(dap_ap(dap, MDM_AP), reg, result);
if (retval != ERROR_OK) {
LOG_DEBUG("MDM: failed to queue a read request");
return retval;
@@ -575,9 +577,12 @@ COMMAND_HANDLER(kinetis_check_flash_security_status)
retval = kinetis_mdm_read_register(dap, MDM_REG_ID, &val);
if (retval != ERROR_OK) {
LOG_ERROR("MDM: failed to read ID register");
- goto fail;
+ return ERROR_OK;
}
+ if (val == 0)
+ return ERROR_OK;
+
bool found = false;
for (size_t i = 0; i < ARRAY_SIZE(kinetis_known_mdm_ids); i++) {
if (val == kinetis_known_mdm_ids[i]) {
@@ -590,17 +595,6 @@ COMMAND_HANDLER(kinetis_check_flash_security_status)
LOG_WARNING("MDM: unknown ID %08" PRIX32, val);
/*
- * ... Read the MDM-AP status register until the Flash Ready bit sets...
- */
- retval = kinetis_mdm_poll_register(dap, MDM_REG_STAT,
- MDM_STAT_FREADY,
- MDM_STAT_FREADY);
- if (retval != ERROR_OK) {
- LOG_ERROR("MDM: flash ready timeout");
- goto fail;
- }
-
- /*
* ... Read the System Security bit to determine if security is enabled.
* If System Security = 0, then proceed. If System Security = 1, then
* communication with the internals of the processor, including the
@@ -610,33 +604,40 @@ COMMAND_HANDLER(kinetis_check_flash_security_status)
retval = kinetis_mdm_read_register(dap, MDM_REG_STAT, &val);
if (retval != ERROR_OK) {
LOG_ERROR("MDM: failed to read MDM_REG_STAT");
- goto fail;
+ return ERROR_OK;
}
- if ((val & (MDM_STAT_SYSSEC | MDM_STAT_CORE_HALTED)) == MDM_STAT_SYSSEC) {
- LOG_WARNING("MDM: Secured MCU state detected however it may be a false alarm");
- LOG_WARNING("MDM: Halting target to detect secured state reliably");
+ /*
+ * System Security bit is also active for short time during reset.
+ * If a MCU has blank flash and runs in RESET/WDOG loop,
+ * System Security bit is active most of time!
+ * We should observe Flash Ready bit and read status several times
+ * to avoid false detection of secured MCU
+ */
+ int secured_score = 0, flash_not_ready_score = 0;
- retval = target_halt(target);
- if (retval == ERROR_OK)
- retval = target_wait_state(target, TARGET_HALTED, 100);
+ if ((val & (MDM_STAT_SYSSEC | MDM_STAT_FREADY)) != MDM_STAT_FREADY) {
+ uint32_t stats[32];
+ int i;
- if (retval != ERROR_OK) {
- LOG_WARNING("MDM: Target not halted, trying reset halt");
- target->reset_halt = true;
- target->type->assert_reset(target);
- target->type->deassert_reset(target);
+ for (i = 0; i < 32; i++) {
+ stats[i] = MDM_STAT_FREADY;
+ dap_queue_ap_read(dap_ap(dap, MDM_AP), MDM_REG_STAT, &stats[i]);
}
-
- /* re-read status */
- retval = kinetis_mdm_read_register(dap, MDM_REG_STAT, &val);
+ retval = dap_run(dap);
if (retval != ERROR_OK) {
- LOG_ERROR("MDM: failed to read MDM_REG_STAT");
- goto fail;
+ LOG_DEBUG("MDM: dap_run failed when validating secured state");
+ return ERROR_OK;
+ }
+ for (i = 0; i < 32; i++) {
+ if (stats[i] & MDM_STAT_SYSSEC)
+ secured_score++;
+ if (!(stats[i] & MDM_STAT_FREADY))
+ flash_not_ready_score++;
}
}
- if (val & MDM_STAT_SYSSEC) {
+ if (flash_not_ready_score <= 8 && secured_score > 24) {
jtag_poll_set_enabled(false);
LOG_WARNING("*********** ATTENTION! ATTENTION! ATTENTION! ATTENTION! **********");
@@ -648,17 +649,22 @@ COMMAND_HANDLER(kinetis_check_flash_security_status)
LOG_WARNING("**** command, power cycle the MCU and restart OpenOCD. ****");
LOG_WARNING("**** ****");
LOG_WARNING("*********** ATTENTION! ATTENTION! ATTENTION! ATTENTION! **********");
+
+ } else if (flash_not_ready_score > 24) {
+ jtag_poll_set_enabled(false);
+ LOG_WARNING("**** Your Kinetis MCU is probably locked-up in RESET/WDOG loop. ****");
+ LOG_WARNING("**** Common reason is a blank flash (at least a reset vector). ****");
+ LOG_WARNING("**** Issue 'kinetis mdm halt' command or if SRST is connected ****");
+ LOG_WARNING("**** and configured, use 'reset halt' ****");
+ LOG_WARNING("**** If MCU cannot be halted, it is likely secured and running ****");
+ LOG_WARNING("**** in RESET/WDOG loop. Issue 'kinetis mdm mass_erase' ****");
+
} else {
LOG_INFO("MDM: Chip is unsecured. Continuing.");
jtag_poll_set_enabled(true);
}
return ERROR_OK;
-
-fail:
- LOG_ERROR("MDM: Failed to check security status of the MCU. Cannot proceed further");
- jtag_poll_set_enabled(false);
- return retval;
}
FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command)