STVD 调试STM8S所遇到的问题

环境为主控芯片: STM8SF103F3,编译器 COSMIC8,IDE环境为STVD。

大概代码如下:

        u8 ret; 
	ret=rf_get_addr_len();
	ret=rf_get_trint_level();
	ret=rf_get_drssi_level();
	ret=rf_get_dest_provider();
	ret=rf_get_addr_len();
 使用STLINK进行调试时发现,ret的值根本就不是正确的,我跟踪到具体的函数里面去,检测值是正确的,但为什么赋值给ret后,这个值就不对了呢?

后来google搜后发现一个贴上有说明,内容如下:


一段很简单的代码,跑在ST-DISCOVERY的板子上(实际芯片是STM8S105C6),环境是STVD + COSMIC 4.3.4

float f1 = 3.90, f2 = 2.78, f3 = 0.0;
unsigned int i1 = 3, i2 = 12, i3 = 0;

initMCU(115200);

f3 = f1 * f2;
i3 = i1 * i2;

这样用ST-LINK/SWIM调试下来,结果完全不对:

  (原文件名:test1.JPG) 
引用图片

貌似i3和f3的值仍然是之前的内存保存的值,感觉像完全没有做乘法一样。

而加上volatile后,
volatile float f1 = 3.90, f2 = 2.78, f3 = 0.0;
volatile unsigned int i1 = 3, i2 = 12, i3 = 0;

initMCU(115200);

f3 = f1 * f2;
i3 = i1 * i2;
再运行,结果就都对了:

  (原文件名:test2.JPG) 
引用图片


难道COSMIC/STM8S一定要在局部变量上加上volatile?
看了一下编译器设置,好像DEBUG模式下没有任何的优化啊。

有没有TX有ST-DISCOVERY的一起试一下?

本贴被 curahee 编辑过,最后修改时间:2010-04-21,12:01:27.
 
2010-04-21,12:00:13
资料 邮件 回复 引用回复   ↑↑   ↓↓ 编辑 删除
【1楼】 lianglong
积分:289
派别:
等级:------
来自:
奇怪!  找机会试试
 
2010-04-21,12:48:08
资料 邮件 回复 引用回复   ↑↑   ↓↓ 编辑 删除
【2楼】 dr2001
积分:1433
派别:
等级:------
来自:
建议检查一下汇编代码。

即便是Debug模式,局部变量,在某些地方,也可能有寄存器优化。此时,数据是在寄存器内,不一定会,或者立即,写回内存。而加了volatile,数据一定会被及时更新到内存。
调试器一般不会管理Reg和自动变量的对应关系,而是直接从内存提取数据信息。这种情况下,就会出问题。
 
2010-04-21,12:54:37
资料 邮件 回复 引用回复   ↑↑   ↓↓ 编辑 删除
【3楼】 curahee
积分:25
派别:
等级:------
来自:
会不会编译器认为这段代码毫无意义(乘法结果后面都没用到)给咔嚓了?
 
2010-04-21,13:06:34
资料 邮件 回复 引用回复   ↑↑   ↓↓ 编辑 删除
【4楼】 McuPlayer
积分:471
派别:
等级:------
来自:深圳
优化导致
如果你的某些运算后面没用用到,编译器会帮你把它干掉
如果某个局部表达式后面多次用到,编译器会只在第一次运算,后面的直接使用先前的计算结果

volatile声明此变量是易失的,可以理解为“直接硬件相关”的,所以编译器优化的时候会保持这个变量参与的运算
__________________________
俺的BLOG:http://www.mcuplayer.com
2010-04-21,13:09:14
资料 邮件 回复 引用回复   ↑↑   ↓↓ 编辑 删除
【5楼】 bynce 罗曼

积分:1399
派别:
等级:------
来自:
volatile float f1 = 3.90, f2 = 2.78, f3 = 0.0; 
volatile unsigned int i1 = 3, i2 = 12, i3 = 0; 

initMCU(115200); 

f3 = f1 * f2; 
i3 = i1 * i2; 

你这个是局部变量?把你完整程序帖出来
 
2010-04-21,13:20:18
资料 邮件 回复 引用回复   ↑↑   ↓↓ 编辑 删除
【6楼】 curahee
积分:25
派别:
等级:------
来自:
继续,全部代码是这样的,稍作修改:
void main(void)
{
float f1 = 3.90, f2 = 2.78, f3 = 0.0;
unsigned int i1 = 3, i2 = 12, i3 = 0;

initMCU(115200);

f3 = 0.0;
i3 = 0;

f3 = f1 * f2;
i3 = i1 * i2;

while(1)
{
if( i3 > (u16)f3 )
{
LED_ON;
}
else
{
LED_OFF;
}

}
}

如果不加volatile,执行完的结果:

  (原文件名:test3.JPG) 
引用图片


f3 == f2, i3 == i2 ?? 怎么会连i2和f2的值也会变?


本贴被 curahee 编辑过,最后修改时间:2010-04-21,15:09:53.
 
2010-04-21,15:07:58
资料 邮件 回复 引用回复   ↑↑   ↓↓ 编辑 删除
【7楼】 curahee
积分:25
派别:
等级:------
来自:
引用图片【6楼】curahee  
-----------------------------------------------------------------------

  (原文件名:test3.JPG) 
引用图片


明白了一点,编译器其实没有错,而且很强大,i3和i2分配在同一个地址,还有f3和f2也分配在同一个地址上。

一分钱是掰成两半花的。

总结,COSMIC很节约,会节省每个字节的FLASH/RAM:

1. 没有用的变量和代码会被和谐掉(见1楼的代码)
2. 可以用一个地址分配的变量一定不会用两个地址空间来分配(见6楼的代码和结果)。
3. 加了volatile会绕过这些优化。

挺好!


原文:http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3988838&bbs_page_no=1&search_mode=3&search_text=curahee&bbs_id=9999

你可能感兴趣的:(嵌入式学习)