uboot注释
uboot 详细注释讲解(1)
大多数bootloader都分为stage1和stage2两部分,u-boot也不例外。
依赖于CPU体系结构的代码(如设备初始化代码等)通常都放在stage1且可以用汇编语言来实现,而stage2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。
1、Stage1 start.S代码结构u-boot的stage1代码通常放在start.S文件中,他用汇编语言写成,其主要代码部分如下:(1)定义入口。
由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本来完成。
(2)设置异常向量(Exception Vector)。
(3)设置CPU的速度、时钟频率及终端控制寄存器。
(4)初始化内存控制器。
(5)将ROM中的程序复制到RAM中。
(6)初始化堆栈。
(7)转到RAM中执行,该工作可使用指令ldr pc来完成。
2、Stage2 C语言代码部分lib_arm/board.c中的start arm boot是C语言开始的函数也是整个启动代码中C语言的主函数,同时还是整个u-boot(armboot)的主函数,该函数只要完成如下操作:(1)调用一系列的初始化函数。
(2)初始化Flash设备。
(3)初始化系统内存分配函数。
(4)如果目标系统拥有NAND设备,则初始化NAND设备。
(5)如果目标系统有显示设备,则初始化该类设备。
(6)初始化相关网络设备,填写IP、MAC地址等。
(7)进去命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。
3、U-Boot的启动顺序(示例,其他u-boot版本类似)cpu/arm920t/start.S@文件包含处理#include <config.h>@由顶层的mkconfig生成,其中只包含了一个文件:configs/<顶层makefile中6个参数的第1个参数>.h#include <version.h>#include <status_led.h>/********************************************************** ****************** Jump vector table as in table 3.1 in [1]********************************************************** *****************/注:ARM微处理器支持字节(8位)、半字(16位)、字(32位)3种数据类型@向量跳转表,每条占四个字节(一个字),地址范围为0x0000 0000~@0x0000 0020@ARM体系结构规定在上电复位后的起始位置,必须有8条连续的跳@转指令,通过硬件实现。
uboot笔记uboot命令分析+实现
uboot笔记uboot命令分析+实现uboot笔记:uboot命令分析+实现Ubootuboot命令分析+实现先贴⼀个重要结构,位于uboot/include/command.h,这个结构代表每个uboot命令struct cmd_tbl_s {char *name; /* Command Name */int maxargs; /* maximum number of arguments*/int repeatable;/* autorepeat allowed? *//* Implementation function */int (*cmd)(struct cmd_tbl_s *, int, int, char *[]);char *usage; /* Usage message (short)简短⽤法信息*/#ifdef CFG_LONGHELPchar *help; /* Help message (long) 长的帮助信息*/#endif#ifdef CONFIG_AUTO_COMPLETE/* do auto completion on the arguments */ int (*complete)(intargc, char *argv[], charlast_char, intmaxv, char *cmdv[]); #endif};typedefstruct cmd_tbl_s cmd_tbl_t;============================================================uboot的第⼀阶段:硬件相关初始化0.reset执⾏arm920t/start.s 过程如下1.设置cpu svc管理模式2.关看门狗中断,mmu等3.设置时钟,sdram,外部总线4.代码重定位,搬运代码,从flash到sdram5.设置栈,bss段清零, bss⽤于未初始化的全局变量和静态变量6.ldr pc, _start_armboot即进⼊uboot启动的第⼆阶段,调⽤c函数start_armboot()从start_armboot开始经过⼀系列外设初始化⽐如falsh_initnand_init...最后循环调⽤mian_loop()main_loop主要流程{1. ⽣成环境变量mtdparts, 调⽤mtdparts_init2. 在启动过程中若⽆空格键按下则boot_zImage,即run_command(getenv("bootcmd"),0)有空格键按下则run_command("menu",0)3. shell过程,读取⽤户的输⼊并执⾏相应的命令{从控制台获得命令,保存在全局变量comsole_buffer中解析命令⾏字符串,分割命令与参数,最后执⾏run_command(...); }}也就是说在mian_loop中,是处理环境变量和控制台⼈机交互,mian_loop调⽤readline ()读取命令⾏到console_buffer,再把console_buffer复制到lastcommand中去,还要设置flag,最后调⽤run_command (lastcommand, flag)函数,run_command (lastcommand, flag)函数中,⾸先定义cmd_tbl_t *cmdtp,再解析命令⾏。
uboot命令使用教程(uboot参数设置)
uboot命令使⽤教程(uboot参数设置)1. Printenv 打印环境变量。
uboot> printenvbaudrate=115200ipaddr=192.168.0.111ethaddr=32:34:46:78:9A:DCserverip=192.168.0.100Environment size: 80/8188 bytes2. Setenv 设置新的变量如:uboot> setenv myboard AT91RM9200DKuboot> saveenvuboot> printenvbaudrate=115200ipaddr=192.168.0.111ethaddr=32:34:46:78:9A:DCserverip=192.168.0.100myboard=AT91RM9200DKEnvironment size: 102/8188 bytes⼜如想重置启动参数bootargs:uboot> setenv bootargs 'noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0'uboot> saveenv3. saveenv 保存变量命令将当前定义的所有的变量及其值存⼊ flash 中。
⽤来存储变量及其值的空间只有 8k 字节,应不要超过。
(如上例,每次与setenv配合使⽤)4. loadb 通过串⼝ Kermit 协议下载⼆进制数据。
5. tftp 通过⽹络下载程序,需要先设置好⽹络配置简单配置:uboot> setenv ethaddr 32:34:46:78:9A:DCuboot> setenv ipaddr 192.168.0.111uboot> setenv serverip 192.168.0.100//下载 bin ⽂件到地址 0x20000000 处。
7.uboot基础知识(1)
在这种模式下,BootLoader将通过串口或网口从主机下载程序到 目标机。例如,下载内核映像,根文件系统映像,应用程序等。
2. u-boot简介
u-boot是由德国DENX小组开发的BootLoader,其全称是Universal Boot Loader。
u-boot的开发目标是支持尽可能多的嵌入式处理器和嵌入式操作系统, 它目前已支持数百种嵌入式开发板和各种CPU,包括ARM, PowerPC, MIPS, X86, Coldfire等,同时还支持Linux,NetBSD,VxWorks等多种嵌入 式操作系统的引导。
进入Ubuntu Linux操作系统的 图形化界面。
打开桌面上的【终端】,进入命令行界面。到/home/cvtech/目录 下,查看u-boot-s5pv210源代码。
在u-boot-s5pv210文件夹中包含的目录说明如下: board:目标板相关文件,主要包含SDRAM、Flash驱动。 common:独立于处理器体系结构的通用代码,如内存大小检测与故障检
除此之外,uboot还有内存操作命令、nand flash操作命令等。 内存操作命令
cmp:内存比较命令。 cp: 内存拷贝命令。 md: 内存显示命令。 mw: 内存填充命令。 mtest:内存测试命令。 Nand flash操作命令 nand info:查看nand flash芯片信息命令。 nand erase:nand flash擦除命令。 nand scrub: nand flash擦除命令,会将坏块信息也擦除掉。 nand read:nand flash读命令。 nand write:将数据从SDRAM写入nand flash。 nand ecc:设置nand flash的ecc校验方法。
U-boot命令详解
常用的U-boot命令详解帮助与环境变量U-boot发展到现在,他的命令行模式已经非常接近Linux下的shell了,在我编译的U-boot-2009.11中的命令行模式模式下支持“Tab”键的命令补全和命令的历史记录功能。
而且如果你输入的命令的前几个字符和别的命令不重复,那么你就只需要打这几个字符即可,比如我想看这个U-boot的版本号,命令就是“ version”,但是在所有的命令中没有其他任何一个的命令是由“v”开头的,所以只需要输入“v”即可。
TX-2440A> versionU-Boot 1.1.6 (Jan 18 2010 - 10:05:35)TX-2440A> vU-Boot 1.1.6 (Jan 18 2010 - 10:05:35)TX-2440A> baseBase Address: 0x00000000TX-2440A> baBase Address: 0x00000000由于U-boot支持的命令实在太多,一个一个细讲不现实,也没有必要。
所以下面我挑一些烧写和引导常用命令介绍一下,其他的命令大家就举一反三,或者“help”吧!(1)获取帮助命令:help 或?功能:查看当前U-boot版本中支持的所有命令。
T X-2440A>h e l p?-a l i a s f o r'h e l p'a u t o s c r-r u n s c r i p t f r o m m e m o r yb a s e-p r i n t o r s e t a d d r e s s o f f s e tb d i n f o-p r i n t B o a r d I n f o s t r uc t u r eb o o t-b o o t d e f a u l t,i.e.,r u n'b o o tc m d'b o o t_n o o s-b o o t U s e r P r o g r a mb o o t_z I m a g e-b o o t L i n u x's z I m a g eb o o t d-b o o t d e f a u l t,i.e.,r u n'b o o tc m d'b o o t e l f-B o o t f r o m a n E L F i m a g e i n m e m o r yb o o t m-b o o t a p p l ic a t i o n i m a g e f r o m m e m o r yb o o t p-b o o t i m a g e v i a n e t w o r k u s i n g B o o t P/T F T P p r o t oc o lb o o t v x-B o o t v x W o r k s f r o m a n E L F i m a g ec h p a r t-c h a n g e a c t i v e p a r t i t i o nc m p-m e m o r y c o m p a r ec o n i n f o-p r i n t c o n s o l ede v i c e s a n d i nf o r m a t i o nc p-m e m o r y c o p yc r c32-c h e c k s u m c a l c u l a t i o nd a t e-ge t/s e t/r e s e t d a t e&t i m ed c a c h e-e n a b l e o r d i s a b l e d a t a c a c h ee c h o-e c h o a r g s t o c o n s o l ee r a s e-e r a s e F L A S H m e m o r yf l i n f o-p r i n t F L A S H m e m o r y i n f o r m a t i o nf s i n f o-p r i n t i n f o r m a t i o n a b o u t f i l e s y s t e m sf s l o a d-l o a d b i n a r y f i l e f r o m a f i l e s y s t e m i m ag eg o-s t a r t a p p l i c a t i o n a t a d d r e s s'a d d r'h e l p-p r i n t o n l i n e h e l pi c a c h e-e n a b l e o r d i s a b l e i n s t r u c t i o n c a c h ei m i n f o-p r i n t h e a d e r i n f o r m a t i o n f o r a p p l i c a t i o n i m a g ei t e s t-r e t u r n t r u e/f a l s e o n i n t e g e r c o m p a r el o a d b-l o a d b i n a r y f i l e o v e r s e r i a l l i n e(k e r m i t m o d e) l o a d s-l o a d S-R e c o r d f i l e o v e r s e r i a l l i n el o a d x-l o a d b i n a r y f i l e o v e r s e r i a l l i n e(x m o d e m m o d e)l o a d y-l o a d b i n a r y f i l e o v e r s e r i a l l i n e(y m o d e m m o d e) l o o p-i n f i n i t e l o o p o n a d d r e s s r a n g el s-l i s t f i l e s i n a d i r e c t o r y(d e f a u l t/)m d-m e m o r y d i s p l a ym e n u-d i s p l a y a m e n u,t o s e l e c t t h e i t e m s t o d o s o m e t h i n g m m-m e m o r y m o d i f y(a u t o-i n c r e m e n t i n g)m t d p a r t s-d e f i n e f l a s h/n a n d p a r t i t i o n sm t e s t-s i m p l e R A M t e s tm w-m e m o r y w r i t e(f i l l)n a n d-N A N D s u b-s y s t e mn b o o t-b o o t f r o m N A N D d e v i c en m-m e m o r y m o d i f y(c o n s t a n t a d d r e s s)p i n g-s e n d I C M P E C H O_R E Q U E S T t o n e t w o r k h o s tp r i n t e n v-p r i n t e n v i r o n m e n t v a r i a b l e sp r o t e c t-e n a b l e o r d i s a b l e F L A S H w r i t e p r o t e c t i o nr a r p b o o t-b o o t i m a g e v i a n e t w o r k u s i n g R A R P/T F T P p r o t o c o l r e s e t-P e r f o r m R E S E T o f t h e C P Ur u n-r u n c o m m a n d s i n a n e n v i r o n m e n t v a r i a b l es a v e e n v-s a v e e n v i r o n m e n t v a r i a b l e s t o p e r s i s t e n t s t o r a g e s e t e n v-s e t e n v i r o n m e n t v a r i a b l e ss l e e p-d e l a y e x e c u t i o n f o r s o m e t i m et f t p b o o t-b o o t i m a g e v i a n e t w o r k u s i n g T F T P p r o t o c o lu s b s l a v e-g e t f i l e f r o m h o s t(P C)v e r s i o n-p r i n t m o n i t o r v e r s i o n如果你想获取某条命令的更详细的帮助,可以使用:help <你想要查的指令>或者?<你想要查的指令>,甚至h <你想要查的指令缩写>。
联咏方案uboot
联咏方案uboot1. 联咏方案概述联咏方案(LinkIt)是联发科(MediaTek)推出的一套物联网(IoT)解决方案,包括硬件和软件。
其中,uboot(universal bootloader)是一款开源的引导加载程序,用于启动嵌入式系统。
uboot作为硬件平台和操作系统之间的桥梁,具备了丰富的功能,包括启动系统、烧录固件、设置环境变量等。
联咏方案的uboot是经过定制和优化的,以适应联咏方案的特点和需求。
本文档将介绍联咏方案的uboot的基本使用方法和常见功能,帮助开发者更好地利用uboot来开发和调试联咏方案的嵌入式系统。
2. uboot的基本使用方法2.1 编译uboot在开始使用uboot之前,需要先编译uboot源代码。
联咏方案提供了uboot的源代码和编译工具链。
以下是编译uboot的基本步骤:1.下载uboot源代码,并解压到本地目录。
2.进入uboot源代码目录,执行以下命令配置编译选项:make menuconfig3.在配置界面中,根据目标设备的特点进行配置,如处理器架构、存储设备等。
4.保存配置并退出配置界面。
5.执行以下命令编译uboot:make6.编译成功后,生成可执行文件u-boot.bin。
2.2 烧录uboot烧录uboot到目标设备的闪存中,可以使用烧录工具,如OpenOCD、J-Link等。
以下是烧录uboot的基本步骤:1.将目标设备与烧录工具连接,确保连接正常。
2.执行以下命令烧录uboot:make flash3.等待烧录完成。
2.3 uboot交互界面在uboot启动后,会进入uboot的交互界面。
通过该界面,可以执行各种uboot命令。
以下是uboot交互界面的基本命令:•help:显示所有可用的uboot命令及其说明。
•printenv:显示当前uboot的环境变量。
•setenv:设置uboot的环境变量。
•saveenv:保存uboot的环境变量。
uboot常用命令
U-Boot(Universal Bootloader)是一款常用的开源引导加载程序,用于嵌入式系统的启动 和管理。以下是一些常用的 U-Boot 命令示例:
1. printenv :打印环境变量列表。
2. setenv <variable> <value> :设置环境变量的值。
8. mw <addr> <value> [<length>] :将指定的十六进制数值写入到指定的内存地址。
9. mmc list :显示支持的 MMC 存储设备列表。
10. tftpboot <addr> <filename> :通过 TFTP 协议从网络下载一个文件到指定的内存 地址。
11. fatls <interface> <partition> :列出指定接口(如 mmc、usb 等)上指定分区 中的文件列表。
3. saveenv :保存环境源自量到存储设备中,以便下次启动时使用。
4. boot :启动操作系统,根据环境变量中的配置来加载内核镜像和根文件系统。
5. bootm :直接从指定的内存地址启动指定的内核镜像。
6. help :显示帮助信息,列出可用的 U-Boot 命令和它们的功能说明。
7. md <addr> <length> :在指定的内存地址处以十六进制格式显示指定长度的数据。
12. run <script> :运行一个预定义的 U-Boot 脚本。
13. reset :重启设备。
这些命令只是 U-Boot 中的一部分,U-Boot 还提供了很多其他的命令和功能来管理和配 置系统。请注意,具体可用的命令和支持的功能取决于 U-Boot 版本以及不同的硬件平台 和配置。在实际使用时,您可能需要参考特定版本的 U-Boot 的文档或提供的帮助信息来 获取更详细和准确的命令列表和说明。
BOOT详解
1 U-Boot简介U-Boot,全称Universal BootLoader,是遵循GPL条款的开放源码项目。
从FADSROM、8xxROM、PPCBOOT逐步发展演化而来。
其源码目录、编译形式与Linux内核很相似,事实上,不少U-Boot源码就是相应的Linux内核源程序的简化,尤其是一些设备的驱动程序,这从U-Boot源码的注释中能体现这一点。
但是U-Boot不仅仅支持嵌入式Linux系统的引导,当前,它还支持NetBSD,VxWorks, QNX, RTEMS, ARTOS,LynxOS嵌入式操作系统。
其目前要支持的目标操作系统是OpenBSD, NetBSD,FreeBSD,4.4BSD, Linux, SVR4, Esix, Solaris, Irix, SCO, Dell, NCR,VxWorks, LynxOS, pSOS, QNX, RTEMS,ARTOS。
这是U-Boot中Universal的一层含义,另外一层含义则是U-Boot除了支持PowerPC系列的处理器外,还能支持MIPS、x86、ARM、NIOS、XScale等诸多常用系列的处理器。
这两个特点正是U-Boot 项目的开发目标,即支持尽可能多的嵌入式处理器和嵌入式操作系统。
就目前来看,U-Boot 对PowerPC系列处理器支持最为丰富,对Linux的支持最完善。
其它系列的处理器和操作系统基本是在2002年11月PPCBOOT改名为U-Boot后逐步扩充的。
从PPCBOOT向U-Boot 的顺利过渡,很大程度上归功于U-Boot的维护人德国DENX软件工程中心WolfgangDenk[以下简称W.D]本人精湛专业水平和持着不懈的努力。
当前,U-Boot项目正在他的领军之下,众多有志于开放源码BOOTLOADER移植工作的嵌入式开发人员正如火如荼地将各个不同系列嵌入式处理器的移植工作不断展开和深入,以支持更多的嵌入式操作系统的装载与引导。
uboot 命令详解
u-boot 技术文档1.U boot 命令详解1.1查看帮助命令使用help 或者?1.2环境变量打印环境变量:printenv设置环境变量:setenv(不会保存)保存环境变量:saveenv这个时候就有了1.3nandflash命令使用nand查看nandflash 所有指令擦除nand erase1.4norflash命令查看Flash信息命令: flinfo加/解写保护命令: protect擦除命令: erase1.5内存命令nm1.5USB指令使用help usb 查看usb具体指令使用usb 启动使用usb tree查看信息f atls usb 0 罗列u盘信息1.5.1实例演练usb指令烧写1.6实例演练ftp指令烧写环境变量中体现了开发板上的IP地址为192.168.0.2,网关为192.168.0.1,要求电上的tftp 服务器的IP为192.168.0.1;运行电脑上tftp服务器,指定好根目录,将内核和根文件系统放在根目录下。
注:线接上后,电脑上的本地连接可能是显示网络电缆没插好,这很正常!在使用过程中它们会自动去连接!<2>分别下载内核和根文件系统到内存0x30008000开始的空间先检查坏块nand bad再擦除坏块清理某个区域0x560000 0x3b22c00将根文件系统加载到0x30008000然后再将根文件系统写到0x560000 0x3b22c00这个位置然后重启:重复上面的步骤:nand erase 0x60000 0x267000将内核文件保存到0x60000 0x267000这块区域运行1.8系统重启指令2.U boot 内核移植在cpu/arm920t/start.S中添加以下代码在修改并添加为以下代码在include/configs/mini2440.h修改为如下:将以下代码修改为:将以下代码修改为:将以下代码修改为:在drivers/mtd/nand/s3c2410_nand.h 在最后下面代码上添加如下带码:。
uboot分析和笔记
uboot一、uboot是ppcboot和armboot合并而成,现在主流的bootloader为uboot和redboot二、bootm addr_kernel addr_initrd三、移植uboot时最好(一定)要找到一个自己板子的原形(即自己的板子是在这个板子上做一些修改而来的)的版本,这样就可以事半功倍。
这样要修改的地方就比较少,也比较容易了。
uboot支持很多平台,与一个具体平台相关的主要有三个地方:1、./include/configs/xxxxx.h, 主要定义了flash、sdram的起始地址等信息,一般要修改flash的起始地址、大小,有时候会有位宽等。
2、./board/xxxxx/*,这个目录下主要有两三个.c文件,主要为该平台的初始化和flash操作的函数。
有时候flash的操作需要修改,不过一般都是找一个现有的支持该flash的驱动,一般情况在uboot 别的./board/平台下就会有现成的,拷贝过了就可以了。
3、./cpu/xxxxxx/arch_xxx/xxxxxx/*, 一般是此cpu的初始等函数。
四、具体移植的时候最多涉及到的会是./include/configs/xxxx.h,如果有现成的平台(uboot现在支持绝大部分我们常用的平台),可能只需要对着原来的xxxx.h文件,修改几个我们在硬件上修改了的地方,一般会是flash的起始地址、大小;内存大小(内存的起始地址应该都是0);uboot设置信息保存的地址和长度;console 口和它的波特率;默认的设置;uboot的入口地址等(具体情况可能会有一些变化),如果不是从相同的平台移植,可能会比较麻烦,因为这时候要修改一些和此cpu相关的一些寄存器、频率和内存等硬件方面的东西了(也在这个xxxx.h中),虽然这时改动的地方也不多,但是会很痛苦,因为经常不知道要改哪里或者改为多少。
所以可能需要参考cpu的datasheet和到网上找一些资料了并且慢慢试了。
经典=Uboot-4-启动流程-代码注释
U-Boot启动第一阶段代码分析:(1)设置异常向量(cpu/arm920t/start.S).globl _start_start: b start_code /*复位*/ldr pc, _undefined_instruction /*未定义指令向量*/ldr pc, _software_interrupt /*软件中断向量*/ldr pc, _prefetch_abort /*预取指令异常向量*/ldr pc, _data_abort /*数据操作异常向量*/ldr pc, _not_used /*未使用*/ldr pc, _irq /*irq中断向量*/ldr pc, _fiq /*fiq中断向量*//*中断向量表入口地址*/_undefined_instruction: .word undefined_instruction_software_interrupt: .word software_interrupt_prefetch_abort: .word prefetch_abort_data_abort: .word data_abort_not_used: .word not_used_irq: .word irq_fiq: .word fiq.balignl 16,0xdeadbeef(2)CPU进入SVC模式(cpu/arm920t/start.S)start_code:/*set the cpu to SVC32 mode*/mrs r0, cpsrbic r0, r0, #0x1f /*工作模式位清零*/orr r0, r0, #0xd3 /*工作模式位设置为“10011”(管理模式),并将中断禁止位和快中断禁止位置1 */msr cpsr, r0(3)设置控制寄存器地址(cpu/arm920t/start.S)# if defined(CONFIG_S3C2400)# define pWTCON 0x15300000# define INTMSK 0x14400008# define CLKDIVN 0x14800014#else /* s3c2410与s3c2440下面4个寄存器地址相同*/# define pWTCON 0x53000000 /* WATCHDOG控制寄存器地址 */# define INTMSK 0x4A000008 /* INTMSK寄存器地址 */# define INTSUBMSK 0x4A00001C /* INTSUBMSK寄存器地址 */# define CLKDIVN 0x4C000014 /* CLKDIVN寄存器地址 */# endif(4)关闭看门狗(cpu/arm920t/start.S)ldr r0, =pWTCONmov r1, #0x0str r1, [r0] /* 看门狗控制器的最低位为0时,看门狗不输出复位信号 */ (5)屏蔽中断(cpu/arm920t/start.S)/* mask all IRQs by setting all bits in the INTMR – default */mov r1, #0xffffffff /* 某位被置1则对应的中断被屏蔽 */ldr r0, =INTMSK /* 中断源寄存器 */str r1, [r0]# if defined(CONFIG_S3C2440)l dr r1, =0x7fffl dr r0, =INTSUBMSK /* 子中断源寄存器 */s tr r1, [r0]# endif(6)设置MPLLCON、PLLCON、CLKDIVN(cpu/arm920t/start.S)# if defined(CONFIG_S3C2440) 【这个变量在哪里定义?】#define MPLLCON 0x4C000004#define UPLLCON 0x4C000008l dr r0, =CLKDIVNm ov r1, #5s tr r1, [r0]l dr r0, =MPLLCONl dr r1, =0x7F021s tr r1, [r0]ldr r0, =UPLLCONl dr r1, =0x38022s tr r1, [r0]# else/* FCLK:HCLK:PCLK = 1:2:4 *//* default FCLK is 120 MHz ! */ldr r0, =CLKDIVNmov r1, #3str r1, [r0]#endifCPU上电几毫秒后,晶振输出稳定,FCLK=Fin(晶振频率),CPU开始执行指令。
1UBoot操作和常用命令-文档资料
tftp的安装和配置
• redhat9下载tftp-server-0.32-4.i386.rpm软件包
– rpm -ivh tftp-server-0.32-4.i386.rpm安装
• Fedora9下可以使用yum在线安装tftp-server
– yum install tftp-server
• 新建tftftproot – chmod -R 777 /var/tftproot
• tftp server 配置
– tftp server配置文件,/etc/xinetd.d/tftp
修改tftp配置文件
# default: off # description: The tftp server serves files using the trivial file transfer \ # protocol. The tftp protocol is often used to boot diskless \ # workstations, download configuration files to network-aware printers, \ # and to start the installation process for some operating systems. service tftp { disable = no //设置为no,开启服务 socket_type = dgram protocol = udp wait = yes user = root server = /usr/sbin/in.tftpd server_args = -s /var/tftproot -c //这里配置tftp服务器根目录,-c参数表示 可以写文件 per_source = 11 cps = 100 2 flags = IPv4 }
U-BOOT Makefile注释
首先要了解的当然是config目标比如:sm dk2410_config : unconfig@$(MKCONFIG) $(@:_config=) arm arm920t sm dk2410 sam sung s3c24x0依赖为unconfig,第二行开头的@,只是表明该行命令的输出将被抑制。
而$(MKCONFIG)变量则是要运行的命令,它是一个脚本文件,后面的是它的参数。
前面有变量MKCONFIG的定义:MKCONFIG := $(SRCTREE)/mkconfig而变量SRCTREE的定义则为:SRCTREE := $(CURDIR)而变量CURDIR是没有定义的,没有定义的话,也就是空,即指当前目录。
所以$(MKCONFIG)也就是源码根目录下的文件mkconfig它接受最多6个参数。
这个脚本文件创建头文件和配置链接。
Parameters: Target Architecture CPU Board [VENDOR] [SOC]$@是make的自动变量,标识规则的目标名。
即smdk2410_config。
$(@:_config=)意思就是$@ 中的“_config”替换为空,也就是删掉目标中“_config”这个子串。
这样看的话在配置时,执行make smdk2410_config实际上执行的是:./mkconfig smdk2410 arm arm920t smdk2410 samsung2s3c24x0其内容为:APPEND=no # Default: Create new config fileBOARD_NAME="" # Name to print in make outputTARGETS=""while [ $# -gt 0 ] ; docase "$1" in--) shift ; break ;;-a) shift ; APPEND=yes ;;-n) shift ; BOARD_NAME="${1%%_config}" ; shift ;;-t) shift ; TARGETS="`echo $1 | sed 's:_: :g'` ${TARGETS}" ; shift ;;*) break ;;esacdone###### "$#" 将扩展成传递给脚本的参数的数目### shift 将$*中的剩余的参数向左移动一个位置并减少$#的值1。
uboot下的fdt reserved-memory的定义-概述说明以及解释
uboot下的fdt reserved-memory的定义-概述说明以及解释1.引言1.1 概述概述部分的内容可以如下所示:概述U-Boot是一种广泛应用于嵌入式系统的开源引导加载程序。
它提供了一个灵活且可扩展的平台,用于引导和管理各种嵌入式设备。
在U-Boot 中,FDT(Flattened Device Tree)是一种用于描述硬件设备的数据结构。
通过使用FDT,我们可以在引导过程中动态配置硬件资源,如内存、设备节点等。
本文旨在探讨在U-Boot中的FDT reserved-memory的定义。
FDT reserved-memory是一种用于保留特定内存区域的机制。
在启动过程中,U-Boot可以通过配置FDT reserved-memory来指定需要被保留的内存区域,以供系统中其他组件使用。
这种机制在嵌入式系统中非常实用,特别是当我们需要在运行时划分内存空间时。
通过合理配置FDT reserved-memory,可以避免内存冲突和资源浪费,提高系统性能与稳定性。
接下来的章节将依次介绍U-Boot的简介、FDT的简介以及U-Boot 中的FDT reserved-memory。
在最后,我们将详细阐述FDT reserved-memory的定义,以帮助读者更好地理解和应用这一重要的概念。
通过对U-Boot下的FDT reserved-memory的定义的深入探讨,我们可以更好地了解如何在嵌入式系统中合理地管理和配置内存资源,优化系统性能与稳定性。
同时,本文也为进一步研究和应用U-Boot和FDT提供了有益的参考。
1.2文章结构文章结构部分的内容可以按照以下方式编写:1.2 文章结构本文将按照以下结构进行讲解:1. 引言1.1 概述1.2 文章结构1.3 目的2. 正文2.1 U-Boot简介2.2 FDT(Flattened Device Tree)简介2.3 U-Boot中的FDT reserved-memory2.4 FDT reserved-memory的定义3. 结论3.1 总结3.2 展望在引言部分,我们将对本文的主题进行概述,并介绍文章的结构和目的。
MIPSuboot代码注释
MIPSuboot代码注释MIPS U-Boot——by M.CUboot启动流程关中断设置kseg0no cache初始化gp指针lowlevel_init mips_cache_reset 设置kseg0cache mips_cache_lockBoard_init_f relocate_code Board_init_r启动内核根据CPU rate初始化外部时钟、内存初始化cachecache未初始化前不能用cache已初始化设置临时cache栈把uboot程序从flash搬到ram执行start.Smtc0zero, CP0_WATCHLO mtc0zero, CP0_WATCHHI 清除硬件数据断点,防止产生调试断点,导致程序停止。
芯片在复位后,某些寄存器的内容也许是你想要的结果,但是谁知道呢,为了保证准确无误,最好还是重新进行手动初始化mfc0k0, CP0_STATUSli k1, ~ST0_IEand k0, k1mtc0k0, CP0_STATUS禁止全局中断mtc0zero, CP0_CAUSE初始化异常寄存器,清除异常原因指示mtc0zero, CP0_COUNTmtc0zero, CP0_COMPARE初始化时钟寄存器,防止产生计数器中断li t0, CONF_CM_UNCACHEDmtc0t0, CP0_CONFIG设置kseg0区不经过cache。
cache需要先初始化才能使用。
bal1fnop.word_gp1:lw gp, 0(ra)bal分支调用,ra返回地址指向下下一条指令,即.word _gp把.word_gp的存储位置载入gp寄存器,即设置GOT表的起始位置la t9, lowlevel_init jalr t9nop 根据CPU rate初始化外部时钟、内存。
lowlevel_init函数定义见lowlevel_init.Sla t9, mips_cache_reset jalr t9nop 初始化高速缓存cache。
Uboot命令详解
U-Boot命令详解U-Boot还提供了更加周详的命令帮助,通过help命令还能够查看每个命令的参数说明。
由于研发过程的需要,有必要先把U-Boot命令的用法弄清楚。
接下来,根据每一条命令的帮助信息,解释一下这些命令的功能和参数。
1、bootmbootm [addr [arg ...]]- boot application image stored in memorypassing arguments ’arg ...’; when booting a Linux kernel,’arg’ can be the address of an initrd imagebootm命令能够引导启动存储在内存中的程式映像。
这些内存包括RAM和能够永久保存的Flash。
第1个参数addr是程式映像的地址,这个程式映像必须转换成U-Boot的格式。
第2个参数对于引导Linux内核有用,通常作为U-Boot格式的RAMDISK映像存储地址;也能够是传递给Linux内核的参数(缺省情况下传递bootargs环境变量给内核)。
2、bootpbootp [loadAddress] [bootfilename]bootp命令通过bootp请求,需要DHCP服务器分配IP地址,然后通过TFTP协议下载指定的文档到内存。
第1个参数是下载文档存放的内存地址。
第2个参数是要下载的文档名称,这个文档应该在研发主机上准备好。
3、cmpcmp [.b, .w, .l] addr1 addr2 count- compare memorycmp命令能够比较2块内存中的内容。
.b以字节为单位;.w以字为单位;.l以长字为单位。
注意:cmp.b中间不能保留空格,需要连续敲入命令。
第1个参数addr1是第一块内存的起始地址。
第2个参数addr2是第二块内存的起始地址。
第3个参数count是要比较的数目,单位按照字节、字或长字。
4、cpcp [.b, .w, .l] source target count- copy memorycp命令能够在内存中复制数据块,包括对Flash的读写操作。
uboot命令解释与运行分析
uboot命令解释与运行分析题记: 省略200字这一回来分析一下uboot中命令行的解释, 所以我们直接从main_loop开始分析.1. 从汇编阶段进入c阶段的第一个函数是start_xxx, 如/lib_unicore/board.c中的start_unicoreboot. 前半部分调用了若干初始化函数来进行部分硬件的初始化, 并设置一下环境. 这里不是我们本回要讨论的所以一一跳过. 在start_xxx的最后调用了main_loop(), 而且还是被一个死循环死死圈住了;2. 现在我们已经进入了这个圈套那么只能往里钻了. common/main.c文件中的main_loop().上面代码主要是对自启动部分的描述, 其中命令执行部分是在run_command中进行的, 这个等在后文分析. 如果我们没有bootcmd 或者在延时中被打断, 那么代码会继续向下执行3.read_line()读取到命令行后会调用common/main.c文件中的run_command().现在是分析run_command()的时候了,不管是从环境变量还是终端获得命令,都是由run_command()来处理的.中场休息,下面要进入处理cmdbuf的循环中了, 长征马上开始以;分割. 忽略'\;'for(inquotes = 0, sep = str;*sep; sep++){if((*sep=='\'')&&(*(sep-1)!='\\'))inquotes=!inquotes;if(!inquotes &&(*sep ==';')&&( sep != str)&&(*(sep-1)!='\\'))break;}//如果上面for循环找到一条以';'结束的命令, 那么sep指向命令末尾token = str;if(*sep){str = sep + 1;*sep ='\0';}elsestr = sep;process_macros (token, finaltoken);if((argc = parse_line (finaltoken, argv))== 0){rc =-1;4.就此打断一下, 我们要分析一下find_cmd了, 不能再跳过了. find_cmd()在.u_boot_cmd段中寻找该命令的cmd_tbl_t结构, 找到后返回该结构. 该命令的结构是通过定义在include/command.h中的宏定义U_BOOT_CMD登记进.u_boot_cmd段中的.5. 刚才我们在长征的半路翻越了一座雪山, 现在继续回到while循环中if(cmdtp->cmd == do_bootd){if(flag & CMD_FLAG_BOOTD){puts("'bootd' recursion detected\n");rc =-1;continue;}else{flag |= CMD_FLAG_BOOTD;}}#endif//长征马上结束, 胜利就在眼前! 调用结构体中注册的cmd函数, 何时注册的呢? 上面不远处介绍的U_BOOT_CMD!if((cmdtp->cmd)(cmdtp, flag, argc, argv)!= 0){ rc =-1;}repeatable &= cmdtp->repeatable;if(had_ctrlc ())return-1;}。
ubootmmc命令详解Nandflashuboot命令详解
ubootmmc命令详解Nandflashuboot命令详解
md指令
uboot下输⼊指令md,会提⽰md的⽤法,memory display,即内存显⽰。
b:8位
w:16位
l:32位(默认值)
⽰例:
上述0x10000000是要显⽰内存的那个地址,后⾯的数字是输出的个数,注意是16进制的。
直接输⼊md来显⽰,默认是以32位为单位输出。
mw指令
uboot下输⼊指令mw,会提⽰md的⽤法,memory write,即向内存中写⼊数据。
b\w\l的意思同上,address是要写⼊内存的地址,value是要写⼊的值,count是从address开始要写⼊多少个数,这些都是16进制数。
⽰例:
⽰例
在0x10000000地址内存的起始位置写⼊0x12345678,打印出内存的输出。
发现低位0x78是写在低地址0x10000000,⾼位0x12是写在⾼地址0x10000003上,也就是常说的⼩端模式(little endian),简单记忆:低低模式,即低位在低地址。
uboot中C语言代码入口函数(start_armboot)的注释
uboot中C语言代码入口函数(start_armboot)的注释//打印BANK的相关信息display_dram_config,NULL, //用以标识列表数组的结束};//------------start_armboot--------------------//功能: 完成uboot第二阶级的一系列的// 硬件初始化工作, 然后转入main函数.//备注: 该函数是C程序的入口函数,从汇编语// 言跳转到此 .//---------------------------------------------void start_armboot (void){init_fnc_t **init_fnc_ptr; //init_fnc_t 是各初始化函数的数组char *s;#ifndef CFG_NO_FLASHulong size;#endif#if defined(CONFIG_VFD) || defined(CONFIG_LCD)unsigned long addr;#endif/* Pointer is writable since we allocated a register for itgd_t: 定义在 /include/asm-arm/Global_data.h中,包含一些全局通用的变量._armboot_start: 代码的起始地址,它定义在start.S中的前几行中,定义为 _start 当系统第一次加电时,指令是从0x0地址开始执行的,所以此时的 _start值应为0x0;而当uboot经过代码重定位后,指令会从 _TEXT_BASE 处开始执行,此时的 _start值就成了 _TEXT_BASE的值.CFG_MALLOC_LEN: 在/include/configs/smdk2440.h中有定义,该变量表示供malloc函数使用的内存池空间,代码中定义值为:0x10000+128*1024|-------|<--- _armboot_start基址| 4 ||-------|<--- malloc函数池基址| 3 ||-------|<--- (gd_t)gd(全局变量表)基址| 2 ||-------|<--- (bt_t)bd(板卡信息表)基址| 1 |-------4 就是为malloc函数预留的数据空间3 是全信息表gd的数据区2 是板卡信息表bd的数据区网上找了个图片,更能反应这个空间的分配关系:*///分配区域 3 给 gd ,gd是一个全局静态变量gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));/* compiler optimization barrier needed for GCC >= 3.4 */__asm__ __volatile__("": : :"memory");//把gd变量的内容填充为0 ,填充 3 区的数据为0 ,即初始化gd表.注意:这里并没有 //初始化bd表,在gd表中的bd成员只是一个指针,因为对初始化的是个指针地址memset ((void*)gd, 0, sizeof (gd_t));/*bd_t 结构体在/include/asm-arm/U-boot.h中定义, 定义板子的一些信息,包括:波特率,IP地址, 以太网地址, 架构编码,启动参数 ,BANK的起始地址和大小等*///分配区域 2 给bd, bd的基址 = gd的基址 - bd的尺寸gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));//把区域 2 填充为 0 ,即初始化 bd 表memset (gd->bd, 0, sizeof (bd_t));/*monitor_falsh_len定义在 /lib_arm/Board.c在bin文件中 BSS 段和 TEXT 段和 DATA 段存放的顺序同前向后依次是:TEXT(代码段 RO) DATA(已初始化数据段 RW) BSS(未初始化数据段 ZI)所以 _bss_start 的基址等于 TEXT的长度加上DATA的长度.即: _bss_start(BSS段基址) = 代码段长度+数据段长度BSS(Block Started by Symbol)段是未被初始化的数据段,是存放程序中未被初始化的全局变量的一块内存区域,初始化时应清零;该段只有名称和大小却没有值;该段不包含任何数据,只是简单的维护开始和结束的地址,以便内存区能在运行时被有效地清零,它在应用程序的映像文件(ARM中也即bin文件)中并不存在.text :代码段,是包含程序代码的段dat :已经初始化的数据段,保存已经初始化的全局变量.在嵌入式系统中,bin文件(又称Image文件)中只包含text和data段,而bss段不在其中,它是由系统初始化为零.*///_armboot_start 在start.S中定义为_start,而_start为代码的起始地址//只包含 RO(TEXT) 和 RW(DATA) 段.重定位前的值为0x0,此时指向flash,//重定位后则指向RAM中的某一地址//由此可以知道: _bss_start - _armboot_start 的值即是在第一阶段从//flash中重定位到RAM中的那部分代码的长度,也即可TEXT和DATA数据段,//这个值与start.S中的重定位那部分代码所计算的值是相等的//所以,monitor_flash_len表示从flash中搬来的代码的长度monitor_flash_len = _bss_start - _armboot_start; //_bss_start 在u-boot.lds中定位//各设置的初始化.当返回值不为0时表示初始化失败 ,此时会调用 hang()函数//打印一错误提示信息,然后进入死循环for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {if ((*init_fnc_ptr)() != 0) {hang ();}}//CFG_NO_FLASH 表示没有flash,如果没定义该常量则表示板子上有flash,此时调用flash_init()对其进行初始化.#ifndef CFG_NO_FLASH/* configure available FLASH banks */size = flash_init ();display_flash_config (size); //打印flash的信息,这里仅输出它的大小#endif /* CFG_NO_FLASH */#ifdef CONFIG_VFD# ifndef PAGE_SIZE# define PAGE_SIZE 4096# endif/** reserve memory for VFD display (always full pages)*//* bss_end is defined in the board-specific linker script */addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); //???size = vfd_setmem (addr);gd->fb_base = addr;#endif /* CONFIG_VFD */#ifdef CONFIG_LCD# ifndef PAGE_SIZE# define PAGE_SIZE 4096# endif/** reserve memory for LCD display (always full pages)*///为LCD分配RAM(内存)空间/* bss_end is defined in the board-specific linker script */addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);size = lcd_setmem (addr);gd->fb_base = addr; //为显存缓冲区地址变量赋值#endif /* CONFIG_LCD *//* armboot_start is defined in the board-specific linker script *///malloc函数使用缓冲区的初始化mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);//如果定义了命令和NAND命令,则初始化nand#if (CONFIG_COMMANDS & CFG_CMD_NAND)puts ("NAND: ");nand_init(); /* go init the NAND */#endif#ifdef CONFIG_HAS_DATAFLASHAT91F_DataflashInit();dataflash_print_info();#endif/* initialize environment 环境的初始化,代码在common\env_common.c中 */env_relocate ();#ifdef CONFIG_VFD/* must do this after the framebuffer is allocated */drv_vfd_init();#endif /* CONFIG_VFD *//* IP Address 为全局变量的成员赋值:IP地址*/gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");//ipaddr在smdk2440.h中的CONFIG_IPADDR中出现,应该是该常量/* MAC Address *///高处MAC地址 ,并赋给gd的成员变量{int i;ulong reg;char *s, *e;char tmp[64];i = getenv_r ("ethaddr", tmp, sizeof (tmp));s = (i > 0) ? tmp : NULL;for (reg = 0; reg < 6; ++reg) {gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;if (s)s = (*e) ? e + 1 : e;}#ifdef CONFIG_HAS_ETH1i = getenv_r ("eth1addr", tmp, sizeof (tmp));s = (i > 0) ? tmp : NULL;for (reg = 0; reg < 6; ++reg) {gd->bd->bi_enet1addr[reg] = s ? simple_strtoul (s, &e, 16) : 0;if (s)s = (*e) ? e + 1 : e;}#endif}//这个函数涉及好多,我没深入分析,若哪位分析了希望能分享一下:cczy_english@,将不胜感激 devices_init (); /* get the devices list going. */#ifdef CONFIG_CMC_PU2load_sernum_ethaddr ();#endif /* CONFIG_CMC_PU2 *///初始化跳转表,对gd中的jt(函数跳转表)数组进行初始化,其中保存着一些函数的入口地址。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
以下用以记录uboot代码的分析过程,目标是s3c6410,如有错误,欢迎指正。
强调,内容与三星原厂提供的uboot-1.1.6有更改的地方,因为外接外设的区别,特别是nand_flash、外接网卡芯片和LCD芯片。
以下纯代码情景分析,请结合uboot的功能结构图和内存分布图查看代码,这样会更加容易理解。
s3c-u-boot-1.1.6源代码可以在三星下面的网站获得,但前提是你有官方的email。
还是百度一下吧功能结构图(上图) uboot内存分布图(上图)1.start.s代码分析(第一阶段)--------------------.globl _start_start: b resetldr pc, _undefined_instruction ldr pc, _software_interruptldr pc, _prefetch_abortldr pc, _data_abortldr pc, _not_usedldr pc, _irqldr pc, _fiq_undefined_instruction:.word undefined_instruction _software_interrupt:.word software_interrupt_prefetch_abort:.word prefetch_abort_data_abort:.word data_abort_not_used:.word not_used_irq:.word irq_fiq:.word fiq_pad:.word 0x12345678.global _end_vect_end_vect:.balignl 16,0xdeadbeef----------------------------------------_undefined_instruction:.word undefined_instruction _software_interrupt:.word software_interrupt_prefetch_abort:.word prefetch_abort_data_abort:.word data_abort_not_used:.word not_used_irq:.word irq_fiq:.word fiq_pad:.word 0x12345678.global _end_vect_end_vect:.balignl 16,0xdeadbeef----------------------------------------_TEXT_BASE:.word TEXT_BASE----------------------------------------_TEXT_PHY_BASE:.word CFG_PHY_UBOOT_BASE ----------------------------------------.globl _armboot_start_armboot_start:.word _start----------------------------------------.globl _bss_start_bss_start:.word __bss_start.globl _bss_end_bss_end:.word _end----------------------------------------reset:mrs r0,cpsrbic r0,r0,#0x1forr r0,r0,#0xd3msr cpsr,r0--------------------cpu_init_crit:----------------------------------------mov r0, #0mcr p15, 0, r0, c7, c7, 0mcr p15, 0, r0, c8, c7, 0----------------------------------------mrc p15, 0, r0, c1, c0, 0bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) orr r0, r0, #0x00000002 @ set bit 2 (A) Alignorr r0, r0, #0x00001000 @ set bit 12 (I) I-Cachemcr p15, 0, r0, c1, c0, 0----------------------------------------ldr r0, =0x70000000orr r0, r0, #0x13mcr p15,0,r0,c15,c2,4 @ 256M(0x70000000-0x7fffffff) ----------------------------------------bl lowlevel_init----------------------------------------ldr r0, =0xff000fffbic r1, pc, r0ldr r2, _TEXT_PHY_BASEbic r2, r2, r0cmp r1, r2beq after_copy--------------------#ifdef CONFIG_BOOT_NANDmov r0, #0x1000bl copy_from_nand#endif----------------------------------------#ifdef CONFIG_BOOT_MOVINANDldr sp, _TEXT_PHY_BASEbl movi_bl2_copyb after_copy#endif--------------------after_copy:--------------------#ifdef CONFIG_ENABLE_MMUenable_mmu:ldr r5, =0x0000ffffmcr p15, 0, r5, c3, c0, 0 @ load domain access registerldr r0, _mmu_table_baseldr r1, =CFG_PHY_UBOOT_BASEldr r2, =0xfff00000bic r0, r0, r2orr r1, r0, r1mcr p15, 0, r1, c2, c0, 0mmu_on:mrc p15, 0, r0, c1, c0, 0orr r0, r0, #1mcr p15, 0, r0, c1, c0, 0nopnopnopnop#endif----------------------------------------skip_hw_init:stack_setup:#ifdef CONFIG_MEMORY_UPPER_CODEldr sp, =(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0xc)#elseldr r0, _TEXT_BASEsub r0, r0, #CFG_MALLOC_LENsub r0, r0, #CFG_GBL_DATA_SIZE#ifdef CONFIG_USE_IRQsub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)#endifsub sp, r0, #12#endif----------------------------------------clear_bss:ldr r0, _bss_startldr r1, _bss_endmov r2, #0x00000000clbss_l:str r2, [r0]add r0, r0, #4cmp r0, r1ble clbss_l----------------------------------------ldr pc, _start_armboot_start_armboot:.word start_armboot--------------------2.第二阶段代码分析(代码在lib_arm目录下的board.c里面,start_armboot函数)1)初始化CPU及外围硬件init_fnc_t **init_fnc_ptr;char *s;#ifndef CFG_NO_FLASHulong size;#endif#if defined(CONFIG_VFD) || defined(CONFIG_LCD)unsigned long addr;#endif#if defined(CONFIG_BOOT_MOVINAND)uint *magic = (uint *) (PHYS_SDRAM_1);#endif#ifdef CONFIG_MEMORY_UPPER_CODEulong gd_base;gd_base = CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE - sizeof(gd_t); #ifdef CONFIG_USE_IRQgd_base -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);#endifgd = (gd_t*)gd_base;#elsegd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));#endif__asm__ __volatile__("": : :"memory");memset ((void*)gd, 0, sizeof (gd_t));gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));memset (gd->bd, 0, sizeof (bd_t));monitor_flash_len = _bss_start - _armboot_start;for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {if ((*init_fnc_ptr)() != 0) {hang ();}}解释:定义二级指针init_fnc_ptr指向一个存放函数指针的数组,init_fnc_ptr是typedef int (init_fnc_t) (void)类型,即函数类型,init_fnc_ptr可以指向一个没有参数,返回值为int型的函数指针的地址(很绕哦,呵呵),我们看上面代码最后的for循环init_fnc_ptr = init_sequence,if中会使用(*init_fnc_ptr)()方式调用init_sequence中的函数(函数名可以看为一个地址),如果返回值不是0,则执行hang报错。