查看: 2407|回复: 0

[经验] 浅谈ARM处理器内存分配

[复制链接]

该用户从未签到

发表于 2020-11-24 18:05:12 | 显示全部楼层 |阅读模式
分享到:
ARM的体系结构有很多很多介绍的地方,从其7种模式到CPSR状态寄存器,这些都是属于最底层的硬件直接相关的ARM属性,再向上一点,考虑一下在ARM上运行的嵌入式应用,一般称在ARM上直接运行的嵌入式应用为Image就是直接烧进flash运行的可执行文件,这种可执行文件是由IAR,ADS,ARM-EABI-GCC等编译器经过编译所直接生成的。由于没有操作系统的支持,这种镜像文件是需要自己管理底层存储空间的分配的。这里我主要说一下关于Image镜像与ROM,RAM的关系。首先在ARM上电启动时Image是在ROM中的,这就有问题了,我们知道,程序是由指令与数据共同组成的,指令可以放在ROM中,但数据变量必须放在RAM中才能够运行啊,可ARM上电时RAM空间是清空的啊,这就产生一个问题,变量数据是怎么进到RAM中的,由谁来做的。介绍一下ARM程序中各种标志,在ARM中有CODE,READONLY DATA, READWRITE DATA, ZI,他们分别表示

CODE:ARM 指令,
READONLY DATA指只读数据,如const int tst = 1;
READWRITE DATA可读写数据,就是我们常说的变量,已经被初始的变量才是READWRITE DATA。如 int tst = 2;
ZI:Zero Init数据,就是不初始化,或者用0初始化的变量。
在IAR,ADS等开发工具中,其配置文件中需要为编译后的镜像指定各段所在的地址空间,由可读写属性上可以主要分为
READONLY 包括CODE,READONLY DATA
READWRITE 包括READWRITE DATA,ZI。
了解了这些基础知识后,回到最初的问题,ARM的Image就是由上面所说的各个段组成的,那在只读的ROM空间,如何将READWRITE的数据放入RAM中的那,在代码中我们并没有作这些事啊。其实,这部分工作是由Image自动进行的不需要认为干预,在启动时,Image自动将数据拷贝到RAM中,这里还要强调一下,拷贝的只是READWRITE变量,对ZI的变量,直接将所在内存段清0即可,无需拷贝。
在编写嵌入式程序过程中,需要重点将存储空间中各段位置考虑好,在进行Image的编译,Image起始地址必须是0x00,或者CPU指定的运行地址,重点是分配各个特殊状态的STACK空间,以及用于动态分配的HEAP空间。在IAR中有关于 initialize by copy/manule的指令,就是用来将RW数据段拷入RAM中的,这里一定要将RW拷入,否则会导致运行错误。

2
ARM映像文件的组成
所谓ARM映像文件就是指烧录到ROM中的bin文件,也称为image文件。以下用Image文件来称呼它。
Image文件包含了RO和RW数据。
之所以Image文件不包含ZI数据,是因为ZI数据都是0,没必要包含,只要程序运行之前将ZI数据所在的区域一律清零即可。包含进去反而浪费存储空间。

Q:为什么Image中必须包含RO和RW?
A:因为RO中的指令和常量以及RW中初始化过的变量是不能像ZI那样“无中生有”的。

ARM程序的执行过程
从以上两点可以知道,烧录到ROM中的image文件与实际运行时的ARM程序之间并不是完全一样的。因此就有必要了解ARM程序是如何从ROM中的image到达实际运行状态的。
实际上,RO中的指令至少应该有这样的功能:
1. 将RW从ROM中搬到RAM中,因为RW是变量,变量不能存在ROM中。
2. 将ZI所在的RAM区域全部清零,因为ZI区域并不在Image中,所以需要程序根据编译器给出的ZI地址及大小来将相应得RAM区域清零。ZI中也是变量,同理:变量不能存在ROM中
在程序运行的最初阶段,RO中的指令完成了这两项工作后C程序才能正常访问变量。否则只能运行不含变量的代码。
说了上面的可能还是有些迷糊,RO,RW和ZI到底是什么,下面我将给出几个例子,最直观的来说明RO,RW,ZI在C中是什么意思。
1; RO
看下面两段程序,他们之间差了一条语句,这条语句就是声明一个字符常量。因此按照我们之前说的,他们之间应该只会在RO数据中相差一个字节(字符常量为1字节)。
  1. <div align="left">
  2. Prog1:</div><ul type="1" class="litype_1"><li>#i nclude <stdio.h></li><li>void main(void)</li><li>{</li><li>;</li><li>}</li><li>Prog2:</li><li>#i nclude <stdio.h></li><li>const char a = 5;</li><li>void main(void)</li><li>{</li><li>;</li><li>}</li></ul>
复制代码


复制代码
Prog1编译出来后的信息如下:
  1. <div align="left"></div>debug<li>948 60 0 96 0 Grand Totals</li><li>================================================================================</li><li>Total RO Size(Code + RO Data) 1008 ( 0.98kB)</li><li>Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)</li><li>Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)</li><li>================================================================================
  2. </li>
复制代码

复制代码
Prog2编译出来后的信息如下:
    1. <li>================================================================================</li><li>Code RO Data RW Data ZI Data Debug</li><li>948 61 0 96 0 Grand Totals</li><li>================================================================================</li><li>Total RO Size(Code + RO Data) 1009 ( 0.99kB)</li><li>Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)</li><li>Total ROM Size(Code + RO Data + RW Data) 1009 ( 0.99kB)</li><li>================================================================================</li>
    复制代码


复制代码
以上两个程序编译出来后的信息可以看出:
Prog1和Prog2的RO包含了Code和RO Data两类数据。他们的唯一区别就是Prog2的RO Data比Prog1多了1个字节。这正和之前的推测一致。
如果增加的是一条指令而不是一个常量,则结果应该是Code数据大小有差别。
2; RW
同样再看两个程序,他们之间只相差一个“已初始化的变量”,按照之前所讲的,已初始化的变量应该是算在RW中的,所以两个程序之间应该是RW大小有区别。
  1. <div align="left">Prog3:</div><ul type="1" class="litype_1"><li>#i nclude <stdio.h></li><li>void main(void)</li><li>{</li><li>;</li><li>}</li></ul>
复制代码


复制代码
    1. <div align="left">Prog4:</div><ul type="1" class="litype_1"><li>#i nclude <stdio.h></li><li>char a = 5;</li><li>void main(void)</li><li>{</li><li>;</li><li>}</li></ul>
    复制代码


复制代码
Prog3编译出来后的信息如下:
  1. <div align="left"></div><ul type="1" class="litype_1"><li>================================================================================</li><li>Code RO Data RW Data ZI Data Debug</li><li>948 60 0 96 0 Grand Totals</li><li>================================================================================</li><li>Total RO Size(Code + RO Data) 1008 ( 0.98kB)</li><li>Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)</li><li>Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)</li><li>================================================================================</li></ul>
复制代码


复制代码
Prog4编译出来后的信息如下:
  1. <div align="left"></div><ul type="1" class="litype_1"><li>================================================================================</li><li>Code RO Data RW Data ZI Data Debug</li><li>948 60 1 96 0 Grand Totals</li><li>================================================================================</li><li>Total RO Size(Code + RO Data) 1008 ( 0.98kB)</li><li>Total RW Size(RW Data + ZI Data) 97 ( 0.09kB)</li><li>Total ROM Size(Code + RO Data + RW Data) 1009 ( 0.99kB)</li><li>================================================================================</li></ul>
复制代码


复制代码
可以看出Prog3和Prog4之间确实只有RW Data之间相差了1个字节,这个字节正是被初始化过的一个字符型变量“a”所引起的。
3; ZI
再看两个程序,他们之间的差别是一个未初始化的变量“a”,从之前的了解中,应该可以推测,这两个程序之间应该只有ZI大小有差别。
  1. <div align="left">Prog3:</div><ul type="1" class="litype_1"><li>#i nclude <stdio.h></li><li>void main(void)</li><li>{</li><li>;</li><li>}
  2. </li></ul>
复制代码

复制代码
    1. <div align="left">Prog4:</div><ul type="1" class="litype_1"><li>#i nclude <stdio.h></li><li>char a;</li><li>void main(void)</li><li>{</li><li>;</li><li>}</li></ul>
    复制代码


复制代码
Prog3编译出来后的信息如下:
  1. <div align="left"></div><ul type="1" class="litype_1"><li>================================================================================</li><li>Code RO Data RW Data ZI Data Debug</li><li>948 60 0 96 0 Grand Totals</li><li>================================================================================</li><li>Total RO Size(Code + RO Data) 1008 ( 0.98kB)</li><li>Total RW Size(RW Data + ZI Data)96 ( 0.09kB)</li><li>Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)</li><li>================================================================================</li></ul>
复制代码


复制代码
Prog4编译出来后的信息如下:
  1. <div align="left"></div><ul type="1" class="litype_1"><li>================================================================================</li><li>Code RO Data RW Data ZI Data Debug</li><li>948 60 0 97 0 Grand Totals</li><li>================================================================================</li><li>Total RO Size(Code + RO Data) 1008 ( 0.98kB)</li><li>Total RW Size(RW Data + ZI Data) 97 ( 0.09kB)</li><li>Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)</li><li>================================================================================</li></ul>
复制代码


复制代码
编译的结果完全符合推测,只有ZI数据相差了1个字节。这个字节正是未初始化的一个字符型变量“a”所引起的。
注意:如果一个变量被初始化为0,则该变量的处理方法与未初始化华变量一样放在ZI区域。
即:ARM C程序中,所有的未初始化变量都会被自动初始化为0。


回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /4 下一条



手机版|小黑屋|与非网

GMT+8, 2024-12-18 23:55 , Processed in 0.113710 second(s), 15 queries , MemCache On.

ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

苏公网安备 32059002001037号

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.