#def ine reg_gpio_ctrl *(volatile int *)(ToVirtual(GPIO_REG_CTRL))

#define A (*(volatile unsigned long *)0x48000000) 
... 
     A = 0x01; 
...

这实际上就是内存映射机制的方便性了。其中 volatile 关键字是嵌入式系统开发的一个重要特点。

上述表达式拆开来分析,首先(volatile unsigned long *)0x48000000的意思是把 0x48000000 强制转换成 volatile unsigned long 类型的指针,暂记为 p,

那么就是#define A *p, 即A 为P 指针指向位置的内容了。 这里就是通过内存寻址访问到寄存器 A,可以读/写操作。 
用 GCC 编译时。volatile 所指示的寄存器不进行优化!!!

理解#define rRTCCON    (*(volatile unsigned char *)0x57000043) //RTC control

嵌入式系统编程,要求程序员能够利用C语言访问固定的内存地址。既然是个地址,那么按照C语言的语法规则,这个表示地址的量应该是指针类型。所以,知道要访问的内存地址后,比如0x57000043,

第一步是要把它强制转换为指针类型

(unsigned char *)0x57000043,s3c2410的rRTCCON是单字节访问的,所以0x57000043强制转换为指向unsigned char类型。

volatile(可变的)这个关键字说明这变量可能会被意想不到地改变,这样编译器就不会去假设这个变量的值了。这种“意想不到地改变”,不是由程序去改变,而是由硬件去改变——意想不到。

第二步,对指针变量解引用,就能操作指针所指向的地址的内容了

*(volatile unsigned char *)0x57000043

第三步,小心地把#define宏中的参数用括号括起来,这是一个很好的习惯。

volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。

用volatile关键字声明的变量i每一次被访问时,执行部件都会从i相应的内存单元中取出i的值。

没有用volatile关键字声明的变量i在被访问的时候可能直接从cpu的寄存器中取值(因为之前i被访问过,也就是说之前就从内存中取出i的值保存到某个寄存器中),之所以直接从寄存器中取值,而不去内存中取值,是因为编译器优化代码的结果(访问cpu寄存器比访问ram快的多)。

以上两种情况的区别在于被编译成汇编代码之后,两者是不一样的。之所以这样做是因为变量i可能会经常变化,保证对特殊地址的稳定访问。

volatile关键字的作用在于提醒编译器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份;通过这种方式也就给了volatile定义的变量被线程或中断服务子程序共享使用的能力,否则即使变量在中断中修改了,终端返回后读到的值仍然是修改之前的值,这样的程序会出现这样那样不可预知的bug。

*(volatile int *)解读的更多相关文章

  1. const volatile int i

    问题: const volatile int i=10:这行代码有没有问题?如果没有,那 i 到底是什么属性? 回答: 没有问题,例如只读的状态寄存器.它是volatile,因为它可能被意想不到地改变 ...

  2. 嵌入式中的 *(volatile unsigned int *)0x500 解释

    C语言中*(volatile unsigned int *)0x500的解释: 如下: (unsigned int *)0x500:将地址0x500强制转化为int型指针*(unsigned int ...

  3. const volatile同时限定一个类型int a = 10

    const和volatile放在一起的意义在于: (1)本程序段中不能对a作修改,任何修改都是非法的,或者至少是粗心,编译器应该报错,防止这种粗心: (2)另一个程序段则完全有可能修改,因此编译器最好 ...

  4. *(volatile unsigned int *)的理解

    1. 解释 前面是无符号整型unsigned int的指针, 后面加一个地址,就是无符号整型的地址,前面又一个星号就是这个地址的值. 2.volatile 同步 因为同一个东西可能在不同的存储介质中有 ...

  5. AbstractQueuedSynchronizer源码解读

    1. 背景 AQS(java.util.concurrent.locks.AbstractQueuedSynchronizer)是Doug Lea大师创作的用来构建锁或者其他同步组件(信号量.事件等) ...

  6. 面试(三)---volatile

    一.前言       最近去成都玩了一圈,整体感觉还不错,辞职以后工作找的也很顺利,随着年龄增加自己也考虑定居和个人长期发展的问题,反正乱七八糟的事,总之需要好好屡屡思路,不能那么着急下定论,当然我对 ...

  7. java并发编程之volatile

    Java语言规范第三版中对volatile的定义如下:Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量. 了解volatile关键字之 ...

  8. 关于多线程start()方法原理解读

    1.为什么启动线程不用run()方法而是使用start()方法 run()方法只是一个类中的普通方法,调用run方法跟调用普通方法一样 而start()是创建线程等一系列工作,然后自己调用run里面的 ...

  9. J.U.C剖析与解读2(AQS的由来)

    J.U.C剖析与解读2(AQS的由来) 前言 前面已经通过实现自定义ReentrantLock与自定义ReentrantReadWriteLock,展示了JDK是如何实现独占锁与共享锁的. 那么实际J ...

随机推荐

  1. 宣布推出针对 Microsoft OneDrive 和 SharePoint 的 Autodesk AutoCAD 新集成

    在 OneDrive 和 SharePoint,我们的愿景是随时随地为你的团队提供简单而安全的文件访问.无论你的职位.专业或行业是什么,我们将始终致力于扩展和连接你最重视的内容.今天,我们发布了与 A ...

  2. 在php cli下可以使用 STDIN 来实现标准输入

    简单的例子:  echo "请输入一个数字:";  $num = trim(fgets(STDIN)); echo "请再输入一个数字:";  $num1 =  ...

  3. 自闭的D7

    先是一道**题然后我死了啊. A: 哇人人都会我不会系列. 我们可以运用逆向思维啊,把它转化成若干个人从点1进来, 然后我们考虑深度 dep,用 num[dep] 表示深度大于等于这个点的有多少个, ...

  4. Codeforces Round 504

    (交互题真神奇,,,我自己瞎写了一发目测样例都没过去就AC了...) (只出了两题的竟然没掉下蓝名真是可怕) A:我的代码太不美观了,放个同学的(因为我是c++63分的蒟蒻所以根本不知道那些函数怎么用 ...

  5. thinkphp5中使用PHPExcel(转载)

    thinkphp5中可以使用composer来获取第三方类库,使用起来特别方便,例如:可是使用composer下载PHPMailer,think-captcha(验证码)等等…… 接下来说一下怎么使用 ...

  6. 浅谈编码Base64、Hex、UTF-8、Unicode、GBK等

    网络上大多精彩的回答,该随笔用作自我总结: 首先计算机只认得二进制,0和1,所以我们现在看到的字都是经过二进制数据编码后的:计算机能针对0和1的组合做很多事情,这些规则都是人定义的:然后有了字节的概念 ...

  7. ubuntu14.04 LTS 更新国内网易163源

    2015/10/7 更改ubuntu的默认源是linux学习中必须掌握的基础技能.在此记录,以作参考. 在ubuntu14.04 LTS默认使用的是国外源,由于网络的原因,使用apt-get安装包时异 ...

  8. height:100%

    子元素的高度设置为height:100%时 继承父元素的高度为border+height 子元素的高度为height: 此时父元素的 box-sizing:content-box: border-bo ...

  9. jq1.9.0以上版本不兼容live()解决方法

    最近一个项目里用bootstrap做图形渲染,需要用到jq1.9以上版本,而copy的js代码里用到了live()方法,故两者产生了兼容问题,下面是解决方案: $('#my').on("cl ...

  10. RTOS 和中断之间要注意的

    #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY   15 #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRI ...