使用一个32位处理器,要对一个32位的内存地址进行访问,可以这样定义 
#define RAM_ADDR     (*(volatile unsigned long *)0x0000555F)     然后就可以用C语言对这个内存地址进行读写操作了     读:tmp = RAM_ADDR;     写:RAM_ADDR = 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关键字是嵌入式系统开发的一

var cpro_psid ="u2572954"; var cpro_pswidth =966; var cpro_psheight =120;

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

11.用C对32位内存地址的访问方式的更多相关文章

  1. 怎么样ubuntu 64 11.04 在执行32位程序

    上网一查非常多的信息,头发上的今天ubuntu 64 11.04 在执行32位程序安装ia32-libs包,可执行例如,下面的命令.但提示无法安装 apt-get install ia32-libs ...

  2. java struts2入门学习实例--将客户端IP地址和访问方式输出到浏览器

    实例1:实现客户端IP地址和访问方式输出到浏览器. IpAction.java package com.amos.web.action; import javax.servlet.http.HttpS ...

  3. TCP/IP中32位IP地址与字符串转化

    转载:http://www.cnitblog.com/wujian-IT/archive/2007/10/11/34739.aspx 在网络上面我们用的IP都是数字加点(192.168.0.1)构成的 ...

  4. 深入理解java虚拟机(二)HotSpot Java对象创建,内存布局以及访问方式

    内存中对象的创建.对象的结构以及访问方式. 一.对象的创建 在语言层面上,对象的创建只不过是一个new关键字而已,那么在虚拟机中又是一个怎样的过程呢? (一)判断类是否加载.虚拟机遇到一条new指令的 ...

  5. HotSpot Java对象创建,内存布局以及访问方式

    内存中对象的创建.对象的结构以及访问方式. 一.对象的创建 在语言层面上,对象的创建只不过是一个new关键字而已,那么在虚拟机中又是一个怎样的过程呢? (一)判断类是否加载.虚拟机遇到一条new指令的 ...

  6. 面试题:JVM在Java堆中对对象的创建、内存结构、访问方式

    一.对象创建过程 1.检查类是否已被加载 JVM遇到new指令时,首先会去检查这个指令参数能否在常量池中定位到这个类的符号引用,检查这个符号引用代表的类是否已被加载.解析.初始化,若没有,则进行类加载 ...

  7. 基于32位Windows2003的数据库服务器优化,启用AWE,优化SQL Server

    最近几天,笔者所在的单位中的一台WEB服务器由于负载过大出现了问题,当同时在线的用户达到一定规模(2000-3000)时,频繁出现页面响应迟缓.超时等问题.服务器采用的操作系统是Windows Ser ...

  8. [No0000154]详解为什么32位系统只能用4G内存.

    既然是详解, 就从最基础的讲起了. 或者1来存储数据的, 所以Bit实际上可以看成存放1个二进制数字的1个位置.也就是说bit只有2种值, 0 或者 1, 所以1个bit能存放1个布尔类型的值(boo ...

  9. 详解为什么32位系统只能用4G内存.

    本文转自:https://www.cnblogs.com/nvd11/archive/2013/04/02/2996784.html,感谢作者的干货 既然是详解, 就从最基础的讲起了. 1. Bit( ...

随机推荐

  1. Win10下SQLServer2000的安装

    Win10的技术预览版已经发布近两个星期了,我也迫不及待地装上尝鲜,发现SQLServer2000在Win10上无法安装,在翻遍网上资料和经过无数次尝试后得到了一种安装方法,希望能够帮助遇到类似问题的 ...

  2. D3树状图异步按需加载数据

    D3.js这个绘图工具,功能强大不必多说,完全一个Data Driven Document的绘图工具,用户可以按照自己的数据以及希望实现的图形,随心所欲的绘图. 图形绘制,D3默认采用的是异步加载,但 ...

  3. [Spring] - Quartz定时任务 - Annotation

    Spring + Quartz可以使用annoation方式: 1.AppJob类: package com.my.quartz.testquartz1; import org.springframe ...

  4. [2014.01.27]WFsoft.wfWebCtrl.wfPage 5.9

    wfPage多功能.Net翻页组件,使用简单,功能强大. 提供"首页","上一页","下一页","末页","转 ...

  5. 扩展Redis的Lua调用方式

    Redis是支持Lua脚本的,但是我以为并不方便. 1. SCRIPT LOAD一个字符串拿到一个SHA,首先这个Lua script脚本就很难拿到.Linux一般用cat什么的.但是你作为PHP怎么 ...

  6. 如何使用openssl生成RSA公钥和私钥对

      在ubuntu上要使用openssl的话需要先进行安装,命令如下: sudo apt-get install openssl 安装完成就可以使用openssl了. 首先需要进入openssl的交互 ...

  7. python getopt使用

    函数getopt(args, shortopts, longopts = []) 参数args一般是sys.argv[1:] shortopts 短格式 (-) longopts 长格式(--) 命令 ...

  8. NLog配置文件写入数据库中

    NLog配置文件: <target xsi:type="Database" name="database" connectionString=" ...

  9. Linux命令(22)find的使用

    在linux下面工作,有些命令能够大大提高效率. 比如说find命令,他哥俩可以算是必会的linux命令,几乎每天都要用到他们. find命令 find命令的一般形式 find命令的常用选项及实例 f ...

  10. Android Studio 小技巧/快捷键 合集

    参考: http://jaeger.itscoder.com/android/2016/02/14/android-studio-tips.html 1. 书签(Bookmarks) 描述:这是一个很 ...