U-boot 源代码下载:ftp://ftp.denx.de/pub/u-boot/ 启动过程分析:1.小于8Kb的程序:IROM从nand读8K数据到ISRAM中运行; 2.大于8kb程序(主要指u-boot):IROM从nand读前8k数据到SRAM中主要做两件事: 第一:初始化DRAM; 第二:将剩下的代码搬运到DRAM运行。 3.在DRAM中就可以引导系统启动了。 BL0:IROM,出厂已固化代码 BL1:ISRAM的前16kb,u-boot-spl.bin BL2:ISRAM的后80kb,u-boot.bin ISRAM是内置内存,不用初始化就可以使用; DRAM是外接内存,需要初始化才能使用。 uboot有两种模式: 1.启动加载模式:存储在nand上,上电将操作系统加载到DRAM运行。正常启动时的模式,自动加载linux内核。 2.下载模式:调试模式,通过网络或串口从主机获得文件,控制启动流程。按下任意键进入下载模式。 bootloader有两个阶段: 1.第一阶段代码用汇编:arch/arm/cpu/armv7/start.S和board/samsung/smart210/lowlevel_init.S,从ISRAM运行。 第一:建立中断向量表和异常向量表 第二:获取启动参数,设置SVC32模式,拷贝前8k代码到ISRAM。 第三:cpu_init_crit: 关I/D cache,关看门狗,清TLB,关MMU等 第四:cpu_init_crit调用lowlevel_init.S: 设置TCPZ,禁止中断,初始化系统时钟、内存、串口、nand等 第五:设置栈,判断启动开关,sd卡启动就跳转到board_init_f,nand启动就跳转到board_init_f_nand。 第六:搬运代码,从sd卡或nand到DRAM(内存)。 第七:初始化栈,清bss段,跳转到board_init_r,完了启动过程结束。 2.第二阶段代码用c:arch/arm/lib/board.c和common/main.c,从内存运行。 board_init_f: 为gd数据结构分配地址并清零; 执行init_fnc_ptr函数指针数组中的各个初始化函数; 分配DRAM高64kb为TLB,用于uboot; 分配DRAM下一个单元为uboot代码段,数据段,bss段; 开辟malloc空间存放bd,gd,3个字大小的异常堆空间; 将relocate地址传给gd结构体变量,用于返回start.S。 board_init_r:在内存中运行 对gd,bd数据结构赋值初始化; 各种外设初始化; 进入main_loop,(main_loop函数在common/main.c中定义,进入main.c) common/main.c:引导内核 u-boot源代码支持一部分官方的评估开发板,不需要修改u-boot。由于我们用的cpu和官方的测试版的cpu相同,所以cpu部分u-boot不需要修改,其他部分需要修改。SMDK指三星的评估板 移植关心的文件夹: board文件夹 :和开发板相关的,是移植需要修改的。 arch/arm/文件夹 :和处理器相关的,主流的cpu都是支持的. lib文件夹 :u-boot的通用的自己的库。 arch/arm/lib文件夹 :根据arm处理器创建的库。 include/configs文件夹:里面是头文件,需要修改。 drivers文件夹 :驱动文件夹. common文件夹 :u-boot核心代码。 net文件夹 :网络协议相关代码。 tools文件夹 :u-boot提供的编译运行等辅助工具。 1.u-boot启动过程: start.S :arch/arm/cpu/armv7/start.S,程序的入口; board.c :arch/arm/lib/board.c,不用修改,可以用于所有arm; main.c :common/main.c,与硬件无关,不用修改,所有开发板通用,用来启动内核。 arch/arm/cpu/armv7/start.S调用board/samsung/smart210/lowlevel_init.s进行初始化(主要初始化内存DRAM)。 arch/arm/lib/board.c初始化和硬件相关的函数,调用相关的初始化函数进行初始化开发板上资源。 common/main.c是整个u-boot程序的主函数,主要负责运行维护uboot的shell命令行。 2.添加和开发板相关的程序和头文件 在boart/sumsung/下面新建一个文件夹smart210 参考board/sumsung/smdkv210文件夹中的文件修改成smart210可用文件。 第一、修改arch/arm/cpu/armv7/start.S #include #include #include 定义代码段的链接地址 .globl _TEXT_BASE _TEXT_BASE: .word CONFIG_SYS_TEXT_BASE 定义当前程序的开始地址,一般是在DRAM中 .globl _armboot_start _armboot_start: .word _start #endif 第二、修改board/samsung/smart210/lowlevel_init.S #include #include "smart210_val.h" 第二、修改和开发板相关的代码 board/sumsung/smart210/smart210.c 参看smdkc100,主要进行一些cpu控制器和资源的初始化工作。 #include include/s5pc110.h包含下面两个 include/s5pc110.h arch/arm/include/asm/arch/hardware.h(arch是arch-s5pc1xx的链接) 第四、include/configs/smart210.h 配置文件,添加需要的宏定义。 #defineCONFIG_SAMSUNG 1 #define CONFIG_S5P 1 #define CONFIG_S5PC110 1 #define CONFIG_SMART210 1 #define CONFIG_MACH_TYPE MACH_TYPE_SMART210 #define CONFIG_SYS_TEXT_BASE 0x23E00000 //定义代码段的链接地址 #defineMACH_TYPE_SMART210 3466 配合文件中主要有另类宏: 1.CONFIG_开头的用于cpu、soc、board等的时钟设置、设备驱动等。 2.CFG_开头的用于malloc缓冲池的大小、uboot提示符、uboot下载文件时的默认地址、flash的其实地址等。 3.uboot的配置和编译: 添加目标板的信息到/boards.cfg: # Target ARCH CPU Boardname Vendor SoC Options webee210 arm armv7 webee210 samsung s5pc1xx make distclean #清除之前编译结果 make clean 修改/Makefile文件: unconfig: @rm -f $(obj)include/config.h $(obj)include/config.mk \ $(obj)board*/config.tmp \ $(obj)include/autoconf.mk $(obj)include/autoconf.mk.dep \ $(obj)board/$(VENDOR)/$(BOARD)/config.mk smart210_config: unconfig @$(MKCONFIG) $(@:_config=) arm armv7 smart210samsung s5pc1xx @echo"TEXT_BASE = 0xc3e00000" >$(obj)board/samsung/smart210/config.mk make smart210_config $(@:_config=)表示$@这个目标的_config换成空,得到开发板名称smart210. 执行make smart210_config实际上调用uboot根目录下mkconfig(注意这个脚本的权限)这个shell脚本,该脚本将开发板六个信息写入include/config.mk文件和include/config.h文件中. include/config.mk: ARCH = arm CPU =armv7 BOARD = smart210 VENDOR = samsung SOC =s5pc1xx OPTIONS = include/config.h: #define CONFIG_BOARDDIR board/samsung/smart210 #include #include #include #include 修改board/sumsung/smart210/Makefile 因为在这个文件夹添加了开发板相关的程序,所有需要修改相应的Makefile文件。 参考smdk2410的Makefile COBJS :=smart210.o arch/arm/config.mk已经配置好交叉编译: CROSS_COMPILE ?= arm-linux- arch/arm/cpu/armv7/u-boot.lds定义了起始地址和入口函数: . =0x00000000; . = ALIGN(4); .text : { arch/arm/cpu/armv7/start.o (.text) *(.text) } include/configs/smart210.h定义了定义了TEXT_BASE: #defineCONFIG_SYS_TEXT_BASE 0x23E00000 make 执行/Makefile文件,完成了uboot的编译。 生成以下的文件: u-boot.bin:二进制可执行文件可以直接烧写 u-boot.elf:elf格式的可执行文件 u-boot.srec:motorolas-record格式的可执行文件 u-boot.lds u-boot.map 4.烧写uboot到开发板的nand有两种方法: 第一、先烧写到SD卡, 注意手册给的sd卡的分区:(512b为一个block) 512b(保留区,0block)+8kb(BL1,1-16block)+16Kb(EN环境变量,17-48block)+512kb(BL2,也就是u-boot.bin,从49block开始)+linux内核+根文件系统 cat /proc/partitions #找出SD卡对应的设备,一般为/dev/sdb dmesg | tail sudo dd bs=512 if=/dev/zero of=/dev/sdbcount=2400 sudo dd bs=512 iflag=dsync oflag=dsync if=spl/smart210-spl.binof=/dev/sdb seek=1 sudo dd ba=512 iflag=dsync oflay=dsyncif=smart210-uboot.bin of=/dev/sdb seek=49 再使用uboot命令,烧写到nand: tftp 21000000 smart210-uboot.bin nand erase.chip nand write 21000000 0 3c1f4 第二、使用jtag直接烧写到nand中 5.uboot常用命令: bdinfo:打印目标板配置信息 flinfo:获取可用的flash信息 help:打印帮助信息 base:打印或设置地址偏移 crc:crc32的校验和计算,用于计算某一段存储区的校验和。 cmp:测试两个存储器区域是否相同。 cp:拷贝存储区。 md:存储区显示,显示某些区域的值。 mm:存储区修改,修改累加地址的值。 mtest:存储区测试,测试写操作是够成功,只能测试rom。 mw:内存填充, nm:内存修改,修改同一地址的值。 era:擦除flash存储器某个区域 erase all:擦除整个存储器 protect:使能或禁止flash保护功能,更改某一区域的只读属性。 bootm:从存数器启动应用程序镜像 go:开始某地址处的应用程序。 loadb:经由串口线加载二进制文件(kermit模式) tftpboot:使用tftp协议由网络加载映像文件 printenv:打印环境变量,ipaddr,hostname,netmask。 setenv:设置环境变量 saveenv:保存环境变量到存储器(sd和nand) bootm工作原理: 用于启动操作系统镜像,从镜像头获取操作系统类型,所使用的文件压缩方法,加载和入口点地址等信息。加载镜像文件到指定的存储器,甚至解压。也可以传递要求的启动参数并在入口点启动操作系统。第一个参数是待加载的映像的存储地址,之后可以添加操作系统需要的参数。 bootm用于linux操作系统: 传递一个可选的参数,作为initrd ramdisk映像的起始地址,bootm命令有三个步骤组成: 1.linux内核映像被解压缩并拷贝到DRAM 2.ramdisk映像被加载到DRAM 3.控制权交给linux内核,并传递ramdisk映像的位置和大小信息。 5.怎样用u-boot来启动linux内核(前提是内核已经烧写到nand) nand read 读入的内存目的地址 读入的nand的地址 读入的大小 bootm 内核的入口地址 |
|
来自: zhouADNjj > 《bootload》