TI中文支持网
TI专业的中文技术问题搜集分享网站

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

Part Number:CODECOMPOSEROther 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 IOPBSEL1 = 0x0000;// PB is IOPCSEL1 = 0x0000;// PC is IOPASEL0 = 0x0300;// P2.0 & P2.1 is 32768PBSEL0 = 0x0000;// PB is IOPCSEL0 = 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的问题也很异常。

Eirwen:

已经收到了您的案例,调查需要些时间,感谢您的耐心等待。

,

Daniel:

您好

Liu Kai 说:

现象1、如果使用在线调试工具让代码自动执行,会发现程序无法跳出循环。暂停程序运行后会发现sec_start的高16位值被改变,使得sec_start的值从正确的值0变为一个随机的值(如图所示为0xE6730000)。此时即使global_sec_count已经大于4(如图所示为7),会仍然在进行循环。

我假设已启用-O0(寄存器级)优化。您能否尝试完全禁用优化(设置为-Ooff),以便sec_start位于RAM中?然后看看程序是否按预期运行。

,

Liu Kai:

上述结果是在已启用-O0(寄存器级)优化时的现象。完全禁用优化(设置为-Ooff)后,sec_start被分配到0x003FF8地址处,程序能够正常跳出循环,按照预期运行。

但是我实际项目中的代码量比较大,为了能让程序运行在MSP430FR2476上,我编译的时候是开启O2级别优化以减小程序存储器占用的。

在开启O2级别优化的情况下,在现象1、2的条件下程序无法退出循环,和O0优化级别相同;在现象5的条件下程序可以退出循环,和O0优化级别相同;但是在现象3、4的条件下程序变得无法退出循环。因为开启O2优化后“Variables”窗口已经无法显示sec_start的数值,所以无法确认其内容是否正确。

有没有办法在不禁用优化的情况下修复这个问题呢?

,

Daniel:

您好

http://software-dl.ti.com/ccs/esd/documents/sdto_cgt_How-to-Submit-a-Compiler-Test-Case.html

请您参考这个说明进行操作。

,

Liu Kai:

这个是链接里需要的文件。

bug_report.zip

,

Daniel:

您好

谢谢你的测试用例。我把它编译成汇编代码。我看到了一些似乎不对劲的东西。我会提交一份条目并回复您。

,

Daniel:

您好

EXT_EP-12754

该条目目前描述模糊且不够准确。在错误得到明确描述后,我们会改进此条目。

赞(0)
未经允许不得转载:TI中文支持网 » CODECOMPOSER: 使用定时器进行延时操作时循环无法退出
分享到: 更多 (0)

© 2025 TI中文支持网   网站地图 鲁ICP备2022002796号-1