(*(volatileunsigned ……

#define  GPIO_CTL_BASE0x56000000                                                

#define rTCFG0  (*(volatileunsigned *)0x51000000)

#define rTCFG1  (*(volatileunsigned *)0x51000004)

#define rTCNTB0  (*(volatileunsigned *)0x5100000C)

#define rTCMPB0  (*(volatileunsigned *)0x51000010)

#define rTCON  (*(volatileunsigned *)0x51000008)

#define rGPBCON  (*(volatileunsigned *)0x56000010)

#define rGPBUP  (*(volatileunsigned *)0x56000018)

#define rGPBDAT  (*(volatileunsigned *)0x56000014) 
 
下面是网上前辈看到的英文资料: 
Using C, I was trying to assign a variable nameto a register address so thatmy 
code would be readable. An example of how to dothis is as follows: 
#define DDRA (*(volatile unsigned char*)(0x22)) 
This means that if a register or memorylocation exists at address 0×22, I canuse 
DDRA to read or write to it likeso.. 
DDRA =0x05 

In my C code.The #define looks really crypticat first. The way to understandthis 
is by breaking it down intopieces. 
First ofall, 
unsignedchar 
means we are using a byte-sized memorylocation. Byte being 8-bitswide. 
unsigned char * means we are declaring apointer that points to a byte-sizedlocation. 
(unsigned char *)(0x22) 
means the byte-sized pointer points to address0×22. The C compiler will referto 
address 0×22 when the variable DDRA is used.The assembly code will end upusing 
0×22 in Load(LD) and Store (STR)insturctions. 
(*(unsigned char*)(0x22)) 
The first asterisk from the left signifies thatwe want to manipulate the valuein 
address 0×22. * means “the value pointed to bythe pointer”. 
volatile 
volatile forces the compiler to issue a Load orStore anytime DDRA is accessedas 
the value may change without the compilerknowing it. 

中文的解释: 

#define DDRA (*(volatile unsigned char*)(0x22)) 
   然后就可以用 C 语言对这个内存地址进行读写操作了 
   读:tmp = DDRA; 
   写:DDRA = 0x55; 
定义 volatile是因为它的值可能会改变,大家都知道为什么改变了; 
如果在一个循环操作中需要不停地判断一个内存数据,例如要等待 RAM_ADDR 的I标志位置
位, 因为 RAM_ADDR 也是映射在 SRAM 空间,为了加快速度,编译器可能会编译出这样的代码:
把 RAM_ADDR 读取到 Register 中,然后不停地判断 Register相应位。而不会再读取
RAM_ADDR,这样当然是不行了,因为程序或其它事件(中断等)会改变RAM_ADDR,结果很
可能是一个死循环出不来了。如果定义成 volatile型变量,编译的代码是这样的:每次要
操作一个变量的时候都从内存中读取一次。 
#define rGPACON(*(volatile unsigned long*)0x56000000) 
对于不同的计算机体系结构,设备可能是端口映射,也可能是内存映射的。如果系统结构支
持独立的IO地址空间,并且是端口映射,就必须使用汇编语言完成实际对设备的控制,因
为 C语言并没有提供真正的“端口”的概念。如果是内存映射,那就方便的多了。 
举个例子,比如像寄存器 A(地址假定为 0x48000000)写入数据0x01,那么就可以这样设
置了。 
#define A (*(volatile unsigned long*)0x48000000) 
... 
    A = 0x01; 
... 
   这实际上就是内存映射机制的方便性了。其中 volatile关键字是嵌入式系统开发的一个重要特点。上述表达式拆开来分析,首先(volatile unsigned long*)0x48000000的意思是把0x48000000 强制转换成 volatile unsigned long 类型的指针,暂记为p,那么就是#defineA *p,即A 为P 指针指向位置的内容了。 这里就是通过内存寻址访问到寄存器 A,
可以读/写操作。 
用 GCC 编译时。volatile所指示的寄存器不进行优化!!! 

理解#definerRTCCON   (*(volatile unsigned char *)0x57000043) //RTCcontrol 
嵌入式系统编程,要求程序员能够利用 C语言访问固定的内存地址。既然是个地址,那么按
照 C语言的语法规则,这个表示地址的量应该是指针类型。所以,知道要访问的内存地址后,
比如0x57000043, 
  第一步是要把它强制转换为指针类型 
(unsigned char *)0x57000043, s3c2410的rRTCCON是单字节访问的(怎么看出来的???
我无法理解),所以 0x57000043 强制转换为指向 unsigned char类型。 
  volatile(可变的)这个关键字说明这变量可能会被意想不到地改变,这样编译器就不
会去假设这个变量的值了。这种“意想不到地改变”,不是由程序去改变,而是由硬件去改
变——意想不到。 
  第二步,对指针变量解引用,就能操作指针所指向的地址的内容了 
   *(volatileunsigned char *)0x57000043 
  第三步,小心地把#define宏中的参数用括号括起来,这是一个很好的习惯。 
在嵌入式系统中经常使用到 Volatile,对于volatile的用法 

编译器对代码的优化是指: 
CPU 在执行的过程中,因为访问内存的速度远没有 cpu的执行速度快,为了提高效率,引入了
高速缓存 cache. C编译器在编译时如果不知道变量会被其它外部因素(操作系统、硬件或者
其它线程)修改,那么就会对该变量进行标识,即优化.那么这个变量在CPU的执行过程中,就
会被放到高速缓存 cache 去,进而达到对变量的快速访问.在了解了优化的概念后,试想如
果我们事先就知道该变量会被外部因素改变,那么我们就在这个变量定义前加上Volatile,
这样编译器就不会对该变量进行优化.这样该变量在 cpu处理的过程当中,就不会被放到高
速缓存 cache中。 
为什么要让变量在执行的过程中不被放到 cache中去呢? 
如果变量是被外部因素改变,那么 cpu就无法判断出这个变量已经被改变,那么程序在执行
的过程中如果使用到该变量,还会继续使用 cache中的变量,但是这个变量其实已经被改变
了.需要到内存地址中更新其内容了. 
还有一个原因,在一些寄存器变量或数据端口的使用中,因为寄存器变量本身也是靠cache
来处理,为了避免引起错误,也可以使用volatile修饰符. 

简单的说使用volatile的目的就是: 
让对 volatile变量的存取不能缓存到寄存器,每次使用时需要重新存取。



参考阅读:

http://hi.baidu.com/hustor/item/e4e90d17a68b883ab93180d9

http://blog.sina.com.cn/s/blog_65861d3f0100xsz0.html

http://www.openedv.com/posts/list/918.htm

发布了40 篇原创文章 · 获赞 9 · 访问量 7万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章