您的位置 首页 新能源

bootloader和RO,RW,ZI在ARMC语言中

Bootloader即引导加载程序,是系统加电后运行的第一段软件代码。简单的说它们都是bootloader,所完成的任务也大同小异。熟悉x86体系结构的…

Bootloader即引导加载程序,是体系加电后运转的榜首段软件代码。简略的说它们都是bootloader,所完结的使命也迥然不同。

了解x86体系结构的朋友必定知道,x86渠道上bootloader是由BIOS和坐落硬盘MBR中的OS Bootloader(比方Lilo和Grub)组成的。BIOS完结硬件的检测和资源的分配后,将硬盘MBR中的bootloader读到体系RAM中,之后此bootloader就会开端进行主导,将内核搬到内存中以及进行一些必要的初始化作业,之后跳到内核的进口地址来履行,这样内核就开端发动,也便是体系就发动起来了。
这儿不得不刺进一个论题,经过上面的介绍,仔细的朋友就会发生一个疑问:为什么要有bootloader?已然bootloader仅仅作硬件的初始化并将内核引导起来,那为什么不直接将这段代码加到内核中,直接发动内核就完结一切的作业?实践上要将bootloader与内核整合在一起是彻底能够做到的,可是假设这样作的話,内核就会失掉他的通用性和灵活性,并且将bootloader与内核分开会更有利于开发和办理,将发动进程中与渠道硬件相关的代码集组成bootloader,内核就能够会集处理那些渠道通用的部分了(当然实践上并没有这么严厉的区分,内核中仍是会有一些渠道相关的代码,不过现已算是比较通用的了)。
=============================================================================================================================================================================
一个ARM程序包括3部分:RORWZI
RO是程序中的指令和常量;RO便是readonly,
RW是程序中的已初始化变量; RW便是read/write,
(2) ARM映像文件的组成
所谓ARM映像文件便是指烧录到ROM中的bin文件,也成为image文件。以下用Image文件来称号它。Image文件包括了RO和RW数据。之所以Image文件不包括ZI数据,是由于ZI数据都是0,没必要包括,只需程序运转之前将ZI数据地点的区域一概清零即可。包括进去反而糟蹋存储空间。
Q:为什么Image中有必要包括RO和RW?
A:由于RO中的指令和常量以及RW中初始化过的变量是不能像ZI那样“惹是生非”的。
实践上,ROM中的指令至少应该有这样的功用:
1. 将RW从ROM中搬到RAM中,由于RW是变量,变量不能存在ROM中。
2. 将ZI地点的RAM区域悉数清零,由于ZI区域并不在Image中,所以需求程序依据编译器给出的ZI地址及巨细来将相应得RAM区域清零。ZI中也是变量,同理:变量不能存在ROM中.在程序运转的开端阶段,RO中的指令完结了这两项作业后C程序才干正常拜访变量。不然只能运转不含变量的代码。
下面我将给出几个比如,最直观的来阐明RO,RW,ZI在C中是什么意思。
1; RO
看下面两段程序,他们之间差了一条句子,这条句子便是声明一个字符常量。因而依照咱们之前说的,他们之间应该只会在RO数据中相差一个字节(字符常量为1字节)。
Prog1:
#include
void main(void)
{
;
}

Prog2:
#include
const char a = 5;
void main(void)
{
;
}
Prog1编译出来后的信息如下:
================================================================================
Code RO Data RW Data ZI Data Debug
948 60 0 96 0 Grand Totals
================================================================================
Total RO Size(Code + RO Data) 1008 ( 0.98kB)
Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)
Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)
================================================================================
Prog2编译出来后的信息如下:
================================================================================
Code RO Data RW Data ZI Data Debug
948 61 0 96 0 Grand Totals
================================================================================
Total RO Size(Code + RO Data) 1009 ( 0.99kB)
Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)
Total ROM Size(Code + RO Data + RW Data) 1009 ( 0.99kB)
================================================================================
以上两个程序编译出来后的信息能够看出:
Prog1和Prog2的RO包括了Code和RO Data两类数据。他们的仅有差异便是Prog2的RO Data比Prog1多了1个字节。这正和之前的估测共同。假设添加的是一条指令而不是一个常量,则成果应该是Code数据巨细有不同。
2; RW
相同再看两个程序,他们之间只相差一个“已初始化的变量”,依照之前所讲的,已初始化的变量应该是算在RW中的,所以两个程序之间应该是RW巨细有差异。
Prog3:
#include
void main(void)
{
;
}
Prog4:
#include
char a = 5;
void main(void)
{
;
}
Prog3编译出来后的信息如下:
================================================================================
Code RO Data RW Data ZI Data Debug
948 60 0 96 0 Grand Totals
================================================================================
Total RO Size(Code + RO Data) 1008 ( 0.98kB)
Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)
Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)
================================================================================
Prog4编译出来后的信息如下:
================================================================================
Code RO Data RW Data ZI Data Debug
948 60 1 96 0 Grand Totals
================================================================================
Total RO Size(Code + RO Data) 1008 ( 0.98kB)
Total RW Size(RW Data + ZI Data) 97 ( 0.09kB)
Total ROM Size(Code + RO Data + RW Data) 1009 ( 0.99kB)
================================================================================
能够看出Prog3和Prog4之间的确只要RW Data之间相差了1个字节,这个字节正是被初始化过的一个字符型变量“a”所引起的。
再看两个程序,他们之间的不同是一个未初始化的变量“a”,从之前的了解中,应该能够估测,这两个程序之间应该只要ZI巨细有不同。
Prog3:
#include
void main(void)
{
;
}
Prog4:
#include
char a;
void main(void)
{
;
}
Prog3编译出来后的信息如下:
================================================================================
Code RO Data RW Data ZI Data Debug
948 60 0 96 0 Grand Totals
================================================================================
Total RO Size(Code + RO Data) 1008 ( 0.98kB)
Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)
Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)
================================================================================
Prog4编译出来后的信息如下:
================================================================================
Code RO Data RW Data ZI Data Debug
948 60 0 97 0 Grand Totals
================================================================================
Total RO Size(Code + RO Data) 1008 ( 0.98kB)
Total RW Size(RW Data + ZI Data) 97 ( 0.09kB)
Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)
================================================================================
编译的成果彻底符合估测,只要ZI数据相差了1个字节。这个字节正是未初始化的一个字符型变量“a”所引起的。
留意:假设一个变量被初始化为0,则该变量的处理办法与未初始化华变量相同放在ZI区域。
即:ARM C程序中,一切的未初始化变量都会被主动初始化为0。
总结: 1; C中的指令以及常量被编译后是RO类型数据。
2; C中的未被初始化或初始化为0的变量编译后是ZI类型数据。
3; C中的已被初始化成非0值的变量编译后市RW类型数据。
RAM主要指:PSRAM,SDRAM,SRAM,DDRAM
(5) Image$$??$$Limit 的意义
=0x0c100000+Tatal RO size+1
= 0x0c200000+0x37(4的倍数,0到55,共56个单元)


vivi是mizi开发的用于s3c241x/s3c244x 的linux bootloader,友善之臂移植了USB 下载功用后就成了现在看到的supervivi;u-boot是一个广泛用于ARM渠道的bootloader, 现在也支撑s3c241x/s3c244x,能够用来发动Linux;Eboot是WinCE渠道下的bootloader。uboot便是经过usb来下载os image文件的bootloader; eboot便是经过ethernet下载os image的bootloader。

嵌入式渠道上就跟x86不相同了,可是很相似,并且由于不同的渠道架构自身的特色,每种渠道对应的bootloader做得工作会有所不同,相对x86渠道,一般不会有bios(可是这些都不是必定的,有一些渠道也会有内嵌相似bios的发动程序),整个体系的引导加载都由寄存在flash,rom等存储设备特定方位的bootloader来完结。如arm渠道中的2410,2440,bootloader存在在flash中的0x0的当地,板子加电后,体系会将bootloader的最前面的4k代码经过硬件逻辑主动的装载到SRAM中,之后从SRAM中的0开端履行,在这4k的程序中会完结根本的硬件的初始化,将完好的bootloader搬到内存中,并跳转到ram中的bootloader来进行持续履行。

回到之前所说的,bootloader发动起来之后,一般会有两种操作形式:

发动加载形式便是一上电,bootloader进行相关的初始化之后就立刻把内核发动起来,留意要害的当地在整个进程中没有用户的参加,这种其实也便是bootloader的默许处理,一般的产品设计ok进行最终的发布时,就会处于此种状况。

下载模这种形式,咱们必定十分了解,便是咱们在进行开发的时分所在的环境,咱们常常运用的tftp, erase, cp.b等指令将相关的bin,img文件烧到板子上,这种情况下其实便是处于bootloader的履行环境下,所以必定意义来说,大多的bootloader其实便是一个嵌入式操作体系,仅仅它的功用不强,不像linux的结构那么杂乱,并且也不会支撑多进程多线程处理。

bootloader品种和分类

这儿的分类实践上是依据上面的bootloader的操作形式来进行区分的,依据一个体系是否支撑上面的下载形式咱们这儿将bootloader区分为bootloader和monitor(这不是我区分的,恩,是从他人的文章中引述过来的,不过我觉得他说的很有道理),这儿”bootloader”是指仅仅引导设备与履行主程序的固件,而”monitor”是指不只具有bootloader功用的,还能够进入下载形式的固件。

(1)、ARM程序的组成

此处所说的“ARM程序”是指在ARM体系中正在履行的程序,而非保存在ROM中的bin映像(image)文件,这一点清留意差异。

ZI是程序中的未初始化的变量;ZI便是zero;

(3)ARM程序的履行进程

从以上两点能够知道,烧录到ROM中的image文件与实践运转时的ARM程序之间并不是彻底相同的。因而就有必要了解ARM程序是怎样从ROM中的image抵达实践运转状况的。


3; ZI

(4) ROM主要指:NAND Flash,Nor Flash

关于刚学习ARM的人来说,假设剖析它的发动代码,往往不明白下面几个变量的意义:|Image$$RO$$Limit|、|Image$$RW$$Base|、|Image$$ZI$$Base|。

当把程序编写好今后,就要进行编译和链接了,在ADS1.2中挑选MAKE按钮,会呈现一个Errors and Warnings的对话框,在该栏中显现编译和链接的成果,假设没有过错,在文件的最终应该能看到Image component sizes,后边紧跟的依次是Code,RO Data ,RW Data ,ZI Data ,Debug 各个项目的字节数,最终会有他们的一个统计数据:

Code 163632 ,RO Data 20939 ,RW Data 53 ,ZI Data 17028

Tatal RO size (Code+ RO Data) 184571 (180.25kB)

Tatal RW size(RW Data+ ZI Data) 17081(16.68 kB)

Tatal ROM size(Code+ RO Data+ RW Data) 184624(180.30 kB)

后边的字节数是依据用户不同的程序而来的,下面就以上面的数据为例来介绍那几个变量的核算。

在ADS的Debug Settings中有一栏是Linker/ARM Linker,在output选项中有一个RO base选项,

假设RO base设置为0x0c100000,后边的RW base 设置为0x0c200000,然后在Options选项中有Image entry point ,是一个初始程序的进口地址,设置为0x0c100000 。

有了上面这些信息咱们就能够彻底知道这几个变量是怎样来的了:

|Image$$RO$$Base| = Image entry point =RO base =0x0c100000 ;表明程序代码寄存的开始地址

|Image$$RO$$Limit|=程序代码开始地址+代码长度+1

= 0x0c100000 + 184571 + 1 = 0x0c100000 +0x2D0FB + 1

= 0x0c12d0fc

|Image$$RW$$Base| = 0x0c200000=RW base 地址指定

|Image$$RW$$Limit| =|Image$$RW$$Base|+ RW Data 53

=0x0c200037

|Image$$ZI$$Base| = |Image$$RW$$Limit| + 1 =0x0c200038

|Image$$ZI$$Limit| = |Image$$ZI$$Base| + ZI Data 17028

=0x0c200038 + 0x4284

=0x0c2042bc

也能够由此核算:

|Image$$ZI$$Limit| = |Image$$RW$$Base| +TatalRWsize(RWData+ZIData) 17081

=0x0c200000+0x42b9+3(要满意4的倍数)

=0x0c2042bc

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qiche/xinnengyuan/275606.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部