c 语言嵌入式之:内存操作

                 (嵌入式C C++语言精华 笔记3)

数据指针

      在嵌入式系统的实际调试中,多借助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;

(p++; p == 0xF000FF01;)

 意义:在绝对地址0xF0000+0xFF00(80186使用16位段地址和16位偏移地址)写入11。

 

int *p = (int *)0xF000FF00;

p++ ----->  p = p + sizeof(int);

p--   ----->  p = p -  sizeof(int);

 

注意:CPU以字节为单位编址,而C语言指针以指向的数据类型长度作自增和自减。

 

函数指针

      理解三个问题:

(1) C语言中函数名直接对应于函数生成的指令代码在内存中的地址,因此函数名可以直接赋给指向函数的指针。

(2)调用函数实际上等同于“调转指令+参数传递处理+回归位置入栈”,本质上最核心的操作是将函数生成的目标代码的首

        地址赋给CPU的PC寄存器。

(3)因为函数调用的本质是跳转到某一个地址单元的code去执行,所以可以“调用”一个根本不存在的函数实体。

 

《微型计算机原理》中讲到,186CPU启动后跳转至绝对地址0xFFFF0(对应 C语言指针是 0xF000FFF0, 0xF000为

段地址, 0xFFF0为段内偏移)执行,如例:

 

typedef void (*lpFunction) ();/*定义一个无参数,无返回类型的函数指针类型 */

/*定义一个函数指针 ,指向CPU启动后所执行第一条指令的位置*/

lpFunction lpReset = (lpFunction)0xF000FFF0;

lpReset(); /*调用函数*/

上述代码实现了“软重启”的作用。

 

 

数组 VS.动态申请

    嵌入式系统中任何不经意的内存泄露都会很快导致系统的崩溃。所以一定要保证malloc和free成对出现(原则:谁申请,

就由谁释放。否则会导致代码的耦合度增大)。

内存申请原则:

(1)尽可能的选用数组,数组不能越界访问。

(2)如果使用动态申请,则申请后一定要判断是否申请成功了,并且malloc和free应成对出现。

(值结果参数,值参数)

 

关键字 const

   const意味着只读。

const  int a;

int  const a;

const int *a;

int * const a;

int const * a  const;

在编译阶段需要的常数只能以#define 宏定义!

故在c语言中如下程序是非法的:

   const int SIZE = 10;

   char a[SIZE]; /*便宜阶段不能用到变量*/

 

关键字 volatile 防止编译器优化

volatile 变量可能用于如下几种情况:

(1)并行设备的硬件寄存器(如:状态寄存器)

(2)一个中断服务子程序中会访问到的非自动变量(也就是全局变量)

(3)多线程应用中被几个任务共享的变量。

 

CPU字长与存储器位宽不一致的处理

 80186的字长为16,而NVRAM的位宽为8,在这种情况下,我们需要为NVRAM提供读写字节,字的接口,如下:

 

typedef  usigned  char  BYTE;

typedef  usigned 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 基地址的偏移

    byData, 欲写入的字

*/

 

extern void WriteWordNVRAM (WORD  wOffset, WORD  wData)

{

  .......

}

 

_______                     _________

cpu        | A3--------A2 |                 |

80186    | A2-------A1 |                  |

              | A1-------A0 |   NVRAM    |

              | A0              |                  |

_______|                   |_________|

16位80186与8位NVRAM之间互连只能以地址线A1对其A0,CPU本身的A0与NVRAM不连接,因此,NVRAM的地址只能

是偶数地址,故每次以0x10为单位前进!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值