Part Number: MSP430FR2476
Hello everyone,
I am currently working on a project using the MSP430FR2xx/4xx and implementing the Clock System fault ISR.
Based on the MSP430FR2xx/4xx Family User's Guide, my understanding of the fault logic is the following:
DCO Fault (DCOFFG): The flag is set when the DCO tap reaches 0 or 511 while the DCO is unlocked. This can occur in two scenarios:
- Incorrect configuration or temperature drift - the N-multiplier is set too high for the selected DCO range, causing the tap to hit the ceiling (511), or the FLL loses lock and the tap hits the floor (0)
- XT1 HF crystal failure while used as the FLL reference - when XT1 is operating in HF mode as the FLL reference source, a crystal fault causes no FLLREFCLK signal to be generated. The FLL continues counting down to zero attempting to lock, the DCO tap moves to the lowest position (DCO bits cleared), and DCOFFG is set. This is distinct from XT1 LF mode, where a crystal fault automatically switches FLLREFCLK to REFO instead
XT1 Oscillator Fault (XT1OFFG): If the XT1 oscillator stops, XT1OFFG is set. Each oscillator has a hardware fault counter that resets when a fault occurs and starts counting once the fault condition is removed. The fault flag is cleared only when the counter reaches its maximum value:
- 8192 cycles in XT1 LF mode
- 1024 cycles in XT1 HF mode
My planned ISR behavior is as follows:
DCO Fault Handling: If DCOFFG is set and the DCO tap equals 0 or 511, I interpret this as the DCO hitting its adjustment limits due to either a configuration issue, temperature drift, or XT1 HF crystal failure. In this case I plan to trigger a DCO recalibration routine. If the fault persists after several retries, I perform a software POR as a last resort recovery mechanism.
XT1 Fault Handling: If XT1OFFG is set, the ISR will attempt to clear the fault flag and implement a retry loop that repeatedly clears XT1OFFG and checks OFIFG, allowing time for the oscillator hardware counter to reach its maximum count and confirm the oscillator has stabilized. If the fault persists after multiple attempts, additional recovery actions are taken.
My question is: Does this approach align with the intended clock fault handling mechanism for the MSP430FR2xx/4xx devices? Specifically, is it recommended to recalibrate the DCO when the tap reaches its limits, and to use a retry loop to allow the XT1 oscillator's internal fault counter to clear before taking further action?
Any guidance or recommended implementation patterns would be greatly appreciated.
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=UNMI_VECTOR
__interrupt void UNMI_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(UNMI_VECTOR))) UNMI_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(HWREG16(__MSP430_BASEADDRESS_SYS__ + OFS_SYSUNIV), SYSUNIV__OFIFG)) {
case SYSUNIV__NONE: //OFFSET 0
break;
case SYSUNIV__NMIIFG: //OFFSET 2
break;
case SYSUNIV__OFIFG:{ //OFFSET 4
uint8_t csctl7 = HWREG8(CS_BASE + OFS_CSCTL7_L);
if(csctl7 & DCOFFG) {
HWREG8(CS_BASE + OFS_CSCTL7_L) &= ~DCOFFG;
HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;
count_DCO_fail++;
if(!(HWREG8(SFR_BASE + OFS_SFRIFG1) & OFIFG)) {
count_DCO_fail = 0; // Reset consecutive counter if fixed
}
if(count_DCO_fail >= 10) {
HWREG16(PMM_BASE + OFS_PMMCTL0) = PMMPW | PMMSWPOR; // 10-strike POR
}
}
else if (csctl7 & XT1OFFG){
if ((HWREG16(CS_BASE + OFS_CSCTL4) & SELMS) == CS_XT1CLK_SELECT){
HWREG16(CS_BASE + OFS_CSCTL4) &= ~SELMS;
HWREG16(CS_BASE + OFS_CSCTL4) |= CS_REFOCLK_SELECT;
}
if ((HWREG16(CS_BASE + OFS_CSCTL4) & SELA) == SELA__XT1CLK){
HWREG16(CS_BASE + OFS_CSCTL4) &= ~SELA;
HWREG16(CS_BASE + OFS_CSCTL4) |= SELA__REFOCLK;
}
HWREG8(CS_BASE + OFS_CSCTL7_L) &= ~XT1OFFG;
HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;
}
break;
}
default:
break;
}
}