在阅读uboot源码,linux内核,一些单片机平台的系统头文件中,经常会遇到定义一个固定地址的变量。理解它们的用法对于阅读源码很有帮助。
首先看一个熟悉的定义:
#define GPFCON (*(volatile unsigned int*)5000)
#define GPFCON (*(volatile unsigned char*)5000)
这两句话的意思是:1,定义unsigned int 型变量GPFCON,并绑定变量所在的内存地址为5000;2,定义一个unsigned char型的变量GPFCON,并绑定变量所在的内存地址为5000。
下面是在icc编译环境下写的C语言代码:
/*just for test*/
#define GPFCON (*(volatile unsigned int*)5000)
void main()
{
GPFCON = 0x01 ;
}
查看列表文件的结果为:
0000 ; #define GPFCON (*(volatile unsigned int*)5000)
0000 ;
0000 ; void main()
0000 ; {
0000 .dbline 6
0000 ; GPFCON = 0x01 ;
0000 81E0 ldi R24,1
0002 90E0 ldi R25,0
0004 90938913 sts 5000+1,R25
0008 80938813 sts 5000,R24
000C .dbline -2
000C L1:
000C .dbline 0 ; func end
000C 0895 ret
000E .dbend
000E ; }
很明显看到汇编程序将0x01放入了地址为5000和5001的两个连续的地址空间里。实验证明这种定义固定地址变量的方法是有效的。
#define GPFCON (*(volatile unsigned char*)5000)
验证结果为:汇编程序将0x01放入了地址为5000的一个字节地址空间里。
下面我们看一段uboot源码中的一段代码:
#define S3C2410_NAND_BASE 0x4E000000//寄存器基地址
static inline struct s3c2410_nand *s3c2410_get_base_nand(void)
{
return (struct s3c2410_nand *)S3C2410_NAND_BASE;
}
/* NAND FLASH (see S3C2410 manual chapter 6) */
struct s3c2410_nand {
u32 NFCONF;
u32 NFCMD;
u32 NFADDR;
u32 NFDATA;
u32 NFSTAT;
u32 NFECC;
};//寄存器相关
函数static inline struct s3c2410_nand *s3c2410_get_base_nand(void);的返回值类型为 struct s3c2410_nand *,这种类型可以描述为某种结构体的指针。
return (struct s3c2410_nand *)S3C2410_NAND_BASE;
告诉我们函数return的类型是一个指针地址为0x4E000000的指向 struct s3c2410_nand结构体的指针变量。从语法角度,将S3C2410_NAND_BASE强制转换为一个指针类型(一般为四个字节大小),指向一个连续六个U32类型的地址空间。
所以这个函数的作用可以理解为从某基地址申请一段连续内存地址空间。