#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. Git文件常见下标符号说明

    Git文件常见下标符号说明 git是一种分布式的版本控制工具.     不用联网也能实现版本控制,很实用. 它是一款现在比较流行的版本控制工具. git的文件上的图标,可以反映出当前文件或者文件夹的状 ...

  2. 如何在spring-boot web项目中启用swagger

    swagger的三个项目及其作用 我们打开swagger的官网,会发现有三个swagger相关的项目,它们分别是 swagger-editor 作用是通过写代码,生成文档描述(一个json文件或其他格 ...

  3. ZooKeeper-3.3.4集群安装配置

    https://blog.csdn.net/shirdrn/article/details/7183503

  4. wpgcms---循环导航

    使用wpgcms的时候,在后台设置了导航菜单,那么在前端是如何循环呢? 第一种:简便方法 {% set array = [ {name:'移动APP',icon:'icon-yidongAPP',co ...

  5. 第五天 py if使用

    if 的结果缩进  用个Tab 缩进四个空格就好了

  6. JavaScript基础知识(Number的方法)

    Number的方法 number : 数字 正数 负数 0 NaN 小数; NaN : not a number; 不是一个数字,但是属于数字类型的: 1.typeof :检测当前的数据类型的: 首先 ...

  7. 倒计时48小时|2018GIAC上海站参会攻略来了!

    再过一天,令大家期待已久的GIAC全球互联网架构大会将登陆魔都与众位架构师.技术负责人及高端技术从业人员见面! 这场策划许久的技术盛宴,我们邀请到了腾讯.阿里.京东.美团.keep.UC.360.网商 ...

  8. css学习_css文字阴影、盒子阴影

    文字阴影和盒子阴影的用法: 多阴影

  9. [Day6]引用数据类型、ArrayList 集合

    1.类的定义与使用 (1)类的定义格式 创建java文件,与类名相同 public class 类名{ 数据类型  属性名称1: 数据类型  属性名称2: … } (2)使用格式 导包:我们将所有的类 ...

  10. 跑 vue 项目

    cd ***** npm install  或 yarn(推荐) npm run dev 若是报错: missing script: dev ERR! A complete log of this r ...