|
From: openocd-gerrit <ope...@us...> - 2026-07-01 09:54:36
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 0b3e390506d1dd0e3d8a0db2e3163fce71f6f131 (commit)
from 4de89132f4b5e059d5421af3ec66196b6f855bd2 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 0b3e390506d1dd0e3d8a0db2e3163fce71f6f131
Author: Nishanth Menon <nm...@ti...>
Date: Thu May 28 23:38:44 2026 -0500
flash/nor/mspm0: workaround FLASH_ERR_01 in mspm0_read_part_info
MSPM0G devices have errata FLASH_ERR_01: accessing FACTORYREGION
(0x41C40000) via any AHB bus master causes a hard fault when the flash
controller is operating with 2 wait states. This occurs when MCLK is
sourced from HSCLK (SYSPLL/HFXT), i.e. MCLK > 32 MHz.
This affects OpenOCD reads (via DAP AHB-AP) in mspm0_read_part_info().
Fix this by checking SYSCTL_MCLKCFG before reading FACTORYREGION. If
USEHSCLK is set and FLASHWAIT == 2, temporarily switch MCLK to SYSOSC
(⤠32 MHz), perform the reads (DID, TRACEID, USERID, SRAMFLASH), and
then restore the original MCLK configuration. Restoration is ensured for
both success and error paths.
The workaround is effectively a no-op on MSPM0L and MSPM0C devices,
since they do not reach the required clock conditions.
Also handle cases where FACTORYREGION reads fail during probe: if the
main flash size is zero, force a re-probe by clearing did.
Link: https://www.ti.com/lit/er/slaz758d/slaz758d.pdf
Change-Id: I100b02f009b3e200cb3a4482c4a26ffbdb8f5f3e
Reported-by: Michael Rodriguez <Mic...@cr...>
Tested-by: Michael Rodriguez <Mic...@cr...>
Signed-off-by: Nishanth Menon <nm...@ti...>
Reviewed-on: https://review.openocd.org/c/openocd/+/9726
Tested-by: jenkins
Reviewed-by: Tomas Vanek <va...@fb...>
diff --git a/src/flash/nor/mspm0.c b/src/flash/nor/mspm0.c
index 5ff1d71e4..1ba35374d 100644
--- a/src/flash/nor/mspm0.c
+++ b/src/flash/nor/mspm0.c
@@ -77,6 +77,20 @@
#define SYSCTL_BASE 0x400AF000
#define SYSCTL_SECCFG_SECSTATUS (SYSCTL_BASE + 0x00003048)
+/*
+ * SYSCTL SOCLOCK MCLKCFG register (offset 0x1104 from SYSCTL_BASE).
+ * Used for the FLASH_ERR_01 workaround: accessing FACTORYREGION while MCLK
+ * is sourced from HSCLK (SYSPLL/HFXT, implying MCLK > 32 MHz) with flash
+ * wait-state 2 active causes a hard fault on MSPM0G devices. The flash
+ * controller enforces its wait-state timing for all AHB masters, including
+ * the DAP AHB-AP used by OpenOCD. Temporarily switching MCLK to SYSOSC
+ * (⤠32 MHz on all MSPM0 variants) before reading FACTORYREGION avoids this.
+ */
+#define SYSCTL_MCLKCFG (SYSCTL_BASE + 0x00001104)
+#define SYSCTL_MCLKCFG_USEHSCLK BIT(16)
+#define SYSCTL_MCLKCFG_FLASHWAIT_MASK GENMASK(11, 8)
+#define SYSCTL_MCLKCFG_FLASHWAIT_2 (2U << 8)
+
/* TI manufacturer ID */
#define TI_MANUFACTURER_ID 0x17
@@ -474,30 +488,94 @@ static int mspm0_read_part_info(struct flash_bank *bank)
struct target *target = bank->target;
const struct mspm0_family_info *minfo = NULL;
+ /*
+ * FLASH_ERR_01 workaround: on MSPM0G devices the flash controller
+ * rejects any bus-master access to FACTORYREGION when MCLK is sourced
+ * from HSCLK (SYSPLL/HFXT) and flash wait-state 2 is active
+ * (required for MCLK > 32 MHz). This applies to DAP AHB-AP reads too,
+ * not just CPU accesses. If both conditions are true, temporarily
+ * switch MCLK back to SYSOSC (⤠32 MHz on every MSPM0 variant) for the
+ * FACTORYREGION reads and restore afterwards. The SYSCTL_MCLKCFG write
+ * does not take place on L/C parts: USEHSCLK is never set there because
+ * those cores do not exceed 32 MHz.
+ */
+ uint32_t saved_mclkcfg = 0;
+ bool mclk_switched = false;
+ uint32_t mclkcfg;
+ int retval = target_read_u32(target, SYSCTL_MCLKCFG, &mclkcfg);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to read SYSCTL_MCLKCFG to check FLASH_ERR_01");
+ return retval;
+ }
+
+ if ((mclkcfg & SYSCTL_MCLKCFG_USEHSCLK) &&
+ ((mclkcfg & SYSCTL_MCLKCFG_FLASHWAIT_MASK) == SYSCTL_MCLKCFG_FLASHWAIT_2)) {
+ saved_mclkcfg = mclkcfg;
+ retval = target_write_u32(target, SYSCTL_MCLKCFG,
+ mclkcfg & ~SYSCTL_MCLKCFG_USEHSCLK);
+ if (retval == ERROR_OK) {
+ mclk_switched = true;
+ /*
+ * Read back MCLKCFG to flush the write, then add an
+ * explicit delay to allow the MCLK source mux to fully
+ * settle on SYSOSC before the flash controller timing is
+ * used for FACTORYREGION accesses.
+ */
+ uint32_t dummy;
+ retval = target_read_u32(target, SYSCTL_MCLKCFG, &dummy);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("MSPM0: FLASH_ERR_01 workaround: "
+ "readback flush failed");
+ goto restore_mclk;
+ }
+ alive_sleep(1);
+ LOG_DEBUG("MSPM0: FLASH_ERR_01 workaround ACTIVE: "
+ "Lowering MCLK before FACTORYREGION read");
+ } else {
+ LOG_ERROR("MSPM0: FLASH_ERR_01 workaround: "
+ "could not lower MCLK before FACTORYREGION read");
+ }
+ }
+
/* Read and parse chip identification and flash version register */
uint32_t did;
- int retval = target_read_u32(target, MSPM0_DID, &did);
+ retval = target_read_u32(target, MSPM0_DID, &did);
if (retval != ERROR_OK) {
LOG_ERROR("Failed to read device ID");
- return retval;
+ goto restore_mclk;
}
retval = target_read_u32(target, MSPM0_TRACEID, &mspm0_info->traceid);
if (retval != ERROR_OK) {
LOG_ERROR("Failed to read trace ID");
- return retval;
+ goto restore_mclk;
}
uint32_t userid;
retval = target_read_u32(target, MSPM0_USERID, &userid);
if (retval != ERROR_OK) {
LOG_ERROR("Failed to read user ID");
- return retval;
+ goto restore_mclk;
}
uint32_t flashram;
retval = target_read_u32(target, MSPM0_SRAMFLASH, &flashram);
if (retval != ERROR_OK) {
LOG_ERROR("Failed to read sramflash register");
- return retval;
+ goto restore_mclk;
+ }
+
+restore_mclk:
+ if (mclk_switched) {
+ int retval2 = target_write_u32(target, SYSCTL_MCLKCFG, saved_mclkcfg);
+ if (retval2 != ERROR_OK) {
+ LOG_ERROR("MSPM0: FLASH_ERR_01 workaround: "
+ "could not restore MCLK after FACTORYREGION read");
+ return retval2;
+ }
+ LOG_DEBUG("MSPM0: FLASH_ERR_01 workaround: "
+ "restored MCLK after FACTORYREGION read");
}
+ if (retval != ERROR_OK)
+ return retval;
+
uint32_t flashdesc;
retval = target_read_u32(target, FCTL_REG_DESC, &flashdesc);
if (retval != ERROR_OK) {
@@ -1157,6 +1235,19 @@ static int mspm0_probe(struct flash_bank *bank)
mspm0_info->protect_reg_count = 1;
break;
case MSPM0_FLASH_BASE_MAIN:
+ if (!mspm0_info->main_flash_size_kb) {
+ /*
+ * FACTORYREGION was unreadable when this bank was probed
+ * (e.g. device not yet halted, MCLK still at HSCLK on
+ * first examine). Clear did so the next auto_probe call
+ * re-runs mspm0_read_part_info with the target in a known
+ * state.
+ */
+ LOG_WARNING("MSPM0: main flash size is 0 â "
+ "FACTORYREGION data incomplete, scheduling re-probe");
+ mspm0_info->did = 0;
+ return ERROR_FLASH_BANK_NOT_PROBED;
+ }
bank->size = (mspm0_info->main_flash_size_kb * 1024);
bank->num_sectors = bank->size / mspm0_info->sector_size;
/*
-----------------------------------------------------------------------
Summary of changes:
src/flash/nor/mspm0.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 96 insertions(+), 5 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|