C语言定义数组起始地址对齐方式(IAR C99 Kinetis K66)


前言##

前几天,主管找我问关于定义变量起始地址对齐方式的问题。下面介绍一下问题:上位机生成了一个参数数组 char para[36541] = {...} ;数组比较大,已经内建好了结构体,只要按照指针指到头部地址即可正常读取出来,但是由于处理器读取int 或者 float 数据类型比较要求数据地址是四字节对齐的,而我们这个数组存放在内存中是以两个字节对齐的,这就导致了CPU无法读取数据并死机在了读取float数据类型处;

主管提出,能否直接指定该数组的存在于内存中的起始地址?我一想,确实是,只要头地址对了那就啥问题也没有了。

主管又补充了一句,他测试过了 #pragma pack(4) 这种编译命令,实际效果是没效果,于是我上网查了下,这个命令确实是数据对齐的命令,但是只是对于结构体内部。对于数组头地址,我开始觉得有点挑战了;

而且方法要简单,不要影响程序的运行效率问题;

问题尝试

今天在处理上次开会中提到的内存分配的问题,改着改着忽然就灵光一闪,觉得这个问题应该是可以解决的:

我拿出了自己使用的比较利索的C语言工具->IAR workbench for ARM; 测试平台当然还是最熟悉的Kinetis 系列的 K66 啦!

先定义以下变量:测试看看存放于内存中的位置,代码如下:

char aa[2] = {1,2};

查看地址的方式有两个:

  • 通过IAR编译器生成的MAP文件进行查找
  • 就是通过IAR DEBUG工具中的 watch工具进行查看

而我这种偷懒王必须采用第二种方式啊,多么直观,哈哈哈哈;
如下是我通过IAR Debug watch中查看到的相关信息:

Expression Value Location Type
aa <<a>array>"??" 0x1FFF0070 char[2]
bb <<a>array>"??" 0x1FFF0072 char[2]

可以看出上面aa存放地址是 0x1FFF0070 而bb的地址存放在0x1FFF0072地址上,bb的起始地址是一个2字节对齐的地址,并非四地址对齐的地址。

明确目标,向前进发

准备修改bb的首地址到一个四字节对齐的地址上,或者八字节对齐的地址上

目标明确过后就是尝试了,我首先尝试了下主管说过的

#pragma pack(x) ;

这类编译命令,不出意外,一点影响都没有;

直到今天,一个偶然中想到了是否可以使用IAR 链接时候使用的ICF文件(链接文件)进行处理;
好,说做就做:开始尝试,写了一个简单的链接代码测试一下:

//define block to place test  value 

define symbol m_data_start   = 0x1FFF0000;

define symbol m_data_end    = 0x1FFFFFFF;

define memory mem with size = 4G;    

define region test_region = mem:[from m_data_start to m_data_end];

define block  test_block with alignment = 4 {section .test};

place in test_region {block test_block};

这里定义了一下链接文件(*.icf)将 .test这个段放在了0x00000410 ~ 0x1FFFFFFF这个区段中以四字节对齐的地址上;

然后回去在变量定义中修改成如下代码:

char aa[2] = {1,2};

#pragma location = ".test"

char bb[2] = {3,4};

这里意思是数组aa依然按照编译器缺省规则编译,而数组bb则存放到 .test段中;

究竟是否成功呢?打开IAR Debug watch:惊喜啊,真的是啊:

以下是4字节对齐aa、bb首地址

Expression Value Location Type
aa <<a>array>"??" 0x1FFF0070 char[2]
bb <<a>array>"??" 0x1FFF04A8 char[2]

好家伙,真的是成了四字节对齐的地址了(0x1FFF04A8 % 4 == 0);为了确保是这个样子,多实验几下看看,看看是不是对的,于是将链接中关于对齐部分代码修改如下:

define block  test_block with alignment = 8 {section .test};

再使用IAR debug watch查看一下地址:

以下是8字节对齐的aa、bb首地址

Expression Value Location Type
aa <<a>array>"??" 0x1FFF0070 char[2]
bb <<a>array>"??" 0x1FFF04A8 char[2]

地址竟然和上面一样,使用计算器计算一下发现(0x1FFF04A8 % 8 == 0),确定是8字节对齐的。

我心里还是有点疑虑,看看16、32字节对齐会有啥样子?

以下是16字节对齐的aa、bb首地址

Expression Value Location Type
aa <<a>array>"??" 0x1FFF0070 char[2]
bb <<a>array>"??" 0x1FFF04B0 char[2]

新地址计算一下(0x1FFF04B0 % 16 == 0 )

以下是32字节对齐的aa、bb首地址

Expression Value Location Type
aa <<a>array>"??" 0x1FFF0070 char[2]
bb <<a>array>"??" 0x1FFF04C0 char[2]

新地址计算一下(0x1FFF04C0 % 32 == 0 )

结论

通过这一系列的尝试。发现ICF文件(链接文件)中的块alignment关键字可以使块的首地址按照2^x(2,4,8,16,32...)方式对齐;而我们定义这一个块就存放一个变量,那么这个变量的首地址的对齐方式就是一个可控的值。

展望

由于项目中使用的参数文件是上位机生成的一个数组,按道理这个参数是不需要被被修改的,本着提高CPU的效率考虑(CPU复位时候程序初始化需要搬运.data段到RAM中),我们可以定义到该变量到CODE中成为一个常量表,可以提高系统启动的速率;

以下为改进的icf文件关键代码:

//define block to place test  value 

define symbol m_text_start    = 0x00000410;

define symbol m_text_end     = 0x001FFFFF;

define memory mem with size = 4G;    

define region test_region = mem:[from m_text_start to m_text_end];

define block  test_block with alignment = 4 {section .test};

place in test_region {block test_block};

以下为改进了的测试数组定义

char aa[2] = {1,2};

#pragma location = ".test"

const char bb[2] = {3,4};

以下是通过IAR Debug Watch 所观察到的变量数据:

Expression Value Location Type
aa <<a>array>"??" 0x1FFF0070 char[2]
bb <<a>array>"??" 0x00013748 char[2]

可以发现该地址存在于flash空间中,仍然是一个4字节对齐的地址,成功,哈哈哈哈,这次任务完成;

寄语

楼主文笔特别差,很多时候表词不达意,或者用词错误,亦或者对于东西理解不深入等等。但是希望我的分享能够解决你的实际问题。也希望你阅读过程中发现对文章的技术或者其他方法有怀疑的提出反馈,一起讨论学习,一起进步。谢谢阅读。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容

  • 开篇废话 这几天一直忙着积累知识,还没有来得及总结呢,前些日子讲述了一种在C语言环境中设置数组的对齐的方式,但是那...
    爪爪熊阅读 2,617评论 2 5
  • 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; ...
    朱森阅读 3,419评论 3 44
  • 昨天被其他用户提醒《婆媳之间的那些事》被锁定,看了半天不知是怎么回事?心里还总在嘀咕是不是哪个用户看上自己没写完的...
    蔷薇花儿落地开阅读 133评论 2 2
  • 小时候,很多人大概都写过这样的作文。长大了,我要成为什么样的人。 有人说,我要成为科学家...老梗,有人说我要当明...
    Connection_u_i阅读 531评论 0 0
  • “这次可以给我照片了吗?”嘟嘟,糖糖的手机里忽然传来一条微信。糖糖一头乌黑的长发如瀑布般披在肩上,一双大眼睛闪闪发...
    一滴露水阅读 421评论 9 5