uboot代码详细分析.pdf
《uboot代码详细分析.pdf》由会员分享,可在线阅读,更多相关《uboot代码详细分析.pdf(88页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、目录目录 u-boot-1.1.6 之 cpu/arm920t/start.s 分析.2 u-boot 中.lds 连接脚本文件的分析.12 分享一篇我总结的 uboot 学习笔记(转).15 U-BOOT 内存布局及启动过程浅析.22 u-boot 中的命令实现.25 U-BOOT 环境变量实现.28 1.相关文件.28 2.数据结构.28 3.ENV 的初始化.30 3.1env_init.30 3.2 env_relocate.30 3.3*env_relocate_spec.31 4.ENV 的保存.31 U-Boot 环境变量.32 u-boot 代码链接的问题.35 ldr 和 a
2、dr 在使用标号表达式作为操作数的区别.40 start_armboot 浅析.42 1.全局数据结构的初始化.42 2.调用通用初始化函数.43 3.初始化具体设备.44 4.初始化环境变量.44 5.进入主循环.44 u-boot 编译过程.44 mkconfig 文件的分析.47 从 NAND 闪存中启动 U-BOOT 的设计.50 引言.50 NAND 闪存工作原理.51 从 NAND 闪存启动 U-BOOT 的设计思路.51 具体设计.51 支持 NAND 闪存的启动程序设计.51 支持 U-BOOT 命令设计.52 结语.53 参考文献.53 U-boot 给 kernel 传参数
3、和 kernel 读取参数struct tag(以及补充).53 1、u-boot 给 kernel 传 RAM 参数.54 2、Kernel 读取 U-boot 传递的相关参数.56 3、关于 U-boot 中的 bd 和 gd.59 U-BOOT 源码分析及移植.60 一、u-boot工程的总体结构:.61 1、源代码组织.61 2.makefile 简要分析.61 3、u-boot 的通用目录是怎么做到与平台无关的?.63 4、smkd2410 其余重要的文件:.63 二、u-boot 的流程、主要的数据结构、内存分配.64 1、u-boot 的启动流程:.64 2、u-boot 主要的
4、数据结构.66 3、u-boot 重定位后的内存分布:.68 三、u-boot 的重要细节。.68 关于 U-boot 中命令相关的编程:.73 四、U-boot 在 ST2410 的移植,基于 NOR FLASH 和 NAND FLASH 启动。.76 1、从 smdk2410 到 ST2410:.76 2、移植过程:.76 3、移植要考虑的问题:.77 4、SST39VF1601:.77 5、我实现的 flash.c 主要部分:.78 6、增加从 Nand 启动的代码:.82 7、添加网络命令。.87 u-boot-1.1.6 之之 cpu/arm920t/start.s 分析分析 /*a
5、rmboot-Startup Code for ARM920 CPU-core *Copyright(c)2001 Marius Gr 鰃 er *Copyright(c)2002 Alex Z 黳 ke *Copyright(c)2002 Gary Jennejohn *See file CREDITS for list of people who contributed to this *project.*This program is free software;you can redistribute it and/or *modify it under the terms of th
6、e GNU General Public License as *published by the Free Software Foundation;either version 2 of *the License,or(at your option)any later version.*This program is distributed in the hope that it will be useful,*but WITHOUT ANY WARRANTY;without even the implied warranty of *MERCHANTABILITY or FITNESS F
7、OR A PARTICULAR PURPOSE.See the *GNU General Public License for more details.*You should have received a copy of the GNU General Public License *along with this program;if not,write to the Free Software *Foundation,Inc.,59 Temple Place,Suite 330,Boston,*MA 02111-1307 USA */#include#include /*Jump ve
8、ctor table as in table 3.1 in 1 */global 声明一个符号可被其他文档引用,相当于声明了一个全局变量,.globl 和.global 相同。/该部分为处理器的异常处理向量表。地址范围为 0 x0000 0000 0 x0000 0020,刚好 8 条指令。.globl _start /u-boot 启动入口 _start:b reset /复位向量并且跳转到 reset ldr pc,_undefined_instruction ldr pc,_software_interrupt ldr pc,_prefetch_abort ldr pc,_data_ab
9、ort ldr pc,_not_used ldr pc,_irq /中断向量 ldr pc,_fiq /中断向量 /.word 伪操作用于分配一段字内存单元(分配的单元都是字对齐的),并用伪操作中的 expr 初始化。.long 和.int 作用与之相同。_undefined_instruction:.word undefined_instruction _software_interrupt:.word software_interrupt _prefetch_abort:.word prefetch_abort _data_abort:.word data_abort _not_used:
10、.word not_used _irq:.word irq _fiq:.word fiq /.align 伪操作用于表示对齐方式:通过添加填充字节使当前位置满足一定的对齐方式。.balign 的作用同.align。/.align alignment,fill,max /其中:alignment 用于指定对齐方式,可能的取值为 2 的次幂,缺省为 4。fill 是填充内容,缺省用 0填充。max 是填充字节数最大值,假如填充字节数超过 max,/就不进行对齐,例如:/.align 4 /*指定对齐方式为字对齐*/.balignl 16,0 xdeadbeef /*Startup Code(res
11、et vector)*do important init only if we dont start from memory!*relocate armboot to ram *setup stack *jump to second stage */TEXT_BASE 在研发板相关的目录中的 config.mk 文档中定义,他定义了 /代码在运行时所在的地址,那么_TEXT_BASE 中保存了这个地址 _TEXT_BASE:.word TEXT_BASE /声明 _armboot_start 并用 _start 来进行初始化,在 board/u-boot.lds 中定义。.globl _arm
12、boot_start _armboot_start:.word _start/*These are defined in the board-specific linker script.*/声明_bss_start 并用_bss_start 来初始化,其中_bss_start 定义在和板相关的 u-boot.lds 中。/_bss_start 保存的是_bss_start 这个标号所在的地址,这里涉及到当前代码所在 /的地址不是编译时的地址的情况,这里直接取得该标号对应的地址,不受编译时 /地址的影响._bss_end 也是同样的道理.globl _bss_start _bss_start:
13、.word _bss_start /同上.globl _bss_end _bss_end:.word _end#ifdef CONFIG_USE_IRQ/*IRQ stack memory(calculated at run-time)*/.globl IRQ_STACK_START IRQ_STACK_START:.word 0 x0badc0de/*IRQ stack memory(calculated at run-time)*/.globl FIQ_STACK_START FIQ_STACK_START:.word 0 x0badc0de#endif /*the actual rese
14、t code */MRS Rd,CPSR|SPSR 将 CPSR|SPSR 传送到 Rd/使用这两条指令将状态寄存器传送到一般寄存器,只修改必要的位,再将结果传送回状态寄存器,这样能够最好地完成对 CRSP 或 SPSR 的修改/MSR CPSR_|SPSR_,Rm 或是 MSR CPSR_f|SPSR_f,#/MRS 和 MSR 配合使用,作为更新 PSR 的“读取修改写回”序列的一部分/bic r0,r1,r2 ;r0:=r1 and not r2/orr ro,r1,r2 ;r0:=r1 or r2/这几条指令执行完毕后,进入 SVC32 模式,该模式主要用来处理软件中断(SWI)res
15、et:/*set the cpu to SVC32 mode */mrs r0,cpsr /将 CPSR 状态寄存器读取,保存到 R0 中 bic r0,r0,#0 x1f orr r0,r0,#0 xd3 msr cpsr,r0 /将 R0 写入状态寄存器中/*turn off the watchdog*/关闭看门狗#if defined(CONFIG_S3C2400)#define pWTCON 0 x15300000#define INTMSK 0 x14400008/*Interupt-Controller base addresses*/#define CLKDIVN 0 x1480
16、0014/*clock divisor register*/#elif defined(CONFIG_S3C2410)#define pWTCON 0 x53000000#define INTMSK 0 x4A000008/*Interupt-Controller base addresses*/#define INTSUBMSK 0 x4A00001C#define CLKDIVN 0 x4C000014/*clock divisor register*/#endif#if defined(CONFIG_S3C2400)|defined(CONFIG_S3C2410)ldr r0,=pWTC
17、ON mov r1,#0 x0 str r1,r0 /*mask all IRQs by setting all bits in the INTMR-default */关闭所有中断 mov r1,#0 xffffffff ldr r0,=INTMSK str r1,r0#if defined(CONFIG_S3C2410)ldr r1,=0 x3ff ldr r0,=INTSUBMSK str r1,r0#endif /*FCLK:HCLK:PCLK=1:2:4*/*default FCLK is 120 MHz!*/ldr r0,=CLKDIVN mov r1,#3 str r1,r0#e
18、ndif/*CONFIG_S3C2400|CONFIG_S3C2410*/*we do sys-critical inits only at reboot,*not when booting from ram!*/B 转移指令,跳转到指令中指定的目的地址 /BL 带链接的转移指令,像 B 相同跳转并把转移后面紧接的一条指令地址保存到链接寄存器 LR(R14)中,以此来完成子程式的调用 /该语句首先调用 cpu_init_crit 进行 CPU 的初始化,并把下一条指令的地址保存在 LR 中,以使得执行完后能够正常返回。#ifndef CONFIG_SKIP_LOWLEVEL_INIT bl c
19、pu_init_crit#endif#ifndef CONFIG_SKIP_RELOCATE_UBOOT /调试阶段的代码是直接在 RAM 中运行的,而最后需要把这些代码固化到 Flash 中,因此 U-Boot 需要自己从 Flash 转移到 /RAM 中运行,这也是重定向的目的所在。/通过 adr 指令得到当前代码的地址信息:假如 U-boot 是从 RAM 开始运行,则从 adr,r0,_start 得到的地址信息为 /r0=_start=_TEXT_BASE=TEXT_BASE=0 xa3000000;假如 U-boot 从 Flash 开始运行,即从处理器对应的地址运行,/则 r0=
20、0 x0000,这时将会执行 copy_loop 标识的那段代码了。/_TEXT_BASE 定义在 board/smdk2410/config.mk 中 relocate:/*relocate U-Boot to RAM */adr r0,_start /*r0-current position of code */ldr r1,_TEXT_BASE /*test if we run from flash or RAM*/cmp r0,r1 /*dont reloc during debug */beq stack_setup /重新定位代码/声明_bss_start 并用_bss_start
21、 来初始化,其中_bss_start 定义在和板相关的 u-boot.lds 中 ldr r2,_armboot_start ldr r3,_bss_start sub r2,r3,r2 /*r2-size of armboot */add r2,r0,r2 /*r2 region:phdr=fill.s e c n a m e 和 c o n t e n t s 是必须的,其他的都是可选的。下面挑几个常用的看看:1、secname:段名 2、contents:决定哪些内容放在本段,可以是整个目标文件,也可以是目标文件中的某段(代码段、数据段等)3、start:本段连接(运行)的地址,如果没有
22、使用 AT(ldadr),本段存储的地址也是 start。GNU 网站上说 start 可以用任意一种描述地址的符号来描述。4、AT(ldadr):定义本段存储(加载)的地址。看一个简单的例子:(摘自2410 完全开发)/*nand.lds*/SECTIONS firtst 0 x00000000:head.o init.o second 0 x30000000:AT(4096)main.o 以上,head.o 放在 0 x00000000 地址开始处,init.o 放在 head.o 后面,他们的运行地址也是 0 x00000000,即连接和存储地址相同(没有 AT 指定);main.o 放
23、在 4096(0 x1000,是 AT 指定的,存储地址)开始处,但是它的运行地址在 0 x30000000,运行之前需要从 0 x1000(加载处)复制到 0 x30000000(运行处),此过程也就用到了读取 Nand flash。这就是存储地址和连接(运行)地址的不同,称为加载时域和运行时域,可以在.lds 连接脚本文件中分别指定。编写好的.lds 文件,在用 arm-linux-ld 连接命令时带-Tfilename 来调用执行,如 arm-linux-ld Tnand.lds x.o y.o o xy.o。也用-Ttext 参数直接指定连接地址,如 arm-linux-ld Ttex
24、t 0 x30000000 x.o y.o o xy.o。既然程序有了两种地址,就涉及到一些跳转指令的区别,这里正好写下来,以后万一忘记了也可查看,以前不少东西没记下来现在忘得差不多了。ARM 汇编中,常有两种跳转方法:b 跳转指令、ldr 指令向 PC 赋值。我自己经过归纳如下:(1)b step1:b 跳转指令是相对跳转,依赖当前 PC 的值,偏移量是通过该指令本身的 bit23:0算出来的,这使得使用 b 指令的程序不依赖于要跳到的代码的位置,只看指令本身。(2)ldr pc,=step1:该指令是从内存中的某个位置(step1)读出数据并赋给 PC,同样依赖当前 PC 的值,但是偏移量
25、是那个位置(step1)的连接地址(运行时的地址),所以可以用它实现从 Flash 到 RAM 的程序跳转。(3)此外,有必要回味一下 adr 伪指令,U-boot 中那段 relocate 代码就是通过 adr 实现当前程序是在 RAM 中还是 flash 中。仍然用我当时的注释:relocate:/*把 U-Boot 重新定位到 RAM*/adr r0,_start/*r0 是代码的当前位置*/*adr 伪指令,汇编器自动通过当前 PC 的值算出 如果执行到_start 时 PC 的值,放到 r0 中:当此段在 flash 中执行时 r0=_start=0;当此段在 RAM 中执行时_st
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- uboot 代码 详细 分析
限制150内