关于2440init.s之一(转载)


2440的初始化程序,也可以说是bootloader中的精华部分,承载着程序执行的第一条指令
的重要任务,所有得程序要想执行,那么首先必须过Init.s这一关啊。

那么Init究竟做了些什么呢,咳,这的确是一个头大的问题,起初真的是一头雾水啊

首先,定义了入口地址,一般处理器上电以后,都会从存储器的0地址开始执行,好了,现
在就有第一个问题出现了,这个存储器的0地址是个什么概念;

要解决这个问题,首先必须弄清楚你的系统有哪些存储器。一般来说,不外乎rom和ram,
还有flash,flash是很重要的,因为我们的程序就放在那儿。可是我们知道,flash的物理
地址一般不会是从0开始啊,呵呵,的确是这么回事,那这个0到底是什么呢,很简单,偏
移量啊,就是flash的base+xx,这个xx就是0,^_^,就这么简单

接下来,出现第二个问题,程序从0地址执行,那么下一个要执行的代码是什么呢,他是通
过什么跳转到第二个代码呢?

这个问题的回答要针对具体的处理器了,一般代码的存放都是连续存放的,就是第一个地
址,第二个地址,代码占多大空间,那么第二个地址就是第一个地址+第一条指令占居的
空间
比如说我们现在使用的2440,它是32位宽的,就是说每条指令译码后,为一个32位的二进
制数,它的不同的位分别代表了这个指令要做什么。那么这样一条代码在存储器中就要占
据32位。那我们知道现在一般存储器都是按字节存放的,如此算来,一条指令要占据4个字
节,事实上也确实如此。

由此我们得知,假如说我们的第一条指令存放在0x00000000处,那么第二条指令就应该存
放在0x00000004处了。^_^一点都不假。并且,这里还要说明一点,由于它每条指令都是4
字节,也即一个字的宽度,同时arm在寻址的时候,是字对齐的,所以,arm的地址位的低
两位(如A1,A0)在到存储器中寻找的时候,是没有效的,因为存储器按字节存取,而一
条指令占4个字节,所以呢,处理器每次都是4个字节的拿或放,因而2^2=4,所以A1和A0的
变化,只会出现0x00000001,0x00000002,0x00000003这样的数,而这样的数在寻址的时
候,都是指向了0x00000000起始的四个字节,所以啊,即使出现这样的数,都会自动对齐
到0x00000000了,因而才有上面一说。如此,也应该能够明白,在我们读写ram的时候,地
址的结尾只能是0,4,8,c了啊,^_^

那么究竟这个第二个地址的读取是通过一种什么机制呢,那就是PC,也就是Program Coun
t,程序计数器,就是它,在复位或者上电时刻,指向了0地址,即PC=0x00000000,然后
,在指向第二条指令的时候,它做了这样一个运算,PC=PC+4,很简单吧;但是!,因为
2440是三级流水线结构,PC的值就一定小心啊,下面来讲讲为什么
三级流水线,故名思义,就是一个时刻做三件事情,对于2440来说,那就是取指,译码,
执行
取指 译码 执行。。。
   取指 译码 执行。。。
             取指 译码 执行。。。
那么问一个问题,PC究竟是指向取指呢,译码呢,还是执行,^_^,对了,取指令!!由此
便带来一个问题,当前指令执行的时候,PC的值已经不是当前指令所在的地址了,而是
当前地址+8
   0x00000000
   0x00000004        ---假设为当前执行的指令地址
   0x00000008
PC-> 0x0000000c        PC指向的是这儿

上电之时,PC便首先指向了flash的0地址,这个地方的指令将被执行。那么我们的程序如
何才能被放在这个0地址呢,当然不能随便写,汇编中,这些都是有固定格式的,如下 :

   AREA Init,CODE,READONLY
   ENTRY
这个ENTRY便是表明,下面的程序为整个工程代码的入口点,至于如何放到flash的0地址,
那个就是flash烧写的工作了,不归我管,^_^

有了这样的入口,Init都要做些什么,先大概说说,包括几个部分吧,这些,也就是对
2440的初始化了
%定义入口地址
%建立异常向量表
%初始化存储器系统
%初始化堆栈
%初始化必要IO
%初始化中断系统要求的RAM向量
%开中断
%如有必要,改变处理器模式
%如有必要,改变处理器状态
%初始化C语言要求的存储器空间
%跳转到C去执行

建立异常向量表
我们知道,中断机制是PC机中一个非常重要的地方,中断节省CPU资源,加快了突发事件
的处理速度。在arm中,也差不多采取了类似的机制。PC中我们叫中断向量表,中断向量
表存放了一系列的跳转指令,当有中断产生的时候,系统便会自动到中断向量表查找相应
的中断向量号,然后根据中断号跳转到相应的地址去执行。
对于异常向量表,其实也是类似的功能,只不过对于一个arm来说,它上升到了工作模式
的高度,也就是说我们通常用的是用户模式,当有情况发生的时候,它要切换到相应的模
式下进行工作,比如中断,就是其中的一种!其他的还有管理模式,未定义指令模式,快
速中断模式,系统模式等等

异常向量表通常如下所示

b ResetHandler
b HandlerUndef
b HandlerSWI
b HandlerPabort
b HandlerDabort
b .
b IsrIRQ
b HandlerFIQ

那么,当有情况发生的时候,程序便会跳转到这个异常向量表的相应位置,执行相应的
跳转,如IRQ发生的时候,它就跳转到b IsrIRQ,进而执行这个跳转,去执行IsrIRQ标号
的代码

好了,知道了这个机制,便要关心这个表放在什么地方,才能让异常发生的时候,跳转
到这个表去执行相应的指令呢,呵呵,这肯定是放在一个特殊的地方,那就是0地址,
不过要注意了,这里0地址是哪里的0地址呢,呵呵
我们知道,异常的发生肯定是操作系统正在进行工作的时候,操作系统的工作是在
哪里进行??^_^,知道了,就是SDRAM,好了,操作系统在工作的时候,是不会在
返回到Nand Flash中去寻找咚咚的,明白了,这个异常向量表就是放在SDRAM的0地
址处,而且,一定要放在这个地方,这个地方也不能放别的东西,它就是放异常向量表

呵呵,插一段,我们要说说对于2440,它的启动流程是什么样子的,PC是怎么变化
的,简单说说吧

在Nand Flash中,bootloader,内核启动参数,内核,根文件系统是顺序存放的,并且,
bootloader是存放在0地址的,上电之后,PC就是指向这个0地址,并且开始执行,
bootloader要做很多事情,并且这些指令都是对CPU进行操作的,所以,很重要。而Init
就是bootloader中的一个部分,它的任务可以说是bootloader的子集;PC顺序执行,
首先关中断啊,初始化时钟啊等等,然后,将bootloader第二阶段的内容复制到SDRAM中
,包括Main主函数、内核和文件系统等复制过去,然后跳转到SDRAM中去执行,在执行
到跳转到内核去执行的时候,它要做一件事情,就是内存重映射,将PC重新定向到0地址
,并执行放在那儿的跳转指令……

转自http://space.baidu.com/%D2%FE%D0%CE%C8%CBlaigo/blog/item/7c2caadc02b87faacd1166b2.html

Comments

Popular posts from this blog

Basic understanding of TLS-PSK protocol

Differences between ASIC, ASSP and ASIP

Orthogonal instruction set