背景:
Board ? ar7240(ap93) Cpu ? mips
1、首先弄清楚什么是u-boot
Uboot是德国DENX小组的开发,它用于多种嵌入式CPU的bootloader程序, uboot不仅支持嵌入式linux系统的引导,当前,它还支持其他的很多嵌入式操作系统。 除了PowerPC系列,还支持MIPS,x86,ARM,NIOS,XScale。
2、下载完uboot后解压,在根目录下,有如下重要的信息(目录或者文件):
根目录 (u-boot) board common cpu disk Doc drivers fs include Lib_xxx net tools
以下为为每个目录的说明:
Board:和一些已有开发板有关的文件。每一个开发板都以一个子目录出现在当前目录中,子目录存放和开发板相关的配置文件。它的每个子文件夹里都有如下文件(以ar7240/ap93为例): Makefile Config.mk Ap93.c 和板子相关的代码 Flash.c Flash操作代码 u-boot.lds 对应的链接文件
common:实现uboot命令行下支持的命令,每一条命令都对应一个文件。例如bootm命令对应就是cmd_bootm.c
cpu:与特定CPU架构相关目录,每一款Uboot下支持的CPU在该目录下对应一个子目录,比如有子目录mips等。它的每个子文件夹里都有入下文件: Makefile Config.mk Cpu.c 和处理器相关的代码s Interrupts.c 中断处理代码 Serial.c 串口初始化代码 Start.s 全局开始启动代码
Disk:对磁盘的支持
Doc:文档目录。Uboot有非常完善的文档。
Drivers:Uboot支持的设备驱动程序都放在该目录,比如网卡,支持CFI的Flash,串口和
USB等。
Fs:支持的文件系统,Uboot现在支持cramfs、fat、fdos、jffs2和registerfs。
Include:Uboot使用的头文件,还有对各种硬件平台支持的汇编文件,系统的配置文件和对
文件系统支持的文件。该目下configs目录有与开发板相关的配置文件,如ar7240_soc.h。该目录下的asm目录有与CPU体系结构相关的头文件,比如说mips对应的有asm-mips。
Lib_xxx:与体系结构相关的库文件。如与ARM相关的库放在lib_arm中。
Net:与网络协议栈相关的代码,BOOTP协议、TFTP协议、RARP协议和NFS文件系统的
实现。
Tools:生成Uboot的工具,如:mkimage等等。
3、mips架构u-boot启动流程 u-boot的启动过程大致做如下工作: 1、cpu初始化 2、时钟、串口、内存(ddr ram)初始化 3、内存划分、分配栈、数据、配置参数、以及u-boot代码在内存中的位置。 4、对u-boot代码作relocate 5、初始化malloc、flash、pci以及外设(比如,网口) 6、进入命令行或者直接启动Linux kernel 刚一开始由于参考网上代码,我一个劲的对基于smdk2410的板子,arm926ejs的cpu看了N久,启动过程和这个大致相同。
整个启动中要涉及到四个文件: Start.S ? cpu/mips/start.S Cache.S ? cpu/mips/cache.S Lowlevel_init.S ? board/ar7240/common/lowlevel_init.S Board.c ? lib_mips/board.c
整个启动过程分为两个阶段来看: Stage1:系统上电后通过汇编执行代码
Stage2:通过一些列设置搭建了C环境,通过汇编指令跳转到C语言执行.
Stage1:
程序从Start.S的_start开始执行.(至于为什么,参考u-boot.lds分析.doc) 先查看start.S文件吧!~
从_start标记开始会看到一长串莫名奇妙的代码:
RVECENT(reset,0) /* U-boot entry point */ /*U-Boot开始执行的代码起始地址*/ RVECENT(reset,1) /* software reboot */ /*软重启时U-Boot开始执行的起始地址*/ RVECENT(romReserved,2) /*保留本代码所在的地址,重新映射调试异常向量时可以使用该空间*/ RVECENT(romReserved,3) RVECENT(romReserved,4) RVECENT(romReserved,5) RVECENT(romReserved,6) RVECENT(romReserved,7) RVECENT(romReserved,8) RVECENT(romReserved,9) … …
回过头看刚开始的定义有这样的代码: 可以找到:
#define RVECENT(f,n) \\ b f; nop
原来这只是一个简单的跳转指令,f为一个标记,b为跳转指令。
然后看最后,发现: romReserved:
b romReserved
romExcHandle:
b romExcHandle
这两个标记都构建了无意义的死循环。
通过_start标记处的语句RVECENT(reset,0) 代码跳转到标记reset的地方,该段代码的操作就是对寄存器的清零操作了。Mfc0和mtc0指令是对寄存器的一些读写.
在接下来是对协处理器的操作了,其中包括:
CP0_WATCHLO, CP0_WATCHHI, CP0_CAUSE, CP0_COUNT, CP0_COMPARE
之后,配置寄存器CP0_STATUS,设置所使用的协处理器,中断以及cpu运行级别(核心级)。 配置gp寄存器,把GOT段的地址赋给gp寄存器。(gp寄存器的用处会在后面relocate code部分详细解释)
接下来执行lowlevle_init.S的lowlevel_init函数,主要目的是工作频率配置,比如cpu的主频,总线(AHB),DDR 工作频率等。
然后执行cache.S中的mips_cache_reset对cache进行初始化。接着调用mips_cache_lock
u-boot启动分析



