S5PV210的IROM做了什么

对S5PV210_iROM_ApplicationNote_Preliminary_20091126手册里的描述翻译一下。

1.关看门狗定时器        

这个很容易理解,为了防止后面用户忘记初始化而系统重启。为什么三星要这么麻烦,不默认禁止掉看门狗,我猜看门狗定时器应该是属于内核的内容,是ARM公司定的。

2.初始化指令缓存

这个是为了加快CPU指令存取,通常CPU取指令是用到一条在内存中读取一条(虽然有两级流水线),但内存的访问速度比较慢,所以影响系统性能。开启了指令缓存后,CPU会每次读取一个cache的大小(3k,5k多大由制造商决定),如果要取的指令在cache中没有才会去内存中读取,而且一次也是读取一整cache,通常一条指令执行完后如果不是发生跳转都是执行下一条指令,这样CPU就能从cache中读取,而不用再去内存中读取,cache的读取速度远快于内存,所以开启cache可以加快指令的读取速度。

3.初始化栈

主要就初始化SVC模式和IRQ模式的栈。量中模式的栈的指针指向如下图所示。


4.初始化堆区

见上图0xd0035400到0xd0037400,可读可写,同时把内容初始化为0

5.初始化块设备拷贝函数

6.初始化时钟

7.拷贝BL1的内容到BL1

8.校验BL1的内容,如果校验失败则从SD/MMC通道2 启动

9.判断是否需要安全启动模式

10跳转到BL1执行

但经过很多的事实证明,其实IROM做的事情更多,比如没有判断OM_PIN的启动方式,没有写时钟初始化为多少,没有说明初始化了串口......。

前四步很简单,不需要任何判断,可以无脑的顺序执行。

第五步分析:

初始化块拷贝函数,其实这一步不叫做初始化块拷贝函数,应该称为初始化块设备(比如SD卡控制器,NAND控制器...)。而且不是把所有的块设备都初始化,在他初始化这些块设备之前,其实它就要判断OM PIN引脚,判断当前的启动方式。比如OM PIN为MMC通道0启动则,代码会调用MMC0初始化函数,然后从MMC0拷贝BL1大小到SRAM的0xd0020000位置。

至于BL1多大手册也有说明,如下图,最大为16K。


IROM的代码其实就是拷贝16K.

从官方给的图上来看,初始化时钟是在判断OM_PIN前面的,所以第5步和第6步应该是要调换顺序。

前面说到,IROM中的软件会根据OM_PIN引脚初始化块设备,如果校验通过启动成功则,则不会初始化其他块设备。(本人上次通过USB启动的,后面使用到了系统给的块初始化函数,发现如果最后一个参数[0表示不再需要初始化,1代表需要初始化]给的是0,则不能正确读MMC卡,若给的1则可以正确读写,则证明USB启动的情况下,MMC控制器没有被初始化)。若要使用系统给的块设备读取函数,也要考虑初始话问题。

第六步分析:

 时钟最终初始化为了多少?  在外部时钟为24M的情况下,系统时钟配置为了400MHz。下图也把所有的配置参数和公式给了出来。一般我们需要系统跑1G,所以系统启动后我们通常需要重新配置时钟参数。


第七步分析

拷贝BL1到SRAM的0xd0020000。前面我说的拷贝16K,但uboot中BL1为8k,这有事怎么回事。


从上面的图上可以看到,头信息的前4个字节保存的是BL1的大小,IROM会从块设备拷贝16K到SRAM,但进行校验分析的时候,会从头信里的前四个字节判断当前用户设置的BL1为多大,如果头信息里写的BL1为8K,则计算校验和的时候,系统也只会计算8K的内容。(虽然读到SRAM中16K)

第八步分析:

校验和的计算也很简单,把BL1除去头信息的16个字节的内容进行按字节相加。


第九步安全启动我没研究过,就不分析了

第十步直接把PC指针指向0xd0020010位置就可以了


但实际使用的时候,发现如果系统中无可以正确启动的程序,如果串口2接到电脑上也会打印出来一些提示信息,如下图所示。前提是波特率为115200


但把串口接在串口0或其他串口上则没有。事实证明,在IROM中,三星也初始化过串口2了已经。为了证实这个猜想,我在自己写的裸机代码中,不初始化串口。直接使用串口2,发现也能使用,则证明三星确实是在IROM中初始化过串口2。

2018.5.20增加:

关于USB的dnw启动方式,三星在irom中应该使用了定义的一套串行传输协议,用来保证dnw启动。

uart启动,这个我没有使用过,但手册中说了,就应该也做了相关的处理。

重点说一下手册中没说明异常向量表的初始化。

因为ARM通常是把异常向量表的地址放在0地址开始的位置。而三星手册中直接标明放在iram中,说明irom对异常向量表进行了初始化。

根据cortex-a8指南中说明了可以通过更改cp15的从c12寄存器来更改异常向量表的基地址,来让异常向量表进行偏移。使用方法很简单,如下

/* 设置0x30000000为异常向量表的起始地址 */

ldr r0, = 0x30000000
mcr p15, 0, r0, c12, c0, 0

但我通过实验验证iram中的异常向量表只能实现irq和fiq的中断。其它异常不能实现。而我更改异常向量表的基地址后,却能实现软中断,指令错误中断等。说明irom中并没有更改异常向量表的基地址。

我猜是使用函数指针的方式只实现了irq和frq的异常处理函数的地址。

实现应该为发生相应中断,跳到0地址的异常向量表,然后0地址的异常向量表中给定的是iram中的地址,程序会继续跳转到iram中执行相应的中断。irom中的代码通常不会出错,所以没有实现其它异常,而是启动后让用户自己实现。


猜你喜欢

转载自blog.csdn.net/qq_16777851/article/details/80302639