Other Parts Discussed in Thread: MSP430FR2476
#include <msp430fr2476.h>
#define CPU_F ((unsigned long int) 2000000)
#define delay_us(x) __delay_cycles(CPU_F * x / ((unsigned long int)1000000))
#define delay_ms(x) __delay_cycles(CPU_F * x / ((unsigned long int)1000))
#define delay_s(x) __delay_cycles(CPU_F * x / ((unsigned long int)1))
unsigned long int global_sec_count = 0;
//unsigned long int sec_start;
unsigned char timer1_cfg()
{
TA1CTL &= 0xFFCF; // stop
TA1CTL |= 0x0004; // clear
TA1CTL = 0x01C0; // other
TA1CCTL0 = 0x0000;
TA1CCR0 = 0x0200; // 32768 / 8 / 8
TA1EX0 = 0x0007;
TA1CTL |= 0x0010; //up mode
TA1CTL |= 0x0002; // enable interrupt
return 0;
}
#pragma vector = TIMER1_A1_VECTOR
__interrupt void TIMER1_A1_ISR(void)
{
switch(TA1IV)
{
case 0x00: // Vector 0: No interrupts
break;
case 0x0E:
global_sec_count++;
break;
default:
break;
}
}
unsigned char msp430fr2476_init()
{
WDTCTL = 0x5A29; // enable watchdog
PM5CTL0 &= 0xFFFE;
//------------------------------------
PASEL1 = 0x0000; // PA is IO
PBSEL1 = 0x0000; // PB is IO
PCSEL1 = 0x0000; // PC is IO
PASEL0 = 0x0300; // P2.0 & P2.1 is 32768
PBSEL0 = 0x0000; // PB is IO
PCSEL0 = 0x0000; // PC is IO
//----------------------------------
while(SFRIFG1 & 0x0002)
{
CSCTL7 &= 0xFFFC;
SFRIFG1 &= 0xFFFD;
__no_operation();
__no_operation();
}
__bis_SR_register(SCG0); // disable FLL
CSCTL3 &= 0xFFCF;
CSCTL1 = 0x0033;
CSCTL2 = 60; // 2M / 32768 = 61
delay_us(10);
__bic_SR_register(SCG0); // enable FLL
CSCTL4 = 0x0000;
return 0;
}
unsigned char dummy_func()
{
PAOUT = 0xFFFF;
PAOUT = 0x0000;
return 0;
}
unsigned char main()
{
unsigned long int sec_start;
global_sec_count = 0;
msp430fr2476_init();
timer1_cfg(); // enable timer1 and global_sec_count start to increase
__enable_interrupt();
__no_operation();
__no_operation();
sec_start = global_sec_count;
while((global_sec_count - sec_start) <= 3)// wait 3 seconds
{
// dummy_func();
__no_operation();
delay_s(1);
__no_operation();
}
__no_operation();
return 0;
}
开发环境:
Code Composer Studio 12.4.0.00007
目标平台MSP430FR2476
能够复现问题的代码如上所示。该代码的期望功能是初始化MSP430FR2476,然后开启定时器,定时器每隔1秒钟将global_sec_count的值增加1。之后使用sec_start记录当前global_sec_count的值(因为定时器刚开启,所以sec_start应该为0),在while循环时每隔1秒检测sec_start和global_sec_count的差值,当二者差值超过3,即经过3秒后,结束循环,执行后续代码。
实际执行情况是:
现象1、如果使用在线调试工具让代码自动执行,会发现程序无法跳出循环。暂停程序运行后会发现sec_start的高16位值被改变,使得sec_start的值从正确的值0变为一个随机的值(如图所示为0xE6730000)。此时即使global_sec_count已经大于4(如图所示为7),会仍然在进行循环。

现象2、如果使用仿真器在循环内单步执行程序,sec_start的值能够保持为0,但是即使global_sec_count已经大于4(如图所示为7),会仍然在进行循环。

现象3、如果将77行代码的unsigned long int sec_start;修改为signed long int sec_start;,即将sec_start定义为有符号的长整型,程序就能正确跳出while循环。

现象4、如果将sec_start定义为全局变量,仍然保持其为unsigned long int格式,程序也能正确跳出while循环。

现象5、如果在循环内部调用一个理论上不影响循环的函数(例如代码中的dummy_func()),程序也能正确跳出while循环。

从代码来看现象1和现象2不应该出现,同时在现象3-现象5的情况下解决BUG的问题也很异常。