标签:
使用结构体操作寄存器:
//寄存器赋值和取值的时候,要注意寄存器的长度,有的寄存器的值只有8位。 //还要注意,使用volatile修饰寄存器变量。
//addr.h typedef unsigned int S3C24X0_REG32; /* NAND FLASH (see S3C2410 manual chapter 6) */ typedef struct { S3C24X0_REG32 NFCONF; S3C24X0_REG32 NFCMD; S3C24X0_REG32 NFADDR; S3C24X0_REG32 NFDATA; S3C24X0_REG32 NFSTAT; S3C24X0_REG32 NFECC; } S3C2410_NAND; //nand.c static S3C2410_NAND* s3c2410nand = (S3C2410_NAND *)0x4e000000; //如此,s3c2410nand 表示寄存器组的起始地址 。 //&s3c2410nand->NFCMD 表示NFCMD寄存器的地址 。 //s3c2410nand->NFCMD 表示NFCMD寄存器的值 。 //寄存器赋值和取值的时候,要注意寄存器的长度,有的寄存器的值只有8位。 //还要注意,使用volatile修饰寄存器变量。 /* 读取数据 */ static unsigned char s3c2410_read_data(void) { volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFDATA; return *p; }
嵌入式编程中经常用到 volatile这个关键字,在网上查了下他的用法可以归结为以下两点:[1] 一:告诉compiler不能做任何优化 比如要往某一地址送两指令: int *ip =...; //设备地址 *ip = 1; //第一个指令 *ip = 2; //第二个指令 以上程序compiler可能做优化而成: int *ip = ...; *ip = 2; 结果第一个指令丢失。如果用volatile, compiler就不允许做任何的优化,从而保证程序的原意: volatile int *ip = ...; *ip = 1; *ip = 2; 即使你要compiler做优化,它也不会把两次付值语句间化为一。它只能做其它的优化。这对device driver程序员很有用。
再比如如下程序:[2] XBYTE[2]=0x55; XBYTE[2]=0x56; XBYTE[2]=0x57; XBYTE[2]=0x58; 如果对外部硬件上述四条语句分别表示不同的操作,会产生四种不同的动作,那么编译器就不能像对待纯粹的程序那样对上述四条语句进行优化只认为XBYTE[2]=0x58,而忽略前三条语句,并且只产生1条机器码。如果XBYTE用volatileo修饰过,此时编译器会逐一的进行编译并产生相应的4条机器码。
二:表示用volatile定义的变量会在程序外被改变,每次都必须从内存中读取,而不能把他放在cache或寄存器中重复使用。 如 volatile char a; a=0; while(!a){ //do some things; } doother(); 如果没有 volatile doother()不会被执行
下面是volatile变量的几个例子:[就是使用过程中可能被硬件或者其他进程改变。]
1). 并行设备的硬件寄存器(如:状态寄存器)
2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3). 多线程应用中被几个任务共享的变量
参考
1、C中的volatile用法 http://www.cnblogs.com/chio/archive/2007/11/24/970632.html
2、Volatile相关知识 http://www.100ask.org/bbs/forum.php?mod=viewthread&tid=3902&highlight=volatile
标签:
原文地址:http://www.cnblogs.com/mylinux/p/4187246.html