ImageVerifierCode 换一换
格式:DOC , 页数:9 ,大小:88.50KB ,
资源ID:8987839      下载积分:10 金币
快捷注册下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

开通VIP
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.zixin.com.cn/docdown/8987839.html】到电脑端继续下载(重复下载【60天内】不扣币)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

开通VIP折扣优惠下载文档

            查看会员权益                  [ 下载后找不到文档?]

填表反馈(24小时):  下载求助     关注领币    退款申请

开具发票请登录PC端进行申请

   平台协调中心        【在线客服】        免费申请共赢上传

权利声明

1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。

注意事项

本文(u-boot启动分析.doc)为本站上传会员【pc****0】主动上传,咨信网仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知咨信网(发送邮件至1219186828@qq.com、拔打电话4009-655-100或【 微信客服】、【 QQ客服】),核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载【60天内】不扣币。 服务填表

u-boot启动分析.doc

1、背景: 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 inc

2、lude 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:与

3、特定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现在支持c

4、ramfs、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的工具,如:mki

5、mage等等。 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久,启动过程和这个大致相同。 整个启动中要涉及到四个文

6、件: 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.

7、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(romReser

8、ved,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

9、 这两个标记都构建了无意义的死循环。 通过_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 c

10、ode部分详细解释) 接下来执行lowlevle_init.S的lowlevel_init(la t9, lowlevel_init)函数,主要目的是工作频率配置,比如cpu的主频,总线(AHB),DDR 工作频率等。 然后执行cache.S中的mips_cache_reset(la t9, simple_mips_cache_reset)对cache进行初始化。接着调用mips_cache_lock(la t9, mips_cache_lock) (这个调用的目的:当代码执行到这个时候,ddr ram还没有配置好,而如果直接调用C语言的函数必须完成栈的设置,而栈必定要在ram中

11、所以,只有先把一部分cache拿来当做ram用。做法就是把一部分cache配置为栈的地址,锁定。这样,当读写栈的内存空间时,只会访问cache,而不会访问真的ram地址了。) 这时,配置栈的地址,进行调用函数board_init_f (board.c)进入函数board_init_f(la t9, board_init_f)后,首先做一些列的初始化: Timer_init 时钟初始化 Env_init 环境变量初始化(取得环境变量存放的地址) Init_baudrate 串口速率 Serial_init 串口初始化 Console_init_f 配置控制台 Di

12、splay_banner 显示u-boot启动信息,版本号等。 Checkboard 执行board相关的操作 Init_func_ram 初始化内存,配置ddr controller 这一系列工作完成后,串口和内存都已经可以用了。 然后,就要把内存进行划分,在内存的最后一部分,留出u-boot代码大小的空间,准备把u-boot代码从flash搬移到这里。 然后,是堆的空间,malloc的内存就来自于这里。 紧接着放两个全局数据结构bd_infoglobal_data和环境变量boot_params。 最后,是栈的空间。 当内存划分好后,就准备进行r

13、elocate code了。 (relocate code含义: 通常u-boot的执行代码肯定是在flash上(调试可以在ram上).当启动起来之后,要把它从flash上搬移到ram里运行 ) 但是,存在的问题是,flash地址和ram地址是不同的。当我们把代码从flash搬移到ram中后,当执行函数跳转时,代码里的函数地址还是flash的地址,一跳,又重新跳回去了(跳回了flash)。 IPC(position-independent code) 由此引出了。 原理: 当使用IPC方式时,在用gcc编译时需要加上-fpic的选项。编译器会为你的可执行代码建立一个GOT

14、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的执

15、行代码直接从flash里copy到ram的相应区域。 然后,把GOT表中的地址都加上一个偏移量,这个偏移量就是flash里的地址与ram里的地址差。 这里完成的操作还有一些其他工作,比如:设置新的栈指针,从flash代码里跳转到ram代码里等等. 之后,进入board.c的board_init_r函数。进入stage2。 Stage2: 在board_init_r函数中初始化malloc,flash,pci以及外设(如:网口),最后进入命令行或者直接启动Linux Kernel. 这样,u-boot的启动工作完成。 流程分析 1、 最开始系统加电。 E

16、NTRY(_start)程序入口点是_start (原因参考u-boot.lds分析.doc) 2、_start:cpu/mips/start.S 3、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中继续执行

17、 4、la t9,board_init_r cpu/mips/start.S 将函数board_init_r地址赋给t9寄存器 J t9 跳转到t9寄存器中保存的地址指向的指令 a) board_init_r() 函数 lib_mips/board.c b) main_loop() common/main.c s = getenv(“bootcmd”) 取得环境变量中的启动命令行, 如: bootcmd = bootm 0xbf020000 run_command(s,0); //执行这个命令行,即bootm c) do_bootm() co

18、mmand/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)() !=

19、 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_boa

20、rd_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,

21、 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

22、FLASH banks*/ //配置可用的flash单元 Size = flash_init(); //初始化flash Display_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.*/

23、 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初始化配置

24、/**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(); P

25、uts(“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

26、 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或者bootcm

27、d = bootm 0xbf020000 */ Char *s1 = getenv(“bootargs”); //从环境变量中取得bootargs启动参数 Debug(“###main_loop:bootcmd = \”%s\”\n”, s ? s : “”); Run_command(s, 0); //执行启动命令 //手动输入命令 For (;;) { Len = readline(CFG_PROMPT); //读取键入的命令道CFG_PROMPT中 Rc = run_command(lashcommand, flag); //执

28、行这个命令 } #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, ch

29、ar *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中初始化

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服