~
全部博文(18)
分类: 嵌入式
2010-07-27 21:03:15
作者:宋宝华
数据指针
在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C++以外的其它编程语言基本没有直接访问绝对地址的能力。在嵌入式系统的实际调试中,多借助C语言指针所具有的对绝对地址单元内容的读写能力。以指针直接操作内存多发生在如下几种情况:
(1) 某I/O芯片被定位在CPU的存储空间而非I/O空间,而且寄存器对应于某特定地址;
(2) 两个CPU之间以双端口RAM通信,CPU需要在双端口RAM的特定单元(称为mail box)书写内容以在对方CPU产生中断;
(3) 读取在ROM或FLASH的特定单元所烧录的汉字和英文字模。
譬如:
unsigned char *p = (unsigned char *)0xF000FF00; *p=11; |
int *p = (int *)0xF000FF00; |
long int *p = (long int *)0xF000FF00; |
typedef void (*lpFunction) ( ); /* 定义一个无参数、无返回类型的 */ /* 函数指针类型 */ lpFunction lpReset = (lpFunction)0xF000FFF0; /* 定义一个函数指针,指向*/ /* CPU启动后所执行第一条指令的位置 */ lpReset(); /* 调用函数 */ |
char * function(void) { char *p; p = (char *)malloc(…); if(p==NULL) …; … /* 一系列针对p的操作 */ return p; } |
char *q = function(); … free(q); |
char *p=malloc(…); if(p==NULL) …; function(p); … free(p); p=NULL; |
void function(char *p) { … /* 一系列针对p的操作 */ } |
基本上,动态申请内存方式可以用较大的数组替换。对于编程新手,笔者推荐你尽量采用数组!嵌入式系统可以以博大的胸襟接收瑕疵,而无法"海纳"错误。毕竟,以最笨的方式苦练神功的郭靖胜过机智聪明却范政治错误走反革命道路的杨康。
给出原则:
(1)尽可能的选用数组,数组不能越界访问(真理越过一步就是谬误,数组越过界限就光荣地成全了一个混乱的嵌入式系统);
(2)如果使用动态申请,则申请后一定要判断是否申请成功了,并且malloc和free应成对出现!
关键字const
const意味着"只读"。区别如下代码的功能非常重要,也是老生长叹,如果你还不知道它们的区别,而且已经在程序界摸爬滚打多年,那只能说这是一个悲哀:
const int a; int const a; const int *a; int * const a; int const * a const; |
const int SIZE = 10; char a[SIZE]; /* 非法:编译阶段不能用到变量 */ |
int a,b,c; a = inWord(0x100); /*读取I/O空间0x100端口的内容存入a变量*/ b = a; a = inWord (0x100); /*再次读取I/O空间0x100端口的内容存入a变量*/ c = a; |
int a,b,c; a = inWord(0x100); /*读取I/O空间0x100端口的内容存入a变量*/ b = a; c = a; |
volatile int a; |
typedef unsigned char BYTE; typedef unsigned int WORD; /* 函数功能:读NVRAM中字节 * 参数:wOffset,读取位置相对NVRAM基地址的偏移 * 返回:读取到的字节值 */ extern BYTE ReadByteNVRAM(WORD wOffset) { LPBYTE lpAddr = (BYTE*)(NVRAM + wOffset * 2); /* 为什么偏移要×2? */ return *lpAddr; } /* 函数功能:读NVRAM中字 * 参数:wOffset,读取位置相对NVRAM基地址的偏移 * 返回:读取到的字 */ extern WORD ReadWordNVRAM(WORD wOffset) { WORD wTmp = 0; LPBYTE lpAddr; /* 读取高位字节 */ lpAddr = (BYTE*)(NVRAM + wOffset * 2); /* 为什么偏移要×2? */ wTmp += (*lpAddr)*256; /* 读取低位字节 */ lpAddr = (BYTE*)(NVRAM + (wOffset +1) * 2); /* 为什么偏移要×2? */ wTmp += *lpAddr; return wTmp; } /* 函数功能:向NVRAM中写一个字节 *参数:wOffset,写入位置相对NVRAM基地址的偏移 * byData,欲写入的字节 */ extern void WriteByteNVRAM(WORD wOffset, BYTE byData) { … } /* 函数功能:向NVRAM中写一个字 */ *参数:wOffset,写入位置相对NVRAM基地址的偏移 * wData,欲写入的字 */ extern void WriteWordNVRAM(WORD wOffset, WORD wData) { … } |
图1 CPU与NVRAM地址线连接 |