嵌入式开发(*(volatile unsigned long *)) 认识
2023-09-11 14:21:01 时间
一个、说明
(*(volatile unsigned long *))
这个语句对于不同的计算机体系结构,设备可能是port映射,也可能是内存映射的。
假设系统结构支持独立的IO地址空间。而且是port映射,就必须使用汇编语言完毕实际对设备的控制。由于C语言并没有提供真正的“port”的概念。假设是内存映射。那就方便多了。
二、举例解说
以 #define IOPIN (*((volatile unsigned long *)0xE0028000))为例:
作为一个宏定义语句,define是定义一个变量或常量的伪指令。首先 (volatile unsigned long *) 的意思是将后面那个地址强制转换成 volatile unsigned long * , unsigned long *是无符号长整型,volatile是一个类型限定符,如const一样。当使用volatile限定时,表示这个变量是依赖系统实现的。意味着这个变量会被其它程序或者计算机硬件改动。因为地址依赖于硬件,volatile就表示他的值会依赖于硬件。
volatile 类型是这种,其数据确实可能在未知的情况下发生变化。比方,硬件设备的终端更改了它,如今硬件设备往往也有自己的私有内存地址,比方显存,他们通常是通过映象的方式,反映到一段特定的内存地址其中。这样,在某些条件下,程序就能够直接訪问这些私有内存了。另外,比方共享的内存地址。多个程序都对它操作的时候。你的程序并不知道。这个内存何时被改变了。
假设不加这个voliatile修饰,程序是利用cache其中的数据,那个可能是过时的了,加了 voliatile,就在须要用的时候,程序又一次去那个地址去提取,保证是最新的。归纳起来例如以下:
1. volatile变量可变同意除了程序之外的比方硬件来改动他的内容
2. 訪问该数据不论什么时候都会直接訪问该地址处内容,即通过cache提高訪问速度的优化被取消
对于((volatile unsigned long *) 0xE0028000)为随硬件须要定义的一种地址,前面加上“*”指针。为直接指向该地址,整个定义约定符号IOPIN取代,调用的时候直接对指向的地址寄存器写内容既可。
这实际上就是内存映射机制的方便性了。当中volatilekeyword是嵌入式系统开发的一个重要特点。
上述表达式拆开来分析,首先(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。keywordvolatile 确保本条指令不会因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仅仅是个常量,不是指针更不是变量。
參考文章:http://blog.sina.com.cn/s/blog_65861d3f0100xsz0.html
版权声明:本文博客原创文章,博客,未经同意,不得转载。
相关文章
- IAR嵌入式工作台IDE _ (__no_init) 绝对定位
- 嵌入式(交叉编译工具链)
- 《嵌入式C编程:PIC单片机和C编程技术与应用》一1.4 C预编译指令
- 《嵌入式Linux开发实用教程》——4.2 字符设备驱动
- 《嵌入式系统开发之道——菜鸟成长日志与项目经理的私房菜》——02-10 项目风险(Risk)管理
- 《嵌入式 Linux C 语言应用程序设计(修订版)》——本章小结
- 《嵌入式Linux软硬件开发详解——基于S5PV210处理器》——2.5 WM8960音频编解码芯片
- 《嵌入式Linux与物联网软件开发——C语言内核深度解析》一2.6 位运算实战演练2
- 《Linux嵌入式实时应用开发实战(原书第3版)》——3.8 获得帮助
- 从半定制化与嵌入式看起-浅谈AMD的未来发展
- 【嵌入式Linux驱动开发】八、LED驱动尽善尽美 - 设备树点亮一盏假的LED
- 【嵌入式Linux学习】Linux基础知识(总结版)
- 【蓝桥杯嵌入式组】五、TIM的定时中断
- 【正点原子FPGA连载】 第二十五章SD卡读BMP图片HDMI显示实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南
- 【正点原子FPGA连载】第十五章eMMC读写测试实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南
- 【正点原子FPGA连载】第九章Linux图形界面的搭建摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Linux开发指南
- 【正点原子FPGA连载】第六章Petalinux设计流程实战摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Linux开发指南
- 【正点原子Linux连载】第八章 文本读写摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2
- 【正点原子Linux连载】第二十六章 APP主界面开发项目 摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2
- 【正点原子MP157连载】第四十一章 RGB转HDMI实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7
- 【正点原子Linux连载】第三十二章 U-Boot启动流程详解 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
- 【正点原子Linux连载】第十六章主频和时钟配置实验-摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
- 【正点原子Linux连载】第十五章按键输入试验-摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
- 【嵌入式开发学习】__为什么在C语言中能用指针修改const常量
- ROS(5):嵌入式开源开发板 FirePrime
- 17条嵌入式C语言编程小知识总结