u_boot初始化流程

合集下载

U-Boot工作过程

U-Boot工作过程

ldr r1, =0x38022
str r1, [r0]
# else
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
str r1, [r0] /* 看门狗控制器的最低位为0时,看门狗不输出复位信号 */
以上代码向看门狗控制寄存器写入0,关闭看门狗。否则在U-Boot启动过程中,CPU将不断重启。
(5)屏蔽中断
/*
* mask all IRQs by setting all bits in the INTMR - default
ldr pc, _not_used /* 未使用 */
ldr pc, _irq /* irq中断向量 */
ldr pc, _fiq /* fiq中断向量 */
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的执行。
mrs r0, cpsr
bic r0, r0, #0x1f /*工作模式位清零 */
orr r0, r0, #0xd3 /*工作模式位设置为“10011”(管理模式),并将中断禁止位和快中断禁止位置1 */
mov r1, #5
str r1, [r0]
ldr r0, =MPLLCON

U-boot启动流程分析(三)

U-boot启动流程分析(三)

U-boot 启动流程(Linux 内核)的分析(三)U-boot 属于两阶段的Bootloader ,第一阶段的文件为cpu/arm920t/start.S 和board\samsung\smdk2410/lowlevel_init.S,前者是平台相关的,后者是开发板相关的。

1.U-Boot 第一阶段代码分析(1)硬件设备初始化依次完成如下设置:将CPU 的工作模式设为管理模式(SVC ),关闭WATCHDOG ,设置FCLK ,HCLK ,PCLK 的比例,关闭MMU ,CACHE 。

代码在cpu/arm920t/start.S 中,(2)为加载Bootloader 的第二阶段代码准备RAM 空间。

所谓准备RAM 空间,就是初始化内存芯片,使它可用,对于S3C24x0,通过在Start.S 中调用lowlevel_init 函数来设置存储控制器,使得外接 SDRAM 可用,lowlevel_init.S,文件是与开发板相关的,这表示如果外接的设备不一样,可以修改lowlevel_init.S 文件中的相关的宏。

(3)复制Bootloader 的第二阶段代码到RAM 空间中 这里将整个U-Boot 代码都复制到SDRAM 中,这在cpu/arm920t/start.s 中实现上面这段程序,在使用NANDFlash 启动时,需要修改。

(4)设置好栈 /*栈的设置灵活性很大,只要让sp 寄存器指向一段没有使用的内存即可*/.word TEXT_BASE //这里是获得代码段的起始地址,我的是0x33F80000(在board/xxx/config.mk中//可到找到“TEXT_BASE=0x33F80000”.globl lowlevel_init //这里相当于定义一个全局的lowlevel_init以方便调用lowlevel_init :/* memory control configuration *//* make r0 relative the current location so that it *//* reads SMRDATA out of FLASH rather than memory ! */ldr r0, =SMRDATA //SMDATA表示这 13个寄存器的值存放的开始地址,值为0x33F8xxxx,处于内//存中,这一句的作用是把其值加载到r0中ldr r1, _TEXT_BASE // 把代码的起始地址(0x33F80000)加载到r1中sub r0, r0, r1 //r0减去r1其结果存入r0,也即SMDATA中的起始地址0x33F8xxxx减去//0x33F80000,其结果就是13个寄存器的值在NOR Flash存放的开始地址ldr r1, =BWSCON /* Bus Width Status Controller */ //存储控制器的基地址add r2, r0, #13*4 //在计算出来的存放地址加上#13*4,然后其结果保存在r2中//13 个寄存器,每个寄存器占4个字节0:ldr r3, [r0], #4 //内存中r0的值加载到r3中,然后r0加4,即下一个寄存器的str r3, [r1], #4 //读出寄存器的值保存到r1中,然后r1也偏移4cmp r2, r0 //比较r0与r2的值,如果不等继续返回0:执行,也即13个寄存器的值// 是否读完bne 0b/* everything is fine now */mov pc , lr //程序跳转,返回到cpu_init_crit中.ltorg/* the literal pools origin */SMRDATA :...................relocate : /* 将U-Boot复制到RAM中 */adr r0, _start /* r0:当前代码的开始地址 */ldr r1, _TEXT_BASE /* r1:代码段的连接地址*/cmp r0, r1 /* 测试现在是在FLash中,还在是RAM中,如果要从NandFlash启动的话,这里要根据需要修改 */beq stack_setup /*如果已经在RAM中,则不需要复制*/ldr r2, _armboot_start /*_armboot_start在前面定义,是第一条指令的运行地址*/ldr r3, _bss_start /*在连接脚本U-Boot.lds中定义,是代码段的结束地址*/sub r2, r3, r2 /* r2 <- 代码段长度 */add r2, r0, r2 /* r2 <-代码段的结束地址 */copy_loop :ldmia {r3-r10} /* 从地址[r0]处获得数据 */stmia {r3-r10} /* 复制到地址[r1]处 */cmp r0, r2 /* 判断是否复制完毕 */ble copy_loop /*没有复制完,则继续*/#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ldr r0, _TEXT_BASE /* _TEXT_BASE 为代码段的开始地址,值为0x33F80000 */sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* 代码段下面,留出一段内存以实现malloc */sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* 再留出一段内存,存一些全局参数 */#ifdef CONFIG_USE_IRQsub r0, r0, #(CONFIG_STACKSIZE_IRQ +CONFIG_STACKSIZE_FIQ )#endifsub sp , r0, #12 /* 最后,留出12字节的内存给abort异常 */clear_bss :(5)跳转到第二阶段代码的C 入口点 在跳转之前,还要清除BSS 段(初始值0,无初始值的全局变量,静态变量放在BSS 段。

uboot配置过程分析

uboot配置过程分析

fi
#
命令:mkconfig mini6410 arm s3c64xx mini6410 samsung s3c6410 NAND ram256
$0
$1
$2 $3 $4
$5 $6
$7
$8
APPEND=no # Default: Create new config file
BOARD_NAME="" # Name to print in make output
fi
# create link for s3c64xx-mp SoC if [ "$3" = "s3c64xx-mp" ] ; then
rm -f regs.h ln -s $6.h regs.h rm -f asm-$2/arch ln -s arch-$3 asm-$2/arch fi 分析: 上面的语句即判断$2 和$3 等于什么,并且执行相应的语句 $2=arm,$3=s3c64xx 所以执行,蓝色部分不执行 if [ "$3" = "s3c64xx" ] ; then
[ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk 分析: 如果$5 已经定义并且$5 不等于 NULL,则将 VENDOR = $5(VENDOR 进入 config.mk 文件
= samsung) 追 加
[ "$6" ] && [ "$6" != "NULL" ] && echo "SOC = $6" >> config.mk 分析: 如果$6 已经定义并且$6 不等于 NULL,则将 SOC = $6(SOC config.mk 文件 内容: ARCH = arm CPU = s3c64xx BOARD = mini6410 VENDOR = samsung SOC = s3c6410 如图:

uboot启动流程分析

uboot启动流程分析

uboot启动流程分析Uboot启动流程分析。

Uboot是一种常用的嵌入式系统启动加载程序,它的启动流程对于嵌入式系统的正常运行至关重要。

本文将对Uboot启动流程进行分析,以便更好地理解其工作原理。

首先,Uboot的启动流程可以分为以下几个步骤,Reset、初始化、设备初始化、加载内核。

接下来我们将逐一进行详细的分析。

Reset阶段是整个启动流程的起点,当系统上电或者复位时,CPU会跳转到Uboot的入口地址开始执行。

在这个阶段,Uboot会进行一些基本的硬件初始化工作,包括设置栈指针、初始化CPU寄存器等。

接着是初始化阶段,Uboot会进行一系列的初始化工作,包括初始化串口、初始化内存控制器、初始化时钟等。

这些初始化工作是为了确保系统能够正常地运行,并为后续的工作做好准备。

设备初始化阶段是Uboot启动流程中的一个重要环节,它包括对外设的初始化和检测。

在这个阶段,Uboot会初始化各种外设,如网卡、存储设备等,并对其进行检测,以确保它们能够正常工作。

最后一个阶段是加载内核,Uboot会从存储设备中加载操作系统的内核镜像到内存中,并跳转到内核的入口地址开始执行。

在这个过程中,Uboot会进行一些必要的设置,如传递启动参数给内核,并最终将控制权交给内核。

总的来说,Uboot的启动流程是一个非常重要的过程,它涉及到系统的硬件初始化、外设的初始化和内核的加载等工作。

只有当这些工作都顺利完成时,系统才能够正常地启动运行。

因此,对Uboot启动流程的深入理解对于嵌入式系统的开发和调试具有重要意义。

通过本文对Uboot启动流程的分析,相信读者对Uboot的工作原理有了更清晰的认识。

希望本文能够对大家有所帮助,谢谢阅读!。

uboot启动流程

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中初始化序列的说明

U-Boot中初始化序列的说明

U-Boot中初始化序列的说明展开全文在函数中board_init_f()中,进行了一系列的初始化,主要通过调用初始化序列中的函数来实现。

初始化序列定义如下,这里只留下了我用到的初始化函数:init_fnc_t *init_sequence[] = {get_clocks,init_timebase,env_init,init_baudrate,serial_init,console_init_f,display_options,checkcpu,checkboard,init_func_i2c,init_func_ram,NULL, /* Terminate this list */};下面逐个对这些函数进行说明:get_clocks在文件./include/common.h中定义,在文件./cpu/mpc824x/Speed.c中实现,用于设置global_data中的gd->cpu_clk和gd->bus_clk。

init_timebase在文件./include/common.h中定义,在文件./lib_ppc/time.c中实现,用于设置Time Base寄存器TBU和TBL,将其都设置成0。

env_init在文件./include/common.h中定义,在文件./common/Env_flash.c中实现,用于设置global_data中的gd->env_addr和gd->env_valid。

init_baudrate在文件./lib_ppc/board.c中定义和实现,用于设置global_data中的gd->baudrate。

serial_init在文件./include/common.h中定义,在文件./drivers/serial.c中实现,通过调用函数NS16550_init,对UART 相关的寄存器进行初始化。

NS16550_init在文件./include/ns16550.h中定义,在文件. /drivers/ns16550.c中实现。

uboot 代码运行流程

uboot 代码运行流程

uboot 代码运行流程U-Boot代码运行流程U-Boot(Universal Bootloader)是一个开源的引导加载程序,广泛应用于嵌入式系统中。

它负责在系统上电后初始化硬件并加载操作系统内核,是系统启动的重要一环。

下面将从U-Boot代码的运行流程方面进行介绍。

1. 启动阶段当系统上电后,处理器会从预定义的存储器地址开始运行代码。

U-Boot的启动代码通常存放在ROM中,处理器会从ROM的起始地址开始执行。

启动代码负责初始化处理器和一些外设,然后跳转到U-Boot的入口点。

2. 入口点U-Boot的入口点是指U-Boot的main()函数。

在启动代码的最后,会调用main()函数,从而进入U-Boot的主循环。

U-Boot的主循环负责处理用户输入的命令,并根据命令执行相应的操作。

3. 硬件初始化在main()函数中,首先会进行硬件的初始化工作。

这包括初始化串口、初始化存储器控制器、初始化网络接口等。

硬件初始化的目的是为了确保系统能够正常运行,并为后续的操作做好准备。

4. 系统启动硬件初始化完成后,U-Boot会尝试从存储设备(如闪存、SD卡)中加载操作系统内核镜像。

U-Boot会根据预定义的启动命令(例如bootcmd)来确定从哪个设备加载内核镜像,并执行相应的加载操作。

加载完成后,U-Boot会将控制权交给操作系统内核,进入操作系统的启动阶段。

5. 用户交互一般情况下,U-Boot会在系统启动后进入命令行界面,等待用户输入命令。

用户可以通过串口、网络等方式与U-Boot进行交互,执行各种操作,例如烧写固件、修改配置等。

U-Boot提供了丰富的命令集,可以满足不同的需求。

6. 系统重启当用户输入重启命令或系统发生异常时,U-Boot会执行系统重启操作。

重启操作包括重新初始化硬件、重新加载内核镜像等步骤,以重新启动系统。

U-Boot会将控制权交给重新加载的内核,然后进入内核的启动流程。

总结:U-Boot代码的运行流程包括启动阶段、入口点、硬件初始化、系统启动、用户交互和系统重启等几个关键步骤。

uboot开发流程

uboot开发流程

uboot开发流程U-Boot 开发流程U-Boot 是一个用于启动嵌入式系统的大约 40KB 的嵌入式固件。

它在系统启动过程中通常作为第一个软件组件被加载和执行,负责初始化硬件、加载内核并将其传递给内核。

开发 U-Boot 的步骤:1. 获取 U-Boot 源代码从 U-Boot 官方网站下载最新版本的 U-Boot 源代码。

2. 设置开发环境安装必要的工具链和依赖项,例如交叉编译器、Make 和 Perl。

还要创建一个用于开发和构建 U-Boot 的工作区。

3. 配置 U-Boot打开 U-Boot 配置文件(通常为 'config.h'),并根据您的特定板配置选项,例如板类型、内存大小和外围设备。

4. 编译 U-Boot使用 'make' 命令编译 U-Boot。

5. 调试 U-Boot使用 'gdb' 等调试器调试 U-Boot 代码,并修复任何编译错误或运行时问题。

6. 设置和测试 NAND/NOR 闪存配置 U-Boot 以使用 NAND 或 NOR 闪存,并通过写入和验证图像来测试该配置。

7. 集成 U-Boot 到板级支持包 (BSP)将编译后的 U-Boot 图像集成到您的 BSP 中,这是一个用于支持特定硬件板的软件包。

8. 在目标板上测试 U-Boot将 BSP 部署到目标板,并测试 U-Boot 是否可以正确启动系统。

9. 个性化 U-Boot根据您的特定需求定制 U-Boot 的命令行和功能,例如添加自定义命令或修改环境变量。

10. 维护 U-Boot随着时间的推移,跟踪和应用 U-Boot 社区的更新和补丁,以确保您的开发保持最新且安全。

提示:遵循 U-Boot 文档并充分利用社区支持。

使用版本控制系统来跟踪您的更改。

彻底测试您的代码以确保其稳定性。

保持 U-Boot 与您的目标板紧密集成。

定期更新 U-Boot 以利用最新功能和安全改进。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

U-Boot启动代码分析U-boot的启动顺序分为stage1和stage2两部分,见下图。

依赖于CPU体系结构的代码(如设备初始化代码等)通常放在stage1中用汇编语言实现,而在stage2则通常由C语言实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。

以下主要梳理了stage2阶段函数的调用顺序以及每个函数的功能。

U-boot的启动顺序C语言代码部分lib_arm/board.c中的start_armboot既是C语言开始的函数也是整个启动代码中C语言的主函数,同时还是整个U-boot的主函数,该函数只要完成如下操作。

(1)调用一系列的初始化函数。

(2)初始化Flash设备。

(3)初始化系统内存分配函数(4)如果目标系统拥有NAND设备,则初始化NAND设备(5)如果目标系统有显示设备,则初始化该类设备。

(6)初始化相关网络设备,填写IP、MAC地址等。

(7)进入命令循环(即整个Boot的工作循环),接收用户从串口输入的命令,然后进行相应的工作。

下面结合源码分析函数调用顺序以及函功能:代码:void start_armboot (void){init_fnc_t **init_fnc_ptr;char *s;int mmc_exist = 0;#if defined(CONFIG_VFD) || defined(CONFIG_LCD)unsigned long addr;#endif注释:从U-boot stage1中start.s程序调到这里执行start_armboot函数,这一段代码进行了变量声明,其中定义了一个名为init_fnc_ptr的双重指针。

如果CONFIG_VFD或者CONFIG_LCD被定义了则声明一无符号长整型变量addr,本开发板中没有定义无需声明addr。

代码:/* Pointer is writable since we allocated a register for it */gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));/* compiler optimization barrier needed for GCC >= 3.4 */__asm__ __volatile__("": : :"memory"); //内存屏障,告诉编译器内存被修改过了memset ((void*)gd, 0, sizeof (gd_t));gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); //指向gd之前memset (gd->bd, 0, sizeof (bd_t));// gd->flags |= GD_FLG_RELOC;monitor_flash_len = _bss_start - _armboot_start; //u-boot映像的大小其中_armboot_start为code start ,_bss_start为code + data end == BSS start.注释:gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));//内存强制转换,gd为全局环境变量,gd指向uboot之前的地址;memset ():void * memset(void * s,char c,size_t count)将指针s所指地址以及之后count个地址中数值赋值为c。

memset ((void*)gd, 0, sizeof (gd_t))的作用为:gd整个地址的值初始化为0;memset (gd->bd, 0, sizeof (bd_t))的作用为bd地址的值初始化为0。

代码:for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {if ((*init_fnc_ptr)() != 0) { //相当于调用指针中的一个函数,如果不为0就表示死机hang ();}}注释:将init_squence数组送给init_fnc_ptr,利用循环调用init_squence数组中的多个初始化函数,包括初始化CPU、board、中断、时钟、NOR Flash、NAND Flash等,后面根据代码进行分析。

初始化完成之后进入hang()处于死循环即完成U-boot使命。

init_sequence[ ]数组保存基本的初始化函数指针,在board.c中对数组进行了定义:#if defined(CONFIG_ARCH_CPU_INIT)arch_cpu_init, /* basic arch cpu dependent setup */#endifboard_init, /* basic board dependent setup *///#if defined(CONFIG_USE_IRQ)interrupt_init, /* set up exceptions *///#endif//timer_init, /* initialize timer */#ifdef CONFIG_FSL_ESDHC//get_clocks,#endifenv_init,/* initialize environment */init_baudrate,/* initialze baudrate settings */serial_init,/* serial communications setup */console_init_f,/* stage 1 init of console */off_charge,// xiebin.wang @ 20110531,for charger&power off device.display_banner,/* say that we are here */#if defined(CONFIG_DISPLAY_CPUINFO)print_cpuinfo,/* display cpu info (and speed) */#endif#if defined(CONFIG_DISPLAY_BOARDINFO)checkboard,/* display board info */#endif#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)//init_func_i2c,#endifdram_init, /* configure available RAM banks */#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)//arm_pci_init,#endifdisplay_dram_config,NULL,};注释:下面按照顺序依次分析各个初始化函数作用(绿色代码是被注释掉的并不执行):arch_cpu_init():基本处理器相关配置。

如果定义了CONFIG_ARCH_CPU_INIT则执行此函数,本开发板在include/configs/smdkc100.h中定义了此变量。

最终在串口打印:CPU: SMDK4412-AP1.1 [e4412211]APLL = 1000MHz, MPLL = 800MHzARM_CLOCK = 1000MHzboard_init():基本的板级相关配置,设置了一些寄存器,如时钟,IO口,串口,机器类型,启动参数,指令cache,数据cache.env_init():初始化环境变量,这个函数主要是在gd里保存环境变量的存放地址。

一般使用默认的环境变量值即default_environment数组。

init_baudrate():初始化波特率设置,调用getenv_r()函数来获取环境变量,从上面刚初始化好的环境变量列表里找波特率值,如果没有就赋初始值为CONFIG_BAUDRATE,一般在board.c中定义函数。

serial_init():串口通信设置,在cpu/Arm-cortexa9的serial.c中定义了该函数。

console_init_f():控制台初始化阶段,初始化了几个控制台相关的标记。

在common/Console.c 中定义。

off_charge():管理和关闭设备。

display_banner():打印U-boot信息,包括了一些显示函数,在board.c中定义了该函数。

print_cpuinfo():打印cpu信息,如果定义了CONFIG_DISPLAY_CPUINFO,则执行该函数,本开发板定义了此变量。

checkboard():如果定义了CONFIG_DISPLAY_BOARDINFO,则执行函数。

dram_init():配置可用的RAMdisplay_dram_config():显示RAM的配置,打印出DRAM的大小,在board.c中定义了该函数。

代码:/* armboot_start is defined in the board-specific linker script */mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN,CONFIG_SYS_MALLOC_LEN);#ifndef CONFIG_SYS_NO_FLASH/* configure available FLASH banks */display_flash_config (flash_init ());注释:mem_malloc_init():初始化堆空间,malloc使用的内存空间地址。

在common/Dlmalloc.c 中定义了该函数。

flash_init ():记录下flash的大小,数量,sector的大小数量等,并对flash上重要的数据进行保护。

display_flash_config():通过调用flash_init ()来打印flash的大小信息,在board.c中定义了该函数。

代码:#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);vfd_setmem (addr);gd->fb_base = addr;#endif /* CONFIG_VFD注释:如果CONFIG_VFD被定义PAGE_SIZE没有被定义,则定义PAGE_SIZE为4096,为VFD 保存内存空间,以页为单位。

相关文档
最新文档