器件型号: MSP430FR2476
大家好:
我目前正在处理一个使用 MSP430FR2xx/4xx 的项目、并实现了时钟系统故障 ISR。
根据 MSP430FR2xx/4xx 系列用户指南、我对故障逻辑的理解如下:
DCO 故障 (DCOFFG): 当 DCO 抽头在 DCO 解锁期间达到 0 或 511 时、会设置该标志。 这可能在两种情况下发生:
- 配置不正确或温度漂移不正确 - N 倍频器对于选定的 DCO 范围设置得太高,导致抽头达到上限 (511 ),或 FLL 失去锁定,抽头达到下限 (0)
- 用作 FLL 基准时的 XT1 HF 晶体故障 -当 XT1 作为 FLL 基准源在 HF 模式下运行时,晶体故障会导致不生成 FLLREFCLK 信号。 FLL 尝试锁定时继续向下计数至零、DCO 抽头移动到最低位置(DCO 位已清除)、并设置 DCOFFG。 这与 XT1 LF 模式不同、在该模式下、晶体故障会自动将 FLLREFCLK 切换至 REFO
XT1 振荡器故障 (XT1OFFG): 如果 XT1 振荡器停止、则设置 XT1OFFG。 每个振荡器都有一个硬件故障计数器、该计数器在发生故障时复位、并在故障条件消除后开始计数。 仅当计数器达到其最大值时、才会清除故障标志:
- XT1 LF 模式下 8192 个周期
- 1024 个周期、在 XT1 HF 模式下
我计划的 ISR 行为如下:
DCO 故障处理:如果设置了 DCOFFG 且 DCO 抽头等于 0 或 511、我会将其解读为 DCO 由于配置问题、温漂或 XT1 HF 晶体故障而达到其调整限值。 在本例中、我计划触发 DCO 重校准例程。 如果故障在多次重试后仍然存在、我将执行软件 POR 作为最后的解决方法恢复机制。
XT1 故障处理:如果设置了 XT1OFFG、则 ISR 将尝试清除故障标志并实施重试循环、反复清除 XT1OFFG 并检查 OFIFG、以便让振荡器硬件计数器有时间达到其最大计数并确认振荡器已稳定。 如果多次尝试后故障仍然存在、则会采取其他恢复措施。
我的问题是:此方法是否与 MSP430FR2xx/4xx 器件的预期时钟故障处理机制一致? 具体来说、是否建议在抽头达到其限值时重新校准 DCO、并使用重试回路让 XT1 振荡器的内部故障计数器在采取进一步措施之前清除?
任何指导或建议的执行模式都将受到极大的赞赏。
#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;
}
}