使用一个32位处理器,要对一个32位的内存地址进行访问,可以这样定义
#define RAM_ADDR (*(volatile unsigned long *)0x00000000)
然后就可以用C语言对这个内存地址进行读写操作了
读:tmp = RAM_ADDR;
写:RAM_ADDR = 0x55;
volatile的意思是说明这个变量是可能被别的程序或者本程序的其他线程修改的,这样编译器就不能优化它,每次读取都从地址中获取。如果不这样声明的话编译器可以把它缓冲在寄存器中的,这样别的程序修改了它,而寄存器里面的值却是原先的,会发生你不想要的结果。而上面三种情况都是这种可能在本程序或者本线程外被修改的情况,所以要加它。
注意几点:
1.(volatile unsigned long *)0x00000000 说明是一个指针类型,地址在0x00000000
2.在前面加上个*,表示指向这个地址的内容。
3.养成在整体外面再加个括号的习惯。
转载地址:http://blog.sina.com.cn/s/blog_6d8f724b0100mq3a.html
先看一个例子:
*(volatile unsigned int *)0x500 = 0x10
- 1
①(unsigned int *)0x500:将地址0x500强制转化为int型指针
②(unsigned int )0x500=0x10:对地址为0x500赋值为0x10
volatile关键字有以下用途:
用来同步,因为同一个东西可能在不同的存储介质中有多个副本,有些情况下会使得这些副本中的值不同,这是不允许的,所以干脆用volatile,让它只有一个,没有其他的副本,这样就不会发生不同步的问题。
如volatile的意思是告诉编译器,在编程源代码时,对这个变量不要使用优化。
在一般的程序设计中,如:int *a; int b;b = (*a) * (*a);
这种情况下通常编译器为了减少存储器的读写时间,会把代码优化为int *a; int b; int c;
如果把
c = *a;b = c * c;int *a
改为volatile int* a
编译器就不会自动把它优化掉了。在整个运算过程中,对变量*a的值又读取了一次。防止因变量*a的值在这一期间发生了改变,而导致程序结果的错误。防止编译器优化去掉某些语句
我在arm中见到个寄存器非常奇怪,
当中断来的时候,相对应的位置1,而清0又不能向这位写0,向这位写1才是1才是清中断(清0),
// 假设0x560012300 为寄存器地址#define INTPAND *(volatile unsigned int *)0x560012300
;
INTPAND = INTPAND; // 清中断
像编译器如果看到有INTPAND = INTPAND;这种看似无用的操作,如果没有volatile说明,编译器就很有可能会去掉INTPAND = INTPAND;实际上有用的东西,却被编译器当没用的东西优化掉了。当地址是io端口的时候,读写这个地址是不能对它进行缓存的,这是相对于某些嵌入式中有cache才有这个。
比如写这个io端口的时候,如果没有这个volatile,很可能由于编译器的优化,会先把值先写到一个缓冲区,到一定时候
再写到io端口,这样就不能使数据及时的写到io端口,有了volatile说明以后,就不会再经过cache,write buffer这种,而是直接写到io端口,从而避免了读写io端口的延时。