bootloader

来源:互联网 发布:数据分析专业 上海财经 编辑:程序博客网 时间:2024/06/05 18:00
bootloader最终目的:启动内核

BootLoader就是在操作系统运行之前运行的一段小程序。通过这段小程序,可以初始化硬件设备,从而将系统的 
软硬件环境带到一个合适的状态,以便为最终调用操作系统做好准备
在嵌入式系统中,通常没有像BIOS那样的固件程序,因此整个系统的加载启动任务就完全由BootLoader来完成。 
一个嵌入式系统从软件角度来看分为三个层次:
1. 引导加载程序
包括固化在固件(firmware)中的boot程序(可选),和BootLoader 两大部分。 
2. Linux 内核
特定于嵌入式平台的定制内核。
3. 文件系统
包括了系统命令和应用程序。

系统加电或复位后,所有的CPU通常都从CPU制造商预先安排地址开始执行。 比如,S3C2410在复位后从地址0x00000000起开始执行。而嵌入式系统则将固态存储设备(比如:FLASH)安排在这个地址上,而bootloader程序 
又安排在固态存储器的最前端,这样就能保证在系统加电后,CPU首先执行BootLoader程序。

BootLoader 的启动过程可分为单阶段(Single-Stage)和多阶段(Multi-Stage)两种,
BootLoader 大多采用两阶段,
stage1 :汇编编写(C程序运行需要环境)  //程序在Flash上 因为内存掉电即清空
(1)设置svc模式                        //CPU内部的 
(2)关闭看门狗               
(3)屏蔽中断   
(4)初始化SDRAM
(5)设置好堆栈             //为C程序设置 没有堆栈C程序无法运行(局部变量,函数传参大于4时都要用到栈)
(6)初始化时钟
(7)将代码从nand拷贝到SDRAM中
(8)清除BSS段
(9)调用C函数 start_armboot跳到stage2处    //start_armboot函数在lib_arm目录下的board.c文件中 
stage2:
(1)初始化本阶段要使用到的硬件设备                  //板载的硬件(串口、网卡、、、)
(2)将内核映像和根文件系统映像从flash上读到RAM中   //在内存比在Flash上读取速度快
(3)调用内核
分析编译makefile:
第一个文件CPU/arm920t/start.s
链接地址:board/100ask24X0/u-boot.lds + text_base 0x33f80000

如果从norflash启动: 0地址对应于norflash  0地址不能像内存一样去写入
如果从nandflash启动:0地址对应于片内内存  0地址可以写


UBOOT目录结构
Board :和开发板有关的文件。每一个开发板都以一个子目录出现在当 前目录中,比如:SMDK2410,子目录中存放与开发板相关的文件。
Common:实现Uboot支持的命令
Cpu :与特定CPU架构相关的代码,每一款Uboot下支持的CPU在该目录下对应一个子目录,比如有子目录arm920t等
Disk:对磁盘的支持。
Doc:文档目录。Uboot有非常完善的文档,
Drivers :Uboot支持的设备驱动程序都放在该目录,比如各种网卡、支持CFI的Flash、串口和USB等。
Fs:文件系统的支持。
Include :Uboot使用的头文件。该目录下configs目录有与开发板相关的配置头文件,如smdk2410.h。 该目录下的asm目录有与CPU体系结构相关的头文件。
Net:与网络协议栈相关的代码,例如:TFTP协议、RARP协议的实现。
Tools:生成Uboot的工具,如:mkimage, crc等等。


uboot 命令:
help 查看当前单板所支持的命令
printenv:查看环境变量
setenv:添加、删除、修改环境变量  //添加或修改 setenv  name  123  ; 删除  setenv  name
saveenv:保存环境变量    // 如果不保存上次添加的环境则掉电丢失(saveenv将环境变量从内存保存到Flash)
 setenv ethaddr 12:34:56:78:9A:BC
 setenv ipaddr 192.168.1.1
 setenv serverip 192.168.1.254 (tftp服务器的地址)

tftp:网络下载             //事先保证网络畅通 ping  sercverip 
tftp 32000000 uImage  // 大约5秒钟完成
//把server(IP=环境变量中设置的serverip)中服务目录下的uImage通过TFTP读入到0x32000000处。
loadb :串口下载
loadb 31000000           //然后在超级终端上传送文件uImage()   大约25分钟完成

md:显示内存              //默认以四字节显示        md [.b, .w, .l] address
md 32000000             //md.b 32000000   以字节格式显示
mm:修改内存中的内容
mm 32000000      //交互方式修改   按空格然后回车退出

flinfo:查看Flash信息(大小  硬件名  扇区、、、)

protect                                    //Flash写保护
protect off all                       // 关闭所有扇区的写保护 
protect on all                      //打开所有扇区的写保护 
protect off start end         //关闭从start 到 end 扇区的写保护
protect on start end       // 打开从start 到 end 扇区的写保护 
(start为要关闭的第1个扇区的起始地址,end为要关闭的最后一个扇区的结束地址) 

erase           //擦除flash扇区
用法: erase start end          例:erase 30000 1effff 
擦除从start 到 end 的扇区,start 为要擦除的第1个扇区的起始地址,end 为要擦除的最后一个扇区的结束地址(在使用cp命令向Nor型Flash写入数据之前必须先使用erase 命令擦除flash,因为nor flash 按字节写入时,无法写入1,所以必须通过擦除来写入1:擦除的位置全写1)。 

cp:        //数据拷贝。                cp [.b, .w, .l] saddress daddress len 
cp 提供了一种内存与内存,内存与Flash之间数据拷贝的方法。 
例:
cp.b 31000000 50000 d0000    //将内存地址0x31000000处的数据(长度为0xd0000)拷贝到地址0x50000处(Flash中) cp.b 32000000 120000 c0000  //将内存地址0x32000000处的数据(长度为0xc0000)拷贝到 地址0x120000处(Flash中) 

go :  执行内存中的二进制代码,一个简单的跳转到指定地址 
go addr [arg ...]                     // [ ]中的内容表示可有可无
bootm 执行内存中的二进制代码 
//要求二进制代码有固定格式的文件头(uImage有这个头(64字节)  zImage没这个头)
bootm [addr [arg ...]] 

bdinfo – 显示开发板信息 
bdinfo命令(简写为bdi)将在终端显示诸如内存地址和大小、时钟频率、MAC地址等信息。这些信息在传递给Linux内核一些参数时可能会用到。 




移植:
每种不同的CPU体系结构都有不同的BootLoader。除了依赖于CPU的体系结构外, BootLoader 还依赖于具体的嵌入式板级设备的配置,对于两块不同的开发板而言,即使它们是基于同一种CPU而构建的,但如果他们的硬件资源或配置不一致的话,要想在一块开发板上运行的BootLoader程序也能在另一块板子上运行,还是需要作修改。

1.给板子命名,fsc100
2.在顶层Makefile里面创建目标fsc100_config
2.在顶层Makefile里面创建目标fsc100_config
ifeq(arm,$(ARCH))
CROSS_COMPILE ?=  $(ARCH)-cortex_a8-linux-gnueabi-
endif

fsc100_config_config:  unconfig 
    @./mkconfig $(@:_config=) arm arm920t smdk2410 NULL s3c24x0 
参考上面2行,添加下面2行:
fsc100_config:  unconfig 
    @./mkconfig $(@:_config=) arm arm920t mini2440 NULL s3c24x0

mkconfig 是一个脚本  后面的是它的参数
分析 mkconfig脚本
cd  ../include            //下面三个链接两个创建都是在include目录下
在include目录下创建链接asm-->asm-arm
在asm_arm目录下创建链接arch-->arch-s3c24x0
在asm_arm目录下创建链接proc-->proc-armv
在include目录下创建config.mk  
将ARCH=arm  CPU=arm920t  BOARD=smdk2440 VENDOR=NULL SOC=s3c24x0 放到该文件下
在include目录下创建config.h(在start.s中包含过) 板子相关头文件 

3.到board/$(venddr) 下创建fsc100     cp -r  smdkc100/   fsc100
fsc100目录下要修改的文件
(1)low_level_init.S    //关看门狗  系统时钟初始化 串口初始化 nandflash初始化
(2)mem_setup.S         //内存初始化    
(3)fsc100.c             
(4)nand_cp.c           //将uboot拷贝到内存中
(5)本目录下的Makefile
    COBJS-Y  :=fsc100.o   nand_cp.o          //该目录下的.c文件
    SOBJS    :=low_level_init.o  mem_setup.o   //该目录下的.s文件

4.到include/configs 下创建fsc100.h   cp smdkc100.h  fsc100.h
修改fsc100.h
CONFIG_
CONFIG_SYS_

5.启动文件cpu/arm_cortexa8/start.S
(1)设置到SVC模式下
(2)跳到low_level_init.S   //关看门狗  系统时钟初始化 串口初始化 nandflash初始化
(3)重定位relocate:       //看是否在Flash或RAM中运行   将uboot拷贝到内存中
(4)堆栈初始化
(5)清BSS段
(6)跳到C函数start_armboot执行

6.驱动 drivers/
(1)drivers/mtd/nand/s5p_nand.c
(2)dirvers/net/dm9000x.c
(3)net/net.c
原创粉丝点击