**定义变量到固定地址的方法 **
在嵌入式编程中,经常需要定义一些特殊的变量(如:控制类寄存器,或者为了某个目的,要“强霸“某处内存),因此,熟练掌握将变量定义到固定的地址,是嵌入式编程的基本技能之一。
一、 通用方法1:
通用方法是指任何编译器均支持,支持任意数据类型,但不支持数组,示例:
#define VarA (*(uint32
)0x12345678) // uint32类型变量VarA强行分配在内存地址0x12345678处
// 如果在此地址再定义一个变量,就是:union
#define StructVarB (
(volatile struct MyStruct *)0x12345678)
volatile:指示编译器此变量的值不固定,每次必须重读,不能采用先前读过的值(编译优化的结果)
变通方法:
将数组放到一个 struct 里,也可以将相关的连续分配内存的变量按顺充打包在一起
typedef struct
{
uint16 arrA[64];
} NewDataType;
#define VarA (*(volatile NewDataType *)0x12345678)
唯一的缺点就是,数组的访问只能这样: VarA.arrA[x]
如果你还想象常规那样使用,再:
#define arrB[a] VarA.arrA[(a)]
二、 通用方法2:指针法
为了将数组定义到一个固定的地址,可采用指针定义,数组的管理就有能再使用下标了,只能采用指针管理;
#define parrDataStart_Addr ((uint32
) 0x12345678)
数组元素的访问改为指针管理:
arrData[x] =
(parrDataStart_Addr + x )
或者:
#define arrData[a] (
(parrDataStart_Addr + (a) ))
注意:使用前要简单测试一下,看 +1 是否加的是 相关数据类型的 sizeof , 比如,对于 uint32
, +1 ,实际的地址,应:+4 ,以免留下Bug
三、 SECTION 定义法:
将你要定义的变量分配一个特定的内存分段标识,例:
#pragma DATA_SECTION( arrVarA,".VarA_RAM");
uint32 volatile arrVarA[256];
与通用方法不同,此方法还需在内存分配的 CMD(或 MAP) 文件中,添加内容:
page 1:
VarA_RAM_Addr : o = 0x12345678 L = 0x0400
SECTION:
.VarA_RAM > VarA_RAM_Addr page=1
注:此法不同的平台,原理相同,但语法规范有所区别,文件不能直接通用,需修改,所以,可移值性不如通用方法
同理:
#pragma CODE_SECTION( MyFun,”.Fun_RAM”);
可将一段程序定义放到指定的内存中运行。
四、 其它定义法:
这些方法,不同的平台,写法会有所区别,或者根本就不支持,需自行了解清楚之后再使用,以免留下不可预知的Bug
int VarA@0x12345678;
#include <abcacc.h>
long arrA[256] __at (0x12345678)
char VarA
attribute
((at(0x12345678))