am335x嵌入式开发-bootloader启动流程
来源:互联网 发布:php 检验日期格式 编辑:程序博客网 时间:2024/06/05 08:38
bootloader 版本
u-boot-2012.10-psp05.06.00.00
bootloader 启动流程
概述
am335x bootloader整体分为三个部分:rom_code,SPL(Secondary Program Loader)及u-boot。在分析流程之前,先大概浏览以下源代码的结构:
u-boot 源码组织结构
需要重点关注的源码
bootloader的整体运行流程为:
1. 芯片上电或复位
2. rom_code 运行,从外设或外部存储器中加载二级bootloader(SPL)到内存中运行
3. SPL做CPU和外设的初始化(主要是DDR)并将u-boot加载到内存运行
4. u-boot 继续做其它板载或外设的初始化并加载linux内核
5. linux内核开始启动
rom_code
am335x 系列soc在芯片内部的flash中固化了一段代码,称为rom_code,在芯片上电或复位后首先执行芯片内部固化的这段代码,这段代码的作用为引导二级bootloader(SPL)的镜像文件到内部sram中运行。
am335x引导模式
所谓am335x的引导模式其实就是二级bootloader(SPL)镜像的读取方式,刚才提到rom_code的作用是将二级 bootloader加载到内部的sram运行,那么rom_code从什么地方以及通过什么样的方式获取SPL的可执行镜像文件呢?这就决定于am335x的引导模式了。
am335x支持两大类的引导模式,分别为memory模式及外设模式。memory模式可以从NAND flash、NOR flash及eeprom中读取SPL镜像文件并加载到内部sram中运行。外设模式是指rom_code可以通过芯片的一些通信接口(比如EMAC、Serial、USB)获取SPL镜像文件并加载到内部sram中运行。
am335x的引导模式取决于上电或复位时芯片一组引脚的状态,称作SYSBOOT[15:0]共16位。其中SYSBOOT[4:0]决定了芯片的引导顺序。
上图中可以看出当SYSBOOT[4:0]为00010时,芯片会首先从UART0开始引导,如果失败会尝试SPI0、NAND、NANDI2C。
rom_code的运行流程
参考am335x的芯片技术手册,可以知道rome_code的执行流程如下:
下面分析rom_code的执行流程:
- 芯片复位后PC指针首先跳转到0x20000地址开始执行rom_code并做芯片的简单初始化
- rom_code根据SYSBOOT的配置生成引导设备列表
- 查看当前的引导类型是memory模式还是外设模式,并通过相应的接口或地址读取SPL
- SPL image读取成功,执行SPL镜像,SPL开始运行
- SPL image读取失败,尝试启动列表中的下一个外设或接口
- 若所有外设都没有正确读取到SPL image,则进入死循环(dead loop)等待看门狗复位
addr 说明 0x20000 rom_code的运行起始地址 0x402F0400 SPL镜像在内部sram中的加载地址,也是内部ram的起始地址
am335x 内部rom和内部ram的结构如下:
SPL(Secondary Program Loader)
SPL的作用
SPL是紧接着rom_code的第二级bootloader,主要负责板载的部分初始化、加载及运行u-bootSPL运行的起始点
SPL在芯片的内部sram中运行,那么它是从哪儿开始运行的呢?这需要查看spl在链接的时候的链接文件
u-boot-spl.lds,下面是 u-boot-spl.lds的文件内容:
# 定义内部sram区块MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\ # 这个定义在/include/configs/am335x_evm.h LENGTH = CONFIG_SPL_MAX_SIZE }# 定义外部sdram区块 MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ LENGTH = CONFIG_SPL_BSS_MAX_SIZE }OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")OUTPUT_ARCH(arm)# 定义入口为_startENTRY(_start)SECTIONS{ .text : { __start = .; arch/arm/cpu/armv7/start.o (.text) # 首先被执行的地方 *(.text*) } >.sram # 将代码段搬移到内部sram运行 . = ALIGN(4); .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram . = ALIGN(4); .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram . = ALIGN(4); __image_copy_end = .; _end = .; .bss : { . = ALIGN(4); __bss_start = .; *(.bss*) . = ALIGN(4); __bss_end__ = .; } >.sdram}
上述文件中 ENTRY(_start) 定义了SPL镜像的入口符号为start,它所存在的位置在arch/arm/cpu/armv7/start.o (.text) 中,而start.o是由start.S编译得到的,所以SPL的入口文件为arch/arm/cpu/armv7/start.S,另外SPL执行的地址由 CONFIG_SPL_TEXT_BASE定义得到的,我们看一下位于/include/configs/am335x_evm.h中的定义:
/* Defines for SPL */#define CONFIG_SPL#define CONFIG_SPL_FRAMEWORK#define CONFIG_SPL_TEXT_BASE 0x402F0400 // 定义spl的入口地址#define CONFIG_SPL_MAX_SIZE (101 * 1024)#define CONFIG_SPL_STACK CONFIG_SYS_INIT_SP_ADDR#define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/omap-common/u-boot-spl.lds" // 定义spl的链接文件#define CONFIG_SPL_BSS_START_ADDR 0x80000000#define CONFIG_SPL_BSS_MAX_SIZE 0x80000 /* 512 KB */
- SPL执行流程
1. Start.S: bl lowlevel_init 2. lowlevel_init.S::lowlevel_init bl s_init 3. arch/arm/cpu/armv7/am33xx/board.c::s_init • 关闭看门狗 • 初始化PLL • 初始化控制台串口 • 初始化外设pinmux • 初始化DDR 4. Start.S: bl board_init_f 5. arch/arm/lib/board::board_init_f • 初始化堆栈 • 清零bss段 • call board_init_r 6. common/spl/spl.c:: board_init_r • 设置timer • call board_init 7. arch/arm/cpu/armv7/am33xx/board.c::board_init • i2c_init • Lcd_Init • gpmc_init 8. common/spl/spl.c:: 继续初始化 • 根据当前的启动设备,加载u-boot到DDR • 运行并将控制权交给 u-boot • PC跳转到0x80800000(CONFIG_SYS_TEXT_BASE)执行u-boot
- u-boot 执行流程
0. u-boot的起始点也是start.S 1. Start.S: bl lowlevel_init 2. lowlevel_init.S::lowlevel_init bl s_init 3. arch/arm/cpu/armv7/am33xx/board.c::s_init • 关闭看门狗 • 初始化PLL • 初始化控制台串口 • 初始化外设pinmux • 初始化DDR 4. Start.S: bl board_init_f 5. arch/arm/lib/board.C::board_init_f • 初始化堆栈 • 清零bss段 • call board_init_r 6. arch/arm/lib/board.C::board_init_r • call board_init 7. \arch\arm\cpu\armv7\am33xx\board.c::board_init • i2c_init • lcd_init • gpmc_init • dcache_enable 8. arch/arm/lib/board.C::board_init_r • serial_initialize • mem_malloc_init • flash_init • nand_init • mmc_initialize • env_relocate • console_init_r • interrupt_init • enable_interrupts • eth_initialize • reset_phy 9. common/main.c::main_loop • 解析命令,执行命令,boot the linux kernel
- am335x嵌入式开发-bootloader启动流程
- 嵌入式Linux启动流程之BootLoader
- 【嵌入式开发】 Bootloader 详解 ( 代码环境 | ARM 启动流程 | uboot 工作流程 | 架构设计)
- 【嵌入式开发】 Bootloader 详解 ( 代码环境 | ARM 启动流程 | uboot 工作流程 | 架构设计)
- AM3517开发板bootloader启动流程分析
- 基于ARM的嵌入式系统Bootloader启动流程分析(S3C44B0X)
- 基于ARM的嵌入式系统Bootloader启动流程分析----- 转!!
- 基于ARM的嵌入式系统Bootloader启动流程分析
- AM335x bootloader
- AM335x bootloader
- am335x嵌入式开发-GPIO操作
- Bootloader启动流程
- Bootloader启动流程分析
- Bootloader的启动流程
- bootloader简单启动流程
- bootloader启动流程分析
- 【嵌入式】bootloader启动过程分析
- AM335x u-boot启动流程问题
- Android Studio中导入Vitamio框架
- android基础之六——多媒体编程
- Android 5.0/5.1 HOOK技术探究
- 深入理解JVM
- hdoj 2080 夹角有多大II
- am335x嵌入式开发-bootloader启动流程
- Microsoft(R) Developer Studio 已停止工作 解决办法(1)
- oracle之约束解析
- 【机房合作】单例模式实战
- Java特性学习
- YII config main.php
- oracle之索引分析
- Ubuntu14.04 32 编译VLC2.2.1 错误
- An App ID with Identifier is not available. Please enter a different string