u-boot.2012.10——mini2440(二、启动流程分析)

时间:2022-08-16 16:36:20

参考资料:https://blog.csdn.net/suiyuan19840208/article/details/7239949

        https://blog.csdn.net/pugu12/article/details/47011159

1、第一阶段功能

  * 硬件设备初始化

  * 加载u-boot第二段代码到RAM空间

  * 设置好栈

  * 跳转到第二段代码入口

2、第二段代码的功能

  * 初始化本阶段使用的硬件设备

  * 检测系统的内存映射

  * 将内核从Flash读到RAM中

  * 为内核设置启动参数

  * 调用内核

3 、u-boot第一阶段代码分析

我们在编译完成之后,观察顶层目录有个u-boot.lds的链接脚本

 

* 经过编译之后,查看文件u-boot.lds链接脚本,可以看到第一个链接文件是start.S

u-boot.2012.10——mini2440(二、启动流程分析)

 

4、start.S

* 设置异常向量

当一个异常产生时,CPU根据异常号在异常向量表中找到对应的异常向量,然后执行异常向量处的跳转指令,,CPU跳转到对应的异常处理程序执行。

其中复位异常向量的指令“b start_code”决定了启动后将自动跳转到标号"start_code"处执行。

u-boot.2012.10——mini2440(二、启动流程分析)

* CPU进入SVC模式

从数据手册上可以看到10011就是设置为管理模式

u-boot.2012.10——mini2440(二、启动流程分析)

 

u-boot.2012.10——mini2440(二、启动流程分析)

 * 设置控制寄存器的地址

u-boot.2012.10——mini2440(二、启动流程分析)

* 关闭看门狗

u-boot.2012.10——mini2440(二、启动流程分析)

* 屏蔽中断

u-boot.2012.10——mini2440(二、启动流程分析)

 

*设置时钟

u-boot.2012.10——mini2440(二、启动流程分析)

 CPU上电几毫秒后,晶振输出稳定,FCLK=Fin(晶振频率),CPU开始执行指令。但实际上,FCLK可以高于Fin,为了提高系统时钟,需要用软件来启用PLL。这就需要设置CLKDIVN,MPLLCON,UPLLCON这3个寄存器。 

 CLKDIVN寄存器,CLKDIVN寄存器用于设置FCLK,HCLK,PCLK三者间的比例

 u-boot.2012.10——mini2440(二、启动流程分析)

设置CLKDIVN为5,就将HDIVN设置为二进制的10,由于CAMDIVN[9]没有被改变过,取默认值0,因此HCLK = FCLK/4。

 PDIVN被设置为1,因此PCLK= HCLK/2。因此分频比FCLK:HCLK:PCLK = 1:4:8 。

 

 FCLK提供给ARM920T的时钟

 HCLK 是提供给用于 ARM920T,存储器控制器,中断控制器,LCD 控制器,DMA 和 USB 主机模块的 AHB总线的时钟  

 PCLK 是提供给用于外设如WDT,IIS,I2C,PWM 定时器,MMC/SD 接口,ADC,UART,GPIO,RTC 和SPI的 APB 总线的时钟

 

 FCLK与Fin的关系如下面公式:

u-boot.2012.10——mini2440(二、启动流程分析)

MPLLCON寄存器用于设置FCLK与Fin的倍数。MPLLCON的位[19:12]称为MDIV,位[9:4]称为PDIV,位[1:0]称为SDIV。

u-boot.2012.10——mini2440(二、启动流程分析)

MPLLCON与UPLLCON的值可以根据参考:

u-boot.2012.10——mini2440(二、启动流程分析)

MPLLCON=(0x7f<<12) | (0x02<<4) | (0x01) = 0x7f021

UPLLCON=(0x38<<12) | (0x02<<4) | (0x02) = 0x38022

 5、关闭 MMU、cache

u-boot.2012.10——mini2440(二、启动流程分析)

u-boot.2012.10——mini2440(二、启动流程分析)

 

代码中的c0,c1,c7,c8都是ARM920T的协处理器CP15的寄存器。其中c7是cache控制寄存器,c8是TLB控制寄存器。325~327行代码将0写入c7、c8,使Cache,TLB内容无效。

第332~337行代码关闭了MMU。这是通过修改CP15的c1寄存器来实现的,先看CP15的c1寄存器的格式(仅列出代码中用到的位):

u-boot.2012.10——mini2440(二、启动流程分析)

V : 表示异常向量表所在的位置,0:异常向量在0x00000000;1:异常向量在 0xFFFF0000
I : 0 :关闭ICaches;1 :开启ICaches
R、S : 用来与页表中的描述符一起确定内存的访问权限
B : 0 :CPU为小字节序;1 : CPU为大字节序
C : 0:关闭DCaches;1:开启DCaches
A : 0:数据访问时不进行地址对齐检查;1:数据访问时进行地址对齐检查
M : 0:关闭MMU;1:开启MMU

332~337行代码将c1的 M位置零,关闭了MMU。

 

6 、初始化 RAM 控制寄存器

其中的lowlevel_init就完成了内存初始化的工作,由于内存初始化是依赖于开发板的,

因此lowlevel_init的代码一般放在board下面相应的目录中。

对于mini2440,lowlevel_init在board/samsung/mini2440/lowlevel_init.S中定义如下:

7、初始化堆栈、复制U-Boot第二阶段代码到RAM

* 设置栈,跳转到board_init_f

u-boot.2012.10——mini2440(二、启动流程分析)

 * board_init_f 

 * 设置gd结构体

u-boot.2012.10——mini2440(二、启动流程分析)

* 初始化函数

u-boot.2012.10——mini2440(二、启动流程分析)

u-boot.2012.10——mini2440(二、启动流程分析)

 

*   board_early_init_f函数在board/samsung/smdk2410目录下的smdk2410.c文件内

*  timer_init函数在arch/arm/cpu/arm920t/s3c24x0目录下的timer.c文件内

*  env_init函数在common目录下的env_flash.c文件内
*  init_baudrate函数在arch/arm/lib目录下的board.c文件内
*  serial_init函数在drivers/serial目录下的serial_s3c24x0.c文件内,在include/configs/smdk2410.h中CONFIG_S3C24X0_SERIAL
*  console_init_f函数在common目录下的console.c文件内
*  display_banner函数在arch/arm/lib目录下的board.c文件内
*  dram_init函数在board/samsung/smdk2410目录下的smdk2410.c文件内
 
env_init最后关联到这个数组,用于设置环境变量
'\0'表示未进行设置
 
u-boot.2012.10——mini2440(二、启动流程分析)
board_init_f 先是把RAM的地方给大家分好,设置各个模块的地址,例如堆栈、第二段代码的链接地址,最后复制地位段代码到RAM上去。
u-boot.2012.10——mini2440(二、启动流程分析)