您好!
TimerB 出现意外行为导致 WDT 复位。 我正在使用的微控制器是 MSP430FR5989。
上下文:
微控制器会定期调用一个例程、对适合在一个 ACLK 周期内的 SMCLK 节拍数进行计数。
此例程首先将 TimerA (由 ACLK 提供)置于捕获模式(即触发它的模块)、从而禁用中断并"暂停"持续运行的 DMA。
这可以防止计时器设置 CCIFG、因为其 CCTL 寄存器的 CM 字段设置为"无捕捉"。
一旦 DMA 暂停、系统看门狗就会启动、超时为2ms、这对于
此例程的执行时间(ACLK 频率= 32kHz -> ACLK 周期~ 30us)。
然后执行 SMCLK 节拍计数器代码、该代码已按如下方式实现:
__no_init static volatile UCHAR WDTResetCause; UINT16 CountTicks( void ) { UINT16 startTA0R, stopTA0R, deltaTA0R; istate_t local_istate = __get_interrupt_state(); __disable_interruption(); TA1CTL_bit.TAIFG = false; TA1CCTL0_bit.CAP = true; WDTResetCause = 0xAA; WDTCTL = WDTPW | WDTPW | WDTCNTCL | WDTSSEL0 | WDTIS2 | WDTIS1 | WDTIS0; TB0CCR1 = TB0R + 1; TB0CCTL1_bit.CCIFG = false; while ( ! TB0CCTL1_bit.CCIFG ) { } startTA0R = TA0R; TB0CCR1 += 1; TB0CCTL1_bit.CCIFG = false; while ( ! TB0CCTL1_bit.CCIFG ) { } stopTA0R = TA0R; deltaTA0R = stopTA0R - startTA0R; WDTCTL = WDT_STOP; WDTResetCause = 0x00; TA1CCTL0_bit.CAP = false; __set_interrupt_state(local_istate); return deltaTA0R; }
TimerA0配置:
TA1CTL = TASSEL__ACLK | ID__1 | MC__CONTINUOUS | TACLR; TA1CCTL0 = !CAP | OUTMOD_0 | !CCIE; TA1EX0 = TAIDEX_0;
计时器 B1配置:
TB0CTL = TBSSEL__ACLK | ID__1 | MC__CONTINUOUS | TBCLGRP_0 | CNTL_0 | TBCLR; TB0CCTL1 = !CAP | OUTMOD_0 | CLLD_0 | !CCIE; TB0EX0 = TBIDEX_0;
DMA 配置:
DMA0CTL_bit.DMAEN = false; DMACTL4_bit.DMARMWDIS = true; DMACTL0 = ( DMACTL0 & ~DMA0TSEL_31 ) | DMA0TSEL__TA1CCR0; DMA0CTL |= !DMADT0 | !DMADSTINCR0 | !DMADSTINCR1 | DMASRCINCR0 | DMASRCINCR1 | !DMASRCBYTE | !DMADSTBYTE | !DMALEVEL | !DMAIFG | !DMAIE | !DMAABORT | !DMAREQ;
错误描述:
我们几个使用同一微控制器(MSP430FR5989)的器件已由在此例程中启动的看门狗进行复位。 这表示 TimerB 中断
标志已丢失或计时器初始化与其递增之间代码执行超过30us (1个 ACLK 节拍)。 无论哪种方式、程序都必须等待将近2秒
发起一个安全装置复位。
此外、我阅读了微控制器的勘误表、想要寻找中断标志丢失的可能解释、而且我发现、根据勘误表 DMA7、
如果在包含中断标志的模块寄存器的读取-写入-修改执行期间 DMA 请求开始执行、那么可能会丢失模块中断。
仅供参考、发生故障的器件只有此例程是相同的、程序的其余部分及其硬件完全不同且独立。 此外、
他们已经运行了很长一段时间没有问题(现在是1.5年)。
很多其他设备的固件与它们完全相同、并且不会出现此问题、因此这实际上不是一个反复出现的问题。
我试图通过模拟 DMA7勘误表的情况重现错误、但我没有运气。
Question:
前面所述的理论(尤其是 DMA7勘误表)是否可能导致此错误? 如果是、如何重现错误?
还有其他可以尝试的东西吗?
其他信息:
DCO 频率= 8MHz
MCLK 和 SMCLK 频率= 4MHz
ACLK 频率= 32kHz
__no_init static volatile UCHAR WDTResetCause; UINT16 CountTicks( void ) { UINT16 startTA0R, stopTA0R, deltaTA0R; istate_t local_istate = __get_interrupt_state(); __disable_interruption(); TA1CTL_bit.TAIFG = false; TA1CCTL0_bit.CAP = true; WDTResetCause = 0xAA; WDTCTL = WDTPW | WDTPW | WDTCNTCL | WDTSSEL0 | WDTIS2 | WDTIS1 | WDTIS0; TB0CCR1 = TB0R + 2; TB0CCTL1_bit.CCIFG = false; while ( ! TB0CCTL1_bit.CCIFG ) { } startTA0R = TA0R; TB0CCR1 += 1; TB0CCTL1_bit.CCIFG = false; while ( ! TB0CCTL1_bit.CCIFG ) { } stopTA0R = TA0R; deltaTA0R = stopTA0R - startTA0R; WDTCTL = WDT_STOP; WDTResetCause = 0x00; TA1CCTL0_bit.CAP = false; __set_interrupt_state(local_istate); return deltaTA0R; }