This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CODECOMPOSER: 使用定时器进行延时操作时循环无法退出

Part Number: CODECOMPOSER
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的问题也很异常。