曾经老是对ARM程序中(*(volatile unsigned long *))不了解,今日看了两篇文章,觉得对了解这个很有用,当然这个不止在界说内部特别寄存器有用,在用到外部总线时,根据具体情况,界说外部器材的地址也能够用。
下面是文章一
总算了解了#define SREG (*(volatile unsigned
CHAR
*)0x5F)
曾经看到#define SREG
(*(volatile unsigned
CHAR
*)0x5F)
这样的界说,总是感觉很古怪,不知道为什么,今日总算有了一点点心得,请大虾们多多批砖~~~
嵌入式体系编程,要求程序员能够运用C言语拜访固定的内存地址。既然是个地址,那么依照C言语的语法规矩,这个表明地址的量应该是指针类型。所以,知道要拜访的内存地址后,比方0x5F,
第一步是要把它强制转换为指针类型
(unsignedCHAR*)0x5F,AVR的SREG是八位寄存器,所以0x5F强制转换为指向
unsignedCHAR类型。
volatile(可变的)这个关键字阐明这变量或许会被意想不到地改动,这样编译器就不会去假定这个变量的值了。这种“意想不到地改动”,不是由程序去改动,而是由硬件去改动——意想不到。
第二步,对指针变量解引证,就能操作指针所指向的地址的内容了
*(volatile unsignedCHAR*)0x5F
第三步,小心肠把#define宏中的参数用括号括起来,这是一个很好的习气,所以#define SREG (*(volatile unsignedCHAR*)0x5F)
相似的,假如运用一个32位处理器,要对一个32位的内存地址进行拜访,能够这样界说#define RAM_ADDR (*(volatile unsignedLONG *)0x0000555F)
然后就能够用C言语对这个内存地址进行读写操作了
读:tmp = RAM_ADDR;
写:RAM_ADDR = 0x55;
已下是文章二
关于不同的计算机体系结构,设备或许是端口映射,也或许是内存映射的。假如体系结构支撑独立的IO地址空间,并且是端口映射,就必须运用汇编言语完结实践对设备的操控,因为C言语并没有供给真实的“端口”的概念。假如是内存映射,那就便利的多了。
以 #define IOPIN(*((volatile unsigned long *) 0xE0028000))为例:作为一个宏界说句子,define是界说一个变量或常量的伪指令。首要( volatile unsigned long * )的意思是将后边的那个地址强制转换成 volatile unsigned long * ,unsigned long * 是无符号长整形,volatile 是一个类型限定符,如const相同,当运用volatile限守时,表明这个变量是依靠体系完成的,以为着这个变量会被其他程序或许计算机硬件修正,因为地址依靠于硬件,volatile就表明他的值会依靠于硬件。
volatile 类型是这样的,其数据的确或许在不知道的情况下发生变化。比方,硬件设备的终端更改了它,现在硬件设备往往也有自己的私有内存地址,比方显存,他们一般是经过映象的方法,反映到一段特定的内存地址傍边,这样,在某些条件下,程序就能够直接拜访这些私有内存了。别的,比方同享的内存地址,多个程序都对它操作的时分。你的程序并不知道,这个内存何时被改动了。假如不加这个voliatile润饰,程序是运用catch傍边的数据,那个或许是过期的了,加了 voliatile,就在需求用的时分,程序重新去那个地址去提取,保证是最新的。归纳起来如下:
1. volatile变量可变答应除了程序之外的比方硬件来修正他的内容
2. 拜访该数据任何时分都会直接拜访该地址处内容,即经过cache进步拜访速度的优化被撤销
关于((volatile unsigned long *) 0xE0028000)为随硬件需求界说的一种地址,前面加上“*”指针,为直接指向该地址,整个界说约好符号IOPIN替代,调用的时分直接对指向的地址寄存器写内容既可。这实践上便是内存映射机制的便利性了。其间volatile关键字是嵌入式体系开发的一个重要特色。上述表达式拆开来剖析,首要(volatile unsigned long *) 0xE0028000的意思是把0xE0028000强制转换成volatile unsigned long类型的指针,暂记为p,那么便是#define A *p,即A为P指针指向方位的内容了。这儿便是经过内存寻址拜访到寄存器A,能够读/写操作。
关于(volatile unsigned char *)0x20咱们再剖析一下,它是由两部分组成:
1)(unsigned char *)0x20,0x20仅仅个值,前面加(unsigned char *)表明0x20是个地址,并且这个地址类型是unsigned char ,意思是说读写这个地址时,要写进unsigned char 的值,读出也是unsigned char 。
2)volatile,关键字volatile 保证本条指令不会因C 编译器的优化而被省掉,且要求每次直接读值。例如用while((unsigned char *)0x20)时,有时体系或许不真实去读0x20的值,而是用第一次读出的值,假如这样,那这个循环或许是个死循环。用了volatile 则要求每次都去读0x20的实践值。
那么(volatile unsigned char *)0x20是一个固定的指针,是不可变的,不是变量。而char*u则是个指针变量。
再在前面加”*”:*(volatile unsigned char *)0x20则变成了变量(一般的unsigned char变量,不是指针变量),假如#define i (*(volatile unsigned char *)0x20),那么与unsigned char i是相同了,只不过前面的i的地址是固定的。
那么你的问题就可回答了,(*(volatile unsigned char *)0x20)可看作是一个一般变量,这个变量有固定的地址,指向0x20。而0x20仅仅个常量,不是指针更不是变量。
声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qiche/adas/263132.html