1 前言
编译过程中,指定数据绝对存储地址在实际项目中会经常使用到或者必须用到,这样使得项目实现某些功能可以非常灵活,常用的场景有:
2 实现方法
指定数据绝对存储地址,实现方法与编译器相关,不同编译器实现方式不一样;常用的有Keil、IAR、Gcc,Keil AC5和AC6版本编译器实现方法也不同。
例如,定义一个u32变量data,存储起始地址在0x20010000上,不同编译器下实现如下。
uint32_t data __attribute__((at(0x20010000)));
uint32_t data _attribute__ ((section(".ARM.__at_0x20010000")));
#pragma location = 0x20010000
__no_init uint32_t data;
__root __no_init uint32_t data @0x20010000
__root:强制函数或者变量不被编译器优化;函数或者变量没有被任何函数引用的情况下,编译器可能会将其优化掉。
__no_init 强制不执行内存初始化动作;正常情况下,应用程序启动时,IAR将全部全局和静态变量初始化为0,__no_init声明的变量不会执行初始化。
“@”是IAR中的地址操作符,通过“@”或“#program location ”指令来把全局变量/静态变量/代码Text 存放到绝对存储地址空间上;即是“#pragma location = address” 等价于 “@ address”
3 例子
以STM32为例,指定flash地址空间存储固件信息。
typedef struct __attribute__ ((packed)) project_info
{
char name[20];
char id;
char ver_major;
char ver_minor;
char ver_revision;
char build_date[12];
char build_time[10];
} project_info_t;
#define PROJECT_INFO_ADDR 0x08024000U
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
#if defined ( __CC_ARM )
#define __AT(__ADDR) __attribute__ ((at(__ADDR), used))
#elif defined ( __ARMCC_VERSION )
#define __AT(__ADDR) __attribute__ ((section(".ARM.__at_" #__ADDR)))
#endif
#define AT_ADDR(__ADDR) __AT(__ADDR)
const project_info_t project_info AT_ADDR(PROJECT_INFO_ADDR) =
#elif defined(__ICCARM__)
#define AT_ADDR(__ADDR) __AT(__ADDR)
#pragma location = PROJECT_INFO_ADDR
__root const project_info_t project_info @PROJECT_INFO_ADDR =
#else
#error Not select compiler.
#endif
{
.name = "xxx",
.id = 0xAA,
.ver_major = 1,
.ver_minor = 0,
.ver_revision = 0,
.build_date = __DATE__,
.build_time = __TIME__,
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)