Bootloader的启动过程可以分为单阶段、多阶段两种。通常多阶段的 Bootloader能提供更为复杂的功能以及更好的可移植性。从固态存储设备上启动的 Bootloader大多都是两阶段的启动过程。第一阶段使用汇编来实现,它完成一些依赖于CPU体系结构的初始化,并调用第二阶段的代码;第二阶段则通常使用C语言来实现,这样可以实现更复杂的功能,而且代码会有更好的可读性和可移植性。
嵌入式进阶教程分门别类整理好了,看的时候十分方便,由于内容较多,这里就截取一部分图吧。
需要的朋友私信【内核】即可领取。
一般而言,这两个阶段完成的功能可以如下分类:
Bootloader第一阶段的功能硬件设备初始化首先需要设置时钟,设置MPLL(具体参见下面的FCLK HCLK PCLK 部分)。接着设置CLKDIVN地址为0x4C000014,写入0x05,表示设置分频系数为FCLK:HCLK:PCLK=1:4:8。接着,关闭看门狗,关中断,启动ICACHE,关闭DCACHE和TLB,关闭MMU(ICACHE为指令缓存,可以不关闭,指令直接操作的硬件,实际的物理地址。但是DCACHE就必须要关闭,此时MMU没有使能,虚拟地址映射不成功,SDRAM无法访问,DCACHE无数据)。start.s具体代码如下:
/* 设置时钟 */
ldr r0, =0x4c000014
// mov r1, #0x03;
mov r1, #0x05; // FCLK:HCLK:PCLK=1:4:8
str r1, [r0]
/* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
mrc p15, 0, r1, c1, c0, 0 /* 读出控制寄存器 */
orr r1, r1, #0xc0000000 /* 设置为“asynchronous bus mode” */
mcr p15, 0, r1, c1, c0, 0 /* 写入控制寄存器 */
/* MPLLCON = S3C2440_MPLL_200MHZ */
ldr r0, =0x4c000004
ldr r1, =S3C2440_MPLL_400MHZ
str r1, [r0]
/* 启动ICACHE */
mrc p15, 0, r0, c1, c0, 0 @ read control reg
orr r0, r0, #(1<<12)
mcr p15, 0, r0, c1, c0, 0 @ write it back
这里具体讲下是如何设置FCLK HCLK PCLK。 FCLK又称为内核时钟,是提供给ARM920T 的时钟。HCLK又称为总线时钟,是提供给用于存储器控制器,中断控制器,LCD 控制器,DMA 和 USB 主机模块的 AHB总线(advanced high-performance bus)的时钟。
PCLK又称为I/O接口时钟,是提供给用于外设如WDT,IIS,I2C,PWM 定时器,MMC/SD 接口,ADC,UART,GPIO,RTC 和SPI的 APB (advanced peripherals bus)总线的时钟。
S3C2440 FLCK值为400MHz,HCLK值为100MHz、PCLK值为50MHz。那么这些值通过什么方法计算出来呢?S3C2440上的时钟源是12MHz,如果想让CPU工作在更高频率上,就需要通过PLL(锁相环)来提高主频。S3C2440上的PLL有两种,一种是MPLL,它是用来产生FCLK、HCLK、PCLK的高频工作时钟;还有一种是UPLL,用来为USB提供工作频率。S3C2440时钟体系如下:
从时序图中,我们可以看到,上电之后,如果什么都不设置,FCLK和晶振的频率相等。当设置PLL后,CPU并不是马上就使用设置好的高频时钟,而是有一段锁定时间,在这段时间里,CPU停止运行,等12MHz变成高频时钟稳定以后,整个系统再重新运行。
开启MPLL的过程: 1、设置LOCKTIME变频锁定时间2、设置FCLK与晶振输入频率(Fin)的倍数 、设置FCLK,HCLK,PCLK三者之间的比例从手册上可以看到,LOCKTIME的默认时间是0xFFFFFFFF,控制方法如图:刚设置好PLL时,系统认为这是PLL还没稳定,所有这时不用PLL的时钟,而用外部晶振做时钟,将PLL锁住,过了LOCKTIME后认为PLL已经稳定了,才使用PLL给系统提供时钟)