在嵌入式中,会经常遇到寄存器、内存的数据传输,如何向寄存器中写入数据呢?现举例说明:
#define rDISRC0 (*(volatile unsigned *)0x4b000000) //DMA 0 Initial source
这是s3c2410的DMA的初始源地址寄存器的定义。DISRC0是DMA0的初始源地址寄存器,s3c2410为其分配的地址为:0x4b000000 ;上面的预定义是将0x4b000000先强制转换成指针((volatile unsigned *)0x4b000000),然后再对其进行 * 操作,这样就将rDISRC0变成了变量。
rDISRC0 = 0x38000000 //将0x38000000数据赋值给rDISRC0
这个例子延伸到一个很好的用法:
1、 内存地址可以直接由c语言指针操作,如:
unsigned char *p=(unsigned char*)0xF000FF00;
*p=11;
2、
typedef void (*lpFunction)(); /*定义一个无参数、无返回类型的函数指针类型*/
lpFunction lpReset =(lpFunction)(0xF000FFF0) ;/*定义一个函数指针,指向cpu启动后所执行第一条指令的位置*/
lpReset(); /*调用函数*/
以上程序中,没有定义任何一个函数实体,但是程序中却执行了这样的函数调用:
lpReset(),
它实际上起到了“软重启”的作用,跳转到
CPU
启动后第一条要执行的指令的位置。因此,可以通过函数指针调用一个没有函数体的“函数”,本质上只是换一个地址开始执行。
3、linux程序中,内核链表的访问数据的操作有一个很重要的宏:
list_entry()
其实现如下:
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
//得到type结构体的地址
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
//定义一个和membe变量类型一样的指针__mptr
(type *)( (char *)__mptr - offsetof(type,member) );})
//显然type结构体的地址肯定比member变量的地址低
//于是减去它们的差值就得到真实type结构体的地址
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
//得到MEMBER和TYPE结构体地址之间的差值
理解的关键是(type *)0,就是将0地址强制转换为指向type类型的数据,即0地址为起始地址存放的数据时type类型的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)