u-boot启动分析
背景:Board →ar7240(ap93)Cpu →mips1、首先弄清楚什么是u-bootUboot是德国DENX小组的开发,它用于多种嵌入式CPU的bootloader程序, uboot不仅支持嵌入式linux系统的引导,当前,它还支持其他的很多嵌入式操作系统。
除了PowerPC系列,还支持MIPS,x86,ARM,NIOS,XScale。
2、下载完uboot后解压,在根目录下,有如下重要的信息(目录或者文件):以下为为每个目录的说明:Board:和一些已有开发板有关的文件。
每一个开发板都以一个子目录出现在当前目录中,子目录存放和开发板相关的配置文件。
它的每个子文件夹里都有如下文件(以ar7240/ap93为例):MakefileConfig.mkAp93.c 和板子相关的代码Flash.c Flash操作代码u-boot.lds 对应的链接文件common:实现uboot命令行下支持的命令,每一条命令都对应一个文件。
例如bootm命令对应就是cmd_bootm.ccpu:与特定CPU架构相关目录,每一款Uboot下支持的CPU在该目录下对应一个子目录,比如有子目录mips等。
它的每个子文件夹里都有入下文件:MakefileConfig.mkCpu.c 和处理器相关的代码sInterrupts.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代码作relocate5、初始化malloc、flash、pci以及外设(比如,网口)6、进入命令行或者直接启动Linux kernel刚一开始由于参考网上代码,我一个劲的对基于smdk2410的板子,arm926ejs的cpu看了N 久,启动过程和这个大致相同。
整个启动中要涉及到四个文件:Start.S →cpu/mips/start.SCache.S →cpu/mips/cache.SLowlevel_init.S →board/ar7240/common/lowlevel_init.SBoard.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 romReservedromExcHandle: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(这个调用的目的:当代码执行到这个时候,ddr ram还没有配置好,而如果直接调用C语言的函数必须完成栈的设置,而栈必定要在ram中。
所以,只有先把一部分cache拿来当做ram 用。
做法就是把一部分cache配置为栈的地址,锁定。
这样,当读写栈的内存空间时,只会访问cache,而不会访问真的ram地址了。
)这时,配置栈的地址,进行调用函数board_init_f(board.c)进入函数board_init_f后,首先做一些列的初始化:Timer_init 时钟初始化Env_init 环境变量初始化(取得环境变量存放的地址)Init_baudrate 串口速率Serial_init 串口初始化Console_init_f 配置控制台Display_banner 显示u-boot启动信息,版本号等。
Checkboard 执行board相关的操作Init_func_ram 初始化内存,配置ddr controller这一系列工作完成后,串口和内存都已经可以用了。
然后,就要把内存进行划分,在内存的最后一部分,留出u-boot代码大小的空间,准备把u-boot代码从flash搬移到这里。
然后,是堆的空间,malloc的内存就来自于这里。
紧接着放两个全局数据结构bd_infoglobal_data和环境变量boot_params。
最后,是栈的空间。
当内存划分好后,就准备进行relocate code了。
(relocate code含义:通常u-boot的执行代码肯定是在flash上(调试可以在ram上).当启动起来之后,要把它从flash 上搬移到ram里运行)但是,存在的问题是,flash地址和ram地址是不同的。
当我们把代码从flash搬移到ram中后,当执行函数跳转时,代码里的函数地址还是flash的地址,一跳,又重新跳回去了(跳回了flash)。
IPC(position-independent code) 由此引出了。
原理:当使用IPC方式时,在用gcc编译时需要加上-fpic的选项。
编译器会为你的可执行代码建立一个GOT(global offset table)的段。
一个地址在GOT表中有一项,里面存放地址的信息,在使用这个地址时,只要根据这个地址的编号(也可以叫做偏移量offset)找到表中相应的项目,就可以取得那个地址了。
而如果位置发生变化,只要对GOT 表中的地址进行修改就可以了。
例:Lw t9,1088(gp)Jalr t9这里,gp存放的就是GOT表的起始地址,而1088就是要调用函数offset,也就说GOT表的那个位置存放着它的地址。
Lw t9,1088(gp)把函数地址放入t9寄存器,然后调用就可以了。
Relocate code说简单一点就是:把u-boot的执行代码直接从flash里copy到ram的相应区域。
然后,把GOT表中的地址都加上一个偏移量,这个偏移量就是flash里的地址与ram里的地址差。
这里完成的操作还有一些其他工作,比如:设置新的栈指针,从flash代码里跳转到ram代码里等等.之后,进入board.c的board_init_r函数。
进入stage2。
Stage2:在board_init_f函数中初始化malloc,flash,pci以及外设(如:网口),最后进入命令行或者直接启动Linux Kernel.这样,u-boot的启动工作完成。
流程分析1、最开始系统加电。
ENTRY(_start)程序入口点是_start (原因参考u-boot.lds分析.doc)2、_start:cpu/mips/start.S3、la t9,board_init_f ;将函数board_init_f地址赋给t9寄存器J t9 ;程序调转到t9寄存器中保存的地址指向的指令注:(这里有点小疑问:代码运行到这里,pc指向的应该是cache中划分出来的临时ram?)a) board_inif_f() lib_mips/board.c 初始化外部内存relocate_code()回到cpu/mps/start.S中继续执行4、la t9,board_init_r cpu/mips/start.S 将函数board_init_r地址赋给t9寄存器J t9 跳转到t9寄存器中保存的地址指向的指令a) board_init_r()函数lib_mips/board.cb) main_loop()common/main.cs = getenv(“bootcmd”) 取得环境变量中的启动命令行,如:bootcmd = bootm 0xbf020000run_command(s,0); //执行这个命令行,即bootmc) do_bootm() command/cmd_bootm.c//printf(“##Booting image at %08lx…\n”,addr);5、bootm启动内核a) do_bootm_linux() lib_mips/mips_linux.c函数解析1、board_init_f()a)void board_init_f(ulong bootflag){For (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++ init_fnc_ptr){If ((*init_fnc_ptr)() != 0){Hang();}}}/*调用init_sequence函数队列,对板子进行一些初始化,详细见后面初始化external memory,初始化堆栈用cache作堆栈*/relocate_code(addr_sp,id,addr); //回到cpu/mips/start.S中/*NOTREACHED-relocate_code() does not return*/b)typedef int (init_fnc_t) (void);init_fnc_t * init_sequence[] ={/* Clx_board_init, //初始化GPIO,CPU速度,PLL,SDRAM等*/ Timer_init, //时钟初始化Env_init, //环境变量初始化Incaip_set_cpuclk, //根据环境变量设置CPU时钟Init_baudrate, //初始化串口波特率Serial_init, /* serial communicatioins setup */Console_init_f, //串口初始化,后面才能显示Display_banner, //在屏幕上输出一些显示信息Checkboard,Init_func_ram,NULL,};2、board_init_r()a)调用一些列的初始化函数b)初始化Flash设备c)初始化系统内存分配函数d)如果目标系统拥有NAND设备,则初始化NAND设备e)如果目标系统有显示设备,则初始化该类设备f)初始化相关网络设备,填写IP、MAC地址等g)进去命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作Void board_init_r(gd_t *id, ulong dest_addr){/*configure available FLASH banks*/ //配置可用的flash单元Size = flash_init(); //初始化flashDisplay_flash_config(size); //显示flash的大小/*initialize malloc() area*/Mem_malloc_init();Malloc_bin_reloc();Puts(“NAND”);Nand_init(); /*go init the NAND*/ //NAND初始化/*relocate environment function pointers etc.*/Env_relocate(); //初始化环境变量/*board MAC addresss*/S = getenv(“ethaddr”); //以太网MAC地址For (I = 0;I < 6; ++i){Bd->bi_enetaddr[i] = s?simple_strtoul(s,&e,16):0;If (s)S = (*e)?e + 1:e;}/*IP Address*/Bd->bi_ip_addr = getenv_IPaddr(“ipaddr”);Pci_init(); //pci初始化配置/**leave this here (after malloc(),environment and PCI are working **//*initialize devices*/Devices_init();Jumptable_init();/*initialize the console (after the relocation and deivces init)*/Console_init_t(); //串口初始化/miscellaneous platform dependent initialisationss/Misc_init_r();Puts(“Net”);Eth_initialize(gd->bd);/*main_loop() can return to retry autoboot,if so just run it again.*/For (;;){Main_loop();/*循环执行,试图自动启动,接受用户从串口输入的命令,然后进行相应的工作,设置延时时间,确定目标板是进入下载模式还是启动加载模式*/}/* NOTREACHED - no way out of command loop except booting */ }3、main_loop()void main_loop(void){S = getenv(“bootdelay”); //从环境变量中取得bootdelay内核等待延时Bootdelay = s ? (int)simple_strtol(s,NULL,10) : CONFIG_BOOTDELAY;Debug(“###main_loop entered:bootdelay = %d\n\n”, bootdelay);S = getenv(“bootcmd”); //从环境变量中取得bootcmd启动命令行/*例:bootcmd = tftp;bootm或者bootcmd = bootm 0xbf020000*/Char *s1 = getenv(“bootargs”); //从环境变量中取得bootargs启动参数Debug(“###main_loop:bootcmd = \”%s\”\n”, s ? s : “<UNDEFINED>”);Run_command(s, 0); //执行启动命令//手动输入命令For (;;){Len = readline(CFG_PROMPT); //读取键入的命令道CFG_PROMPT中Rc = run_command(lashcommand, flag); //执行这个命令}#endif /*CFG_HUSH_PARSER*/}4、do_bootm()int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])这个函数看着挺长的,作用是将内核解压缩,然后调用do_bootm_linux引导内核5、do_bootm_linux() lib_mips/mips_linux.c打印信息Starting kernel …Void do_bootm_linux(cmd_tbl_t * cmd tp, int flag, int argc, char *argv[],Ulong addr, ulong * len_ptr, int verify){Char * commandline = getenv(“bootargs”);theKernel =(void (*)(int ,char **, char **, int *)) ntohl(hdr->ih_ep);//hdr为指向image header的指针,hr->ih_ep就是我们用mkimage创建image时-e选项的参数:内核的入口地址Linux_params_init(UNCACHED_SDRAM(gd->bd->bi_boot_params),commandline);/*we assume that the kernel is in place*/Printf(“\nStarting kernel … \n\n”);theKernel(linux_argc, linux_argv, linux_env,0); //启动内核}u-boot向内核传递启动参数由一系列在include/configs.h中的宏控制,启动参数传递的地址在board_init中初始化。
U-BOOT启动过程
U-Boot启动过程U-Boot启动内核的过程可以分为两个阶段,两个阶段的功能如下:(1)第一阶段的功能Ø硬件设备初始化Ø加载U-Boot第二阶段代码到RAM空间Ø设臵好栈Ø跳转到第二阶段代码入口(2)第二阶段的功能Ø初始化本阶段使用的硬件设备Ø检测系统内存映射Ø将内核从Flash读取到RAM中Ø为内核设臵启动参数Ø调用内核1.1.1U-Boot启动第一阶段代码分析第一阶段对应的文件是cpu/arm920t/start.S和board/samsung/mini2440/lowlevel_init.S。
U-Boot启动第一阶段流程如下:图 2.1 U-Boot启动第一阶段流程根据cpu/arm920t/u-boot.lds中指定的连接方式:ENTRY(_start)SECTIONS{. = 0x00000000;. = ALIGN(4);.text :{cpu/arm920t/start.o (.text)board/samsung/mini2440/lowlevel_init.o (.text)board/samsung/mini2440/nand_read.o (.text)*(.text)}……}第一个链接的是cpu/arm920t/start.o,因此u-boot.bin的入口代码在cpu/arm920t/start.o中,其源代码在cpu/arm920t/start.S中。
下面我们来分析cpu/arm920t/start.S的执行。
1.硬件设备初始化(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以上代码设臵了ARM异常向量表,各个异常向量介绍如下:表 2.1 ARM异常向量表在cpu/arm920t/start.S中还有这些异常对应的异常处理程序。
基于S3C2440的U-boot启动分析
中北 大学信 息与 通信 工程 学院 洪永 学 余 红英
[ 要] 摘 在嵌入 式的世界 中 , 通常没有像 B O 那样 的固件程序 , IS 因此整 个嵌入式 系统的加栽就完全 由B o od r o t ae 来完成, l 所以B o— o t la e是嵌入 式京 统中不可缺 少的重要部分 , 文结合 u b o一 ..部分源代码详细地分析 U— o 启动过程 , o dr 本 — o t 116 Bo t 主要是对 U— o 启 Bo t 动的关键 环节进行较 为详 细的解析 , 其对 U— o t 目 B o在 标板 ¥ C 40 3 2 4 移植分析具有一定的借鉴价值。 [ 关键 词] o t ae U— 0 启动 移植 B ol dr o Bo t 给 内 核 , 代 码 如 下 : g 一 b 一 b a h n m e : d>d >i r — u br _c U B o, — ot全称 为 U iesl ot o dr 即通 用的 B ood r是遵循 MACH TYP S D 2 1 ; 始 化 串 口 函数 只要 是 sr l n , 置 了 nvra B o a e, L ot ae , l E M K4 0初 e a it i— i设 GL P 条款 的开发代码 , 的名字“ 它 通用” 具有两层含义 : 以引导 多种操 U T控制器 , c uam9 0 sc4 Osf .中实现 。 可 AR 在 p / 2f 32 x/e a c r i 1 作 系统 、 支持 多种架构 的 C U P 。它支持如 下操作 系统 :iu 、 e S 、 Lnx N t D B () 2 检测系统 内存映射( e o a ) m m r m p y V Wo s Q X R T S A T S , 持 如 下 C U架 构 : o e C x r 、 N 、 E M 、 RO 等 支 k P Pw r 、 P 对于特定 的开发板 , 内存 的分 布是明确 的, 以可 以直接设 置 , 其 所 o d m k 4 0 m k4 0 rs s e r it m n 函数指定 了开发板 的内存起 M P 、 8 、 R N I 等 。U B o支 持大 多数 C U, 以烧 写 E T 、 b a / d 2 1/ d2 1 .中的da _ i IS x6 A M、 O S — ot P 可 X 2 Y E S 文件系统 映像 , E F2 支持 串口下 载 , 网络下载 , 提供大量 的命令 , 始地址 , 并 代码如下 : it rm i t o ) n a d 相 对于 M z 司的V v, 的使用更复杂 , i公 i i 它 i 但是可 以用来更方便地 调试 n ( i iv d 、 程序 。本文针对 A M架构 中的 s d 2 1 开发板的 U B o启动进行详 R m k4 0 — ot { g > d >b da 0.at HY _ D AM一 ; d- b 一 i rm[]t =P S S R 细分析。 sr 1 g > d >b d m[ .z d一 b - i r O s e=P S S A 2U— o t 动 过 程 分 析 . B o启 a ]i HY _ DR M— — IE lSZ ; 通常 , ot ae 是 严重 地依 赖于硬 件 而实 现的 , 多数 的 B o B l dr o 大 ot — rtr : e u n0 l dr o e启动 过程 分为两个阶段 , a 本文 以开发板 s d 2 1 为例 , U B o m k 40 其 — ot ) 属于两阶段 的B o od r 一阶段 的文件为 cu r 9 0 s r 和 ba / ot ae , l 第 p / m 2 tt . o r a /aS d () 3 获取 U B o操作命 令 — ot s mdk 41  ̄o e e. 2 0 wlv 1 S。 启 动 U B o 后 可 以在 串 口看 到 一 些 打 印 信 号 , 后 会 出 现 — ot 随 2 — ot 一阶段分析 .U B o 1 第 ”MD 4 0#” S K20 字符等待用户输人命令来启动 内核 , 因此 U B o启动内 — ot () 1硬件设备初始化 核 的主要 核心是通 过 U B o命令来 实现 , — ot 在函数 s r a bo 中进行 t _r ot a m t 依次完 成如下设 置 : C U的工作模式设 置为管理 模式 (v ) 关 相 应 的 f s_ i 0 nn — i 等 函数 后 , 入 m i l p0 过 s 将 P sc , l h i t 和 ad i t a n n0 进 a _ o 通 no = 闭 看 门狗 ( T HD G) 设置 P L , L ,C K的 比例 , 闭 MMU gt v Iot d) WA C O , C KHC KF L 关 , en ( om ” e t c 获取U B o命令 , b — ot 然后通过 rn cm a d s0 u_ o m n ( ) , 执行命 cc A HE等 等 。 令, 最终启动内核 。U B o 中的每个命令都通过 u B O M 宏来定 — ot _O TC D 义, 格式如下 : () 2 为加载 B ood r ot ae 的第二段代码 到 R M空间 l A U BOOT C 所 谓 R M空 间 , 是 初始 化 内存芯 片 , 它能 够使 用 。通过 在 A 就 使 MDn m , xrs eetbecm n , sg””e ” (a emaag, p aal, ma d” ae , l ) r o u hp 各项参数的意义 如下 : s rS t t 中调用 l l e i t a. o e l n 函数来设置控制器 , 得外接 S R M。 w v_ i 使 D A L wl v l i t o e e n 部分函数代码 如下 : i ① nm : a e 命令 的名字 , 注意 , 它不是 一个字符 串( 不要 用双引号 括
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,再解析命令⾏。
U-Boot 启动流程分析与S3C2410上的移植
的命令 体 系 。U— o t 有 以太 网下 载程 序 、 Bo具 网络 启动 操 作 系统 、 烧写 f s l h等功 能 , a 是理 想 的 B ola e , o t d r将 o U— o 移植 到嵌 入式 开 发板上 可 提高 开发 效率 。 o B t
1 U— o t 动 流 程 分 析 bo 启
b o.d o t1s文件 用 来 设 置 U— o t中各 个 目标 文 件 的连 bo
引 导加 载 程序 ( o t a e ) B ol d r 点 之 一 , 同时 也 是 系统 运 行 的 基本 条
件 。 b o 是 当前 比较 流行 、 U—o t 功能 强大 的 B oL a e , o t o d r
它可 以支 持 多种 体 系结 构 的 处 理器 , 同时 提 供 了完备
S l a m/ o r . 和 u b o /o 、 b r b ad C i — o tc mmo / i. 。 面 n man c 下
因此 , 须通 知 编译 器 以使 其 知道 这个 入 口 , 工 必 该 作 可通 过修 改连 接器脚 本 文件 u b o .d —o t1s来 完成 。u —
图 1 U— B o届 动 代 码 沉 程 图 ot
开发 板上 电后 , 行 u b o 执 —o t的第 一 条 指 令 , 然后
一
st rt: a
顺 序 执行 ub o 启 动 函数 。 函数 调 用顺 序 如 图 1 —ot 所
示 。 b o 启 动 流程 主要 体现在 3个 文件上 , sat U—o t 即 tr.
维普资讯
第2 O卷
第 8期
电 脑 开 发 与 应 用
文 覃 纲 号 :0 35 5 2 0 )80 5—2 1 0 — 8 0( 0 7 0 — 0 3 0
u-boot源码分析之start.s分析
一、bootloader启动过程1、Stage1start.S代码结构(1)定义入口。
(2)设置异常向量(Exception Vector)。
(3)设置CPU的速度、时钟频率及终端控制寄存器。
(4)初始化内存控制器。
(5)将ROM中的程序复制到RAM中。
(6)初始化堆栈。
(7)转到RAM中执行,该工作可使用指令ldr pc来完成。
2、Stage2C语言代码部分(1)调用一系列的初始化函数。
(2)初始化Flash设备。
(3)初始化系统内存分配函数。
(4)如果目标系统拥有NAND设备,则初始化NAND设备。
(5)如果目标系统有显示设备,则初始化该类设备。
(6)初始化相关网络设备,填写IP、MAC地址等。
(7)进去命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。
3、U-Boot的启动顺序二、具体代码分析1.Stage1start.S代码结构1.1定义入口(u-boot.lds)ENTRY(_start)1.2设置异常向量1.3设置全局向量表地址变量和字节对齐方式1.4定义重定位全局变量1.5设置全局搬移地址(falsh->dram)1.6设置中断向量地址1.7设置cpu模式设置cpu工作模式为SVC模式。
1.4中断向量表搬移,时钟设置1.5CPU设置(TBL,icache,MMU)1.6板级初始化1.7boot镜像搬移到SDRAM1.8清除bss段计算出偏移地址:__rel_dyn_start 、__rel_dyn_start 、__dynsym_start1.9跳转到Stage2C 语言部分1.10中断处理程序File :arch/arm/lib/Board.cvoid board_init_r (gd_t *id,ulong dest_addr)。
u-boot-2019.06启动流程分析共26页文档
此文来源:赵春江老师的CNSD博客,希望帮到更多的人:/zhaocju-boot支持许多CPU,以及一些常见的开发板。
本文以u-boot-2019.06这个最新版本为例,简要介绍一下u-boot在smdk2410上的启动流程。
首先系统是从arch/arm/cpu/arm920t目录下的start.s文件开始执行,并且实际开始执行的代码是从第117行开始:117:start_code:118:/*119:* set the cpu to SVC32 mode120:*/121:mrs r0, cpsr122:bic r0, r0, #0x1f123:orr r0, r0, #0xd3124:msr cpsr, r0上述代码的含义是设置cpu为SVC32模式,即超级保护模式,用于操作系统使用。
140:#ifdef CONFIG_S3C24X0141:/* turn off the watchdog */142:143:# if defined(CONFIG_S3C2400)144:# define pWTCON 0x15300000145:# define INTMSK 0x14400008 /* Interupt-Controller base addresses */146:# define CLKDIVN 0x14800014 /* clock divisor register */148:# define pWTCON 0x53000000149:# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */ 150:# define INTSUBMSK 0x4A00001C151:# define CLKDIVN 0x4C000014 /* clock divisor register */152:# endif153:154:ldr r0, =pWTCON155:mov r1, #0x0156:str r1, [r0]157:158:/*159:* mask all IRQs by setting all bits in the INTMR - default160:*/161:mov r1, #0xffffffff162:ldr r0, =INTMSK163:str r1, [r0]164:# if defined(CONFIG_S3C2410)165:ldr r1, =0x3ff166:ldr r0, =INTSUBMSK167:str r1, [r0]169:170:/* FCLK:HCLK:PCLK = 1:2:4 */171:/* default FCLK is 120 MHz ! */172:ldr r0, =CLKDIVN173:mov r1, #3174:str r1, [r0]175:#endif /* CONFIG_S3C24X0 */该段代码的含义为,先定义几个需要的寄存器,然后关闭开门狗定时器,以及屏蔽所有中断和子中断,最后设置三个时钟频率之间的比值。
uboot启动流程
U-Boot工作过程U-Boot启动内核的过程可以分为两个阶段,两个阶段的功能如下:(1)第一阶段的功能硬件设备初始化加载U-Boot第二阶段代码到RAM空间设置好栈跳转到第二阶段代码入口(2)第二阶段的功能初始化本阶段使用的硬件设备检测系统内存映射将内核从Flash读取到RAM中为内核设置启动参数调用内核1.1.1 U-Boot启动第一阶段代码分析第一阶段对应的文件是cpu/arm920t/和board/samsung/mini2440/。
U-Boot启动第一阶段流程如下:图 U-Boot启动第一阶段流程根据cpu/arm920t/中指定的连接方式:ENTRY(_start)SECTIONS{. = 0x00000000;. = ALIGN(4);.text :{cpu/arm920t/ (.text)board/samsung/mini2440/ (.text)board/samsung/mini2440/ (.text)*(.text)}… …}第一个链接的是cpu/arm920t/,因此的入口代码在cpu/arm920t/中,其源代码在cpu/arm920t/中。
下面我们来分析cpu/arm920t/的执行。
1. 硬件设备初始化(1)设置异常向量cpu/arm920t/开头有如下的代码:.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以上代码设置了ARM异常向量表,各个异常向量介绍如下:表 ARM异常向量表在cpu/arm920t/中还有这些异常对应的异常处理程序。
U-boot的启动流程分析
sr tb
r ,J1 0 rl
。
网卡芯 片 :s 9 13 mc l 1 晶振 频 率 :1 M 0
TF LCD彩 屏 T
US s/D vc B Hot e ie
/ 设 定时 钟控 制寄 存 器 / 设置 C PU 速 度和 时 钟 频 率 ,调整时 钟 , 由低速 运行 进 入 高 速运 行 阶 段 。
—
—
s a t a m bo . tr r ot
_
2 2 第二阶段 ( 开发板与宿 主机之 间的 . 建立 通信) 进 入到 C 言的入 口函数s r amb o 语 t t r ot a (,此 函数 是整 个启 动 代码 中 C语 言的主 函 ) 数 , 整 个 U— ot 主 函数 , l r 还是 b o的 在 i am/ b b adC 定义 ,主要 完成工 作如 下 : o r .中 () 始化 本阶段 用到 的硬 件设 备 1 初 c u ii / p _nt /在 c u C () p . 中定义 ,主要 内 容为 i c eea l ) 指令 cc e c h n be 打开 a ( ah b a dii )/板 级初 始化 ,对 复用 I o r ̄nt / ( / 0端 口的各个 寄存 器进 行设置 e v ii ) /函数 初始化 环境 变量 ,此 n nt / ( 函数 在C rmo / n ls C Of n ev f h.中 l a itru tii ) / nerp—nt /设 置 中断控 制 器 ( 的特殊功 能寄 存器 so sl i ) / 设置 串 口的初始 化 。 c noe t An ( / dsl an r) / 显 示 U— o t i a b n e( / py TE CHNOLOOY N f FORMATI ON
am335xu-boot启动过程分析
am335xu-boot启动过程分析 u-boot属于两阶段的bootloader,第⼀阶段的⽂件为 arch/arm/cpu/armv7/start.S 和 arch/arm/cpu/armv7/lowlevel_init.S,前者是平台相关的,后者是开发板相关的。
1. u-boot第⼀阶段代码分析 (1)硬件设备初始化 将CPU的⼯作模式设为管理模式(SVC); 关闭中断; 禁⽤MMU,TLB ; 板级初始化; (2)为加载Bootloader的第⼆阶段代码准备RAM空间 加载u-boot.img,跳转到u-boot.img; 上述⼯作,也就是uboot-spl代码流程的核⼼。
代码如下:arch/arm/cpu/armv7/start.S1/*2 * the actual reset code3*/4reset:5 bl save_boot_params6/*7 * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,8 * except if in HYP mode already9*/10 mrs r0, cpsr11 and r1, r0, #0x1f @ mask mode bits12 teq r1, #0x1a @ test for HYP mode13 bicne r0, r0, #0x1f @ clear all mode bits14 orrne r0, r0, #0x13 @ set SVC mode15 orr r0, r0, #0xc0 @ disable FIQ and IRQ16 msr cpsr,r017@@ 以上通过设置CPSR寄存器⾥设置CPU为SVC模式,禁⽌中断18@@ 具体操作可以参考《[kernel 启动流程] (第⼆章)第⼀阶段之——设置SVC、关闭中断》的分析1920/* the mask ROM code should have PLL and others stable */21#ifndef CONFIG_SKIP_LOWLEVEL_INIT22 bl cpu_init_cp1523@@ 调⽤cpu_init_cp15,初始化协处理器CP15,从⽽禁⽤MMU和TLB。
海思uboot启动流程详细分析(一)
海思uboot启动流程详细分析(⼀)第⼀阶段 start.S⾸先我们可以在u-boot.lds中看到ENTRY(_start),即指定了⼊⼝_start,_start也就是整个start.S的最开始;1. reset在arch\arm\cpu\armv8\hi3559av100中的start.S注意x30在ARMV8中代表lr寄存器reset:/** Could be EL3/EL2/EL1, Initial State:* Little Endian, MMU Disabled, i/dCache Disabled*/adr x0, vectorsswitch_el x1, 3f, 2f, 1f3: msr vbar_el3, x0mrs x0, scr_el3orr x0, x0, #0xf /* SCR_EL3.NS|IRQ|FIQ|EA */msr scr_el3, x0msr cptr_el3, xzr /* Enable FP/SIMD */#ifdef COUNTER_FREQUENCYldr x0, =COUNTER_FREQUENCYmsr cntfrq_el0, x0 /* Initialize CNTFRQ */#endifb 0f2: msr vbar_el2, x0mov x0, #0x33ffmsr cptr_el2, x0 /* Enable FP/SIMD */b 0f1: msr vbar_el1, x0mov x0, #3 << 20msr cpacr_el1, x0 /* Enable FP/SIMD */0:/** Cache/BPB/TLB Invalidate* i-cache is invalidated before enabled in icache_enable()* tlb is invalidated before mmu is enabled in dcache_enable()* d-cache is invalidated before enabled in dcache_enable()*//** read system register REG_SC_GEN2* check if ziju flag*/ldr x0, =SYS_CTRL_REG_BASEldr w1, [x0, #REG_SC_GEN2]ldr w2, =0x7a696a75 /* magic for "ziju" */cmp w1, w2bne normal_start_flowmov x1, sp /* save sp */str w1, [x0, #REG_SC_GEN2] /* clear ziju flag */adr x0, vectors,其中的vectors代表了异常向量表主要做了如下事情:1)reset SCTRL寄存器具体可参考reset_sctrl函数,由CONFIG_SYS_RESET_SCTRL控制,⼀般不需要打开。
