打印

请教:volatile关键字

[复制链接]
3135|13
手机看帖
扫描二维码
随时随地手机跟帖
沙发
computer00| | 2009-6-4 22:11 | 只看该作者

volatile告诉编译器不要对这个变量进行代码上的优化

使用特权

评论回复
板凳
beercola| | 2009-6-4 23:51 | 只看该作者

补充下

比如:
volatile int i;
i=0;
i=1;
i=2;
上面的所有语句逐条执行。
int i;
i=0;
i=1;
i=2;
优化之后仅执行最后一句i=2;
一般对功能寄存器地址的访问加volatile修饰。

使用特权

评论回复
地板
guolingho| | 2009-6-23 20:29 | 只看该作者

不优化有什么好处呢?

关注!不优化有什么好处呢?
我知道在进行浮点运算时,优化后的代码和不优化的代码可能存在差别(由于浮点运算存在舍入误差)。那么在整数运算时应该来说优化与否结果都会相同的那么不优化有什么作用呢?希望楼上能够做进一步的发挥哈!

使用特权

评论回复
5
zyboy| | 2009-6-24 10:00 | 只看该作者

ARM字对齐有趣现象

TCPIP协议栈一直采用的uip,感觉不是很好,想采用网上的流行的lwip协议,移植中出现了个有趣的问题,找了好半天才找到,具体不太好描述,用下面这个例子说一下(我用的是KEIL)

在KEIL下测试结构

testzy =(unsigned long *)0x0400130e;
* testzy = 0x11223344;            //0x0400130C(44 33 22 11)    * testzy 真实值变成了 0x00001122

反汇编看

R0=0x11223344;
R1=0x0400130e;

STR  R0,[R1]  ; 显然由于地址0x0400130e不是4的倍数,数据向前移动了 (R0=0x00001122,而不是0x44332211)

但在IAR测试下,结果又是正确的。

不知道在ADS测试如何,不知道哪个仁兄测试看看,谢谢!

在lwip出现问题的地方,是mem_malloc()分配内存时候错误,之所以采用自定义,我想是不是采用自带的malloc会容易产生内存碎片,
由于采用mem_malloc,它分配内存的地址并没有按四个字节的倍数来分,这样往导致分配好后的地址(该地址不是4的倍数)赋值的时候出错

使用特权

评论回复
6
wangkj| | 2009-6-24 10:45 | 只看该作者

这个关键字是对应 IO端口地址的

你这样用毫无意义。

只有针对IO端口,才有意义。
IO端口随时可能变化,所以,每次回读的结果可能不一样。
而内存单元,没有写,回读的内容是一致的,这样,编译器就可能优化掉。

另外,有时候,这样做也可能不好使,甚至必须关闭对应的硬件cache。
这可能就是硬件设计的bug了。

如果没有硬件bug,这样做,基本io就能得到正确的数据了。

使用特权

评论回复
7
TRUE_ARM| | 2009-6-24 11:40 | 只看该作者

一个例子



SysV.Delay = 2;

while(SysV.Delay)
{
 
   //
   printf("Hello.!") ;
}

//--------------------------
如果 SysV.Delay 的类型为
1、  BYTE 类型,在ADS 中有可能是死循环,结果就像 while(1)
2、  volatile BYTE 类型 ,不会是死循环,原因就是每次循环都会
     读取 SysV.Delay 变量,当外部程序把SysV.Delay 清零的 时候
     就会退出这个循环。

使用特权

评论回复
8
Fe_ARM| | 2009-6-24 17:29 | 只看该作者

抑制编译器优化,直接从内存地址取数

抑制编译器优化,直接从内存地址取数

使用特权

评论回复
9
guolingho| | 2009-6-29 20:57 | 只看该作者

明白

表明该地址变量可能被外部修改,编译器不做优化。而使得外部变量修改是在该处能够反映该变量的修改!

使用特权

评论回复
10
philofly| | 2009-6-29 21:30 | 只看该作者

看了半天,只有老王说到点子上了

核心就是cache啊,valotile这个关键字就是为cache设计的啊

使用特权

评论回复
11
聆风| | 2009-6-30 09:08 | 只看该作者

在keil c51中一样要用volatile关键字.

51单片机没有cache

使用特权

评论回复
12
wangkj| | 2009-6-30 09:16 | 只看该作者

我说的是两个问题

一个是软件优化问题,另外一个是硬件设计问题。
这两个等可能造成读取数据错误。

解决方案也是两个方面,
一个是加这个关键字,另外一个就是禁用cache。

测试成功后,可以考虑打开cache测试,如果正常,说明硬件设计没有bug。

voliate 关键字,如果用不用都行,说明没有优化。

使用特权

评论回复
13
guolingho| | 2009-7-11 10:50 | 只看该作者

最近写了一个程序,确实感觉volatile关键字太有用了。不容忽

最近写了一个程序,确实感觉volatile关键字太有用了。不容忽视!
尤其是中断和主程序公用的变量,必须声明称volatile标识的,否则可能会使得编译器优化不能正确的优化!
如连续执行
A *= 3;  
A *= 4;
有Volatile标识的代码编译结果为
    A *= 2;
  08002A1C  9800      LDR          R0, [SP, #0]
  08002A1E  2102      MOVS         R1#0x2
  08002A20  4348      MULS         R0, R1, R0
  08002A22  9000      STR          R0, [SP, #0]
    A *= 3;
  08002A24  9800      LDR          R0, [SP, #0]
  08002A26  2103      MOVS         R1#0x3
  08002A28  4348      MULS         R0, R1, R0
  08002A2A  9000      STR          R0, [SP, #0]
也就是每次都从堆栈取数据,运算后,然后存入堆栈。没有任何的优化,最大限度的遵循了编程者自己的意思。

没有Volatile标识的代码编译结果为
    A *= 2;
  08002A1A  2002      MOVS         R0#0x2
  08002A1C  4344      MULS         R4, R0, R4
    A *= 3;
  08002A1E  2003      MOVS         R0#0x3
  08002A20  4344      MULS         R4, R0, R4
没有任何的堆栈存取操作,都被优化成寄存器内执行。

另外 TRUE_ARM 兄遇到的问题我也遇到了,确实是这样的,在Debug版本下没有死循环,但是在 优化的版本下就有死循环了,编译器认为该循环控制变量没有被修改,而被优化掉,导致死循环。

使用特权

评论回复
14
511| | 2009-7-12 09:32 | 只看该作者

举得例子很好

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

8

帖子

0

粉丝