Tool/software:
Hi TI Experts!
I'm seeing weird issues when running images built with the GNU ARM toolchain on the MSPM0G3507. I've determined 2 spots where "hard faults" occur until now but they occur only when:
1. Running "release builds", i.e. compiled with -Os
.
2. No debugger is connected.
These conditions make it a little difficult to pinpoint what exactly triggers such a hard fault, but I think I was able to do that for one such occurrence:
In a release build with GNU ARM toolchain arm-gnu-toolchain-14.2.rel1-mingw-w64-i686-arm-none-eabi, the hard fault seems to occur when the routine DL_SYSCTL_configSYSPLL()
of TI SDK version 2_03_00_07 writes to SYSCTL->SOCLOCK.
SYSPLLPARAM0
:
void DL_SYSCTL_configSYSPLL(DL_SYSCTL_SYSPLLConfig *config)
{
/* PLL configurations are retained in lower reset levels. Set default
* behavior of disabling the PLL to keep a consistent behavior regardless
* of reset level. */
DL_SYSCTL_disableSYSPLL();
/* Check that SYSPLL is disabled before configuration */
while ((DL_SYSCTL_getClockStatus() & (DL_SYSCTL_CLK_STATUS_SYSPLL_OFF)) !=
(DL_SYSCTL_CLK_STATUS_SYSPLL_OFF)) {
;
}
// set SYSPLL reference clock
DL_Common_updateReg(&SYSCTL->SOCLOCK.SYSPLLCFG0,
((uint32_t) config->sysPLLRef), SYSCTL_SYSPLLCFG0_SYSPLLREF_MASK);
// set predivider PDIV (divides reference clock)
DL_Common_updateReg(&SYSCTL->SOCLOCK.SYSPLLCFG1, ((uint32_t) config->pDiv),
SYSCTL_SYSPLLCFG1_PDIV_MASK);
// save CPUSS CTL state and disable the cache
uint32_t ctlTemp = DL_CORE_getInstructionConfig();
DL_CORE_configInstruction(DL_CORE_PREFETCH_ENABLED, DL_CORE_CACHE_DISABLED,
DL_CORE_LITERAL_CACHE_ENABLED);
// populate SYSPLLPARAM0/1 tuning registers from flash, based on input freq
SYSCTL->SOCLOCK.SYSPLLPARAM0 =
*(volatile uint32_t *) ((uint32_t) config->inputFreq); <-- Hard Fault occurs here
SYSCTL->SOCLOCK.SYSPLLPARAM1 =
*(volatile uint32_t *) ((uint32_t) config->inputFreq + (uint32_t) 0x4);
// restore CPUSS CTL state
CPUSS->CTL = ctlTemp;
// set feedback divider QDIV (multiplies to give output frequency)
DL_Common_updateReg(&SYSCTL->SOCLOCK.SYSPLLCFG1,
((config->qDiv << SYSCTL_SYSPLLCFG1_QDIV_OFS) &
SYSCTL_SYSPLLCFG1_QDIV_MASK),
SYSCTL_SYSPLLCFG1_QDIV_MASK);
// write clock output dividers, enable outputs, and MCLK source to SYSPLLCFG0
DL_Common_updateReg(&SYSCTL->SOCLOCK.SYSPLLCFG0,
(((config->rDivClk2x << SYSCTL_SYSPLLCFG0_RDIVCLK2X_OFS) &
SYSCTL_SYSPLLCFG0_RDIVCLK2X_MASK) |
((config->rDivClk1 << SYSCTL_SYSPLLCFG0_RDIVCLK1_OFS) &
SYSCTL_SYSPLLCFG0_RDIVCLK1_MASK) |
((config->rDivClk0 << SYSCTL_SYSPLLCFG0_RDIVCLK0_OFS) &
SYSCTL_SYSPLLCFG0_RDIVCLK0_MASK) |
config->enableCLK2x | config->enableCLK1 | config->enableCLK0 |
(uint32_t) config->sysPLLMCLK),
(SYSCTL_SYSPLLCFG0_RDIVCLK2X_MASK | SYSCTL_SYSPLLCFG0_RDIVCLK1_MASK |
SYSCTL_SYSPLLCFG0_RDIVCLK0_MASK |
SYSCTL_SYSPLLCFG0_ENABLECLK2X_MASK |
SYSCTL_SYSPLLCFG0_ENABLECLK1_MASK |
SYSCTL_SYSPLLCFG0_ENABLECLK0_MASK |
SYSCTL_SYSPLLCFG0_MCLK2XVCO_MASK));
// enable SYSPLL
SYSCTL->SOCLOCK.HSCLKEN |= SYSCTL_HSCLKEN_SYSPLLEN_ENABLE;
// wait until SYSPLL startup is stabilized
while ((DL_SYSCTL_getClockStatus() & SYSCTL_CLKSTATUS_SYSPLLGOOD_MASK) !=
DL_SYSCTL_CLK_STATUS_SYSPLL_GOOD) {
;
}
}
To repeat:
The hard fault does not occur when:
1. The code was compiled with -O0
. This is also true when I compile only this specific routine with -O0 (using __attribute__((optimize("O0")))
).
2. I'm running the code with a debugger connected.
As such, any programming issues (i.e. the argument config holding some faulty data) can be ruled out from my perspective.
The other occurrence seems to appear with GNU ARM toolchain v9.2.1 only and occurs in the FreeRTOS routine in vPortSuppressTicksAndSleep()
(this requires #define configUSE_TICKLESS_IDLE
1
). I'm not sure exactly where in this routine the hard fault occurs in this case.
What makes this occurrence even weirder is the fact that it goes away when I add an arbitrary interrupt handler to my code instead of letting the "Default_Handler" manage it ... even though this interrupt is neither used nor enabled in the firmware!
Sounds crazy, right? However:
I can reproduce this behavior consistently. Likewise, I can consistently get rid of these issues when I apply any of the "work arounds" mentioned above.
Do you have any explanation for this behavior?
Thanks,
Chris.