学习笔记之 AM335x Linux 的uboot工作流程

alexnewtt

贡献于2013-09-08

字数:6692 关键词: 嵌入式开发

AM335x Linux启动过程 2013-04-09 基于uboot2012-09 一、 AM335x 的启动过程 AM335x 的启动主要包括ROM,SPL, U-Boot 和kernel四个启动步骤: 1. ROM code ROM code是固化在芯片内部的代码,当上电时序正确,而且晶振等芯片启动所需的条件都具备时,AM335x会从ROM code开始运行。 ROM code首先会读取sys_boot引脚上的配置,以确定存放SPL的存储器,或者可以获取SPL的外设。 具体可以参考AM335x technical reference manual中的第26章 Initialization。 ROM code会从相应的地方读取/获取SPL,并运行SPL。 2. SPL SPL 和U-Boot 是bootloader的两个阶段。这里分为两个阶段的原因是, ROM code中不会配置DDR,时钟等最小系统,所以ROM code只能把bootloader加载到片上SRAM中,而片上SRAM对成本影响很大,所以通常很小,例如在AM335x上只有64K,不足够放下整 个U-Boot,所以将U-Boot分成两部分,SPL和U-Boot。 SPL主要的职责就是初始化DDR,时钟等最小系统,以读取U-Boot,并加载到DDR中。具体来看,SPL 由ROM code加载到片上SRAM的起始位置,也就是0x402F0400。SPL会进一步对芯片进行配置,主要包括以下几个方面以完成其主要职责: 配置ARM core。 主要包括对中断向量表,cache,MMU等的配置。 配置时钟系统,主要是PLL等。这个是配置各个功能模块的基础。 配置UART,timer等。主要用于输出必要的调试信息,或者提供些时钟工具。 配置I2C和PMIC。这个主要是为了配置电源管理芯片。 配置DDR。 配置 U-Boot所在的存储器或者外设。 完成配置后,SPL会读取U-Boot,并运行U-Boot。 3. U-Boot U-Boot 主要的工作就是正确加载Kernel。和SPL类似,U-Boot也是要加载下一个阶段的image,但是U-Boot提供了更多外设的支持和更多的调试 工具。所以,U-Boot也要进行各个模块的配置,上述SPL配置的部分, 除了DDR外,U-Boot也会根据需求重新配置(这里重置主要是U-Boot是一个开源工程,其要兼容某些特殊的芯片,从而需要做重载)。此外,U- Boot也会对网口,SD卡等根据需求进行配置。 完成配置后,U-Boot 会从相应的存储器或者外设读取Kernel,并传递参数给kernel,运行kernel。 二、am335x spl 与 uboot详细工作流程以及函数具体位置 u boot 会根据宏定义以及路径的不同产生两个start.o文件,这两个文件会分别编译为MLO 和 u-boot.img MLO #define CONFIG_SPL_BUILD #undef CONFIG_SKIP_LOWLEVEL_INIT ./spl/arch/arm/cpu/armv7/start.o The function board_init_f() and board_init_r() in spl.c(arch/arm/cpu/armv7/omap-common/spl.c) u-boot #undef CONFIG_SPL_BUILD #define CONFIG_SKIP_LOWLEVEL_INIT ./arch/arm/cpu/armv7/start.o The function board_init_f() and board_init_r() in board.c (arch/arm/lib/board.c) 1. SPL (1). save_boot_params (arch/arm/cpu/armv7/ti81xx/lowlevel_init.s) (2). set the cpu to SVC32 mode (arch/arm/cpu/armv7/start.s) (3).(bl cpu_init_cp15) Invalidate(关闭) TLB icache Bparray DSB ISB (arch/arm/cpu/armv7/start.s) (4). disable MMU stuff and caches (arch/arm/cpu/armv7/start.s) (5). (bl cpu_init_crit->b lowlevel_init)setup puu,mux,memory (arch/arm/cpu/armv7/lowlevel_init.s) bl s_init(arch/arm/cpu/armv7/am33xx/board.c) 1). check if we are already running from RAM 2). enable L2 cache (arch/arm/cpu/armv7/ti81xx/cache.s) 3). disable WDT1 (arch/arm/cpu/armv7/am33xx/board.c) 4). Setup the PLLs and the clocks for the peripherals (arch/arm/cpu/armv7/am33xx/clock.c) 5). Enable RTC32K clock (arch/arm/cpu/armv7/am33xx/board.c) 6). UART soft reset (arch/arm/cpu/armv7/am33xx/board.c) 7). Disable smart idle (arch/arm/cpu/armv7/am33xx/board.c) 8). initialize the Timer (board/ti/am335x/evm.c) 9). preloader console init (common/spl.c) 10). config am335x DDR (board/ti/am335x/evm.c) (6). copy data to ram (arch/arm/cpu/armv7/start.s) 1). Set stack pointer in internal RAM to call board_init_f (arch/arm/cpu/armv7/start.s) 2). call board_init_f (common/spl.c) 3). relocate code copy global data to 0x402F0400 (arch/arm/cpu/armv7/start.s) 4). call board_init_r (common/spl.c) (7). load image from SD card (common/spl.c) 1).spl_board_init(arch/arm/cpu/omap-common/boot-common.c)->am33xx_spl_board_init (2013版区别)->arch_misc_init(打开USB(USB Peripheral、USB Host mode)) a).musb_register(arch/arm/cpu/armv7/am33xx/board.c) b).musb_init_controller c).setup musb parts of core(especially endpoints) musb_core_init() 2). initialize timer,i2c,spl board (common/spl.c) 3). load image from mmc (common/spl.c) 4). jump to u-boot image addr:0x80800000 (common/spl.c) 至此,整个AM335x  SPL代码全部分析完毕,主要还是这3个函数: ?  cpu_init_crit    //cpu级初始化 ?  board_init_f    //代码重定位 ?  board_init_r    //板级初始化,并执行最终u-boot 2. U boot (1) Set the cpu to SVC32 mode (arch/arm/cpu/armv7/start.s) (2) call board_init_f (arch/arm/lib/board.c) 1). initialize global data (arch/arm/lib/board.c) U-Boot使用了一个存储在寄存器中的指针gd来记录全局数据区的地址: #define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8") DECLARE_GLOBAL_DATA_PTR定义一个gd_t全局数据结构的指针,这个指针存放在指定的寄存器r8中。这个声明也避免编译器把r8分配给其它的变量。任何想要访问全局数据区的代码,只要代码开头加入“DECLARE_GLOBAL_DATA_PTR”一行代码,然后就可以使用gd指针来访问全局数据区了。 a). Clear global data (arch/arm/lib/board.c)memset /* 逐个调用init_sequence数组中的初始化函数 */ for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { if ((*init_fnc_ptr)() != 0) { hang (); } } b). save time data to gd (arch/arm/cpu/armv7/omap-common/timer.c) c). save environment data to gd (common/env_nand.c) d). save serial data to gd (drivers/serial/serial.c) e). save serial state to gd (common/console.c) f). display uboot version (arch/arm/lib/board.c) g). initialize i2c (drivers/i2c/omap24xx_i2c.c) h). save dram size to gd (arch/arm/lib/board.c) i). save dram config to gd and display it (arch/arm/lib/board.c) j). call relocate_code in start.s (do nothing???) (arch/arm/cpu/armv7/start.s) (3) call board_init_r (arch/arm/lib/board.c) 1). enable caches (just display "WARNING: Caches not enabled") (arch/arm/lib/cache.c) void __enable_caches(void) { puts("WARNING: Caches not enabled\n"); } void enable_caches(void)__attribute__((weak, alias("__enable_caches"))); 函数enable_caches和__enable_cache重名 2). initialize board (arch/arm/cpu/armv7/am33xx/board.c) a). configure the i2c0 pin mux (board/ti/am335x/mux.c) b). Test eeprom and read header information (arch/arm/cpu/armv7/am33xx/board.c) c). detect daughter board (board/ti/am335x/evm.c) d). initialize gpmc for x16 MuxMode (arch/arm/cpu/armv7/ti81xx/mem.c) e). initialize the name of fastboot flash name mappings (common/cmd_fastboot.c) Data stored in the struct ptn (board/ti/am335x/evm.c) 3). initialize the malloc memory to zero (common/dlmalloc.c) 4). initialize the nand (drivers/mtd/nand/nand.c) (mtd: memory technology device) 5). initialize the mmc (drivers/mmc/mmc.c) 6). initialize environment read nand data (common/env_common.c) initialize hash table (env_htab) 7). call stdio_init (just initialize the i2c again) (common/stdio.c) 8). initialize jumptable (gd->jt) (common/exports.c) 9). fully initialize console as a device (gd->jt[getc,tstc,putc,puts,printf])(common/console.c) 9.5). open musb( arch_misc_init ) 10). miscellaneous platform dependent (print board information) (board/ti/am335x/evm.c) 11). initialize interrupt save gd->irq_sp to IRQ_STACK_START (arch/arm/lib/interrupts.c) 12). enable interrupts (do nothing) (arch/arm/lib/interrupts.c) 13). find loadaddress from hash table (common/cmd_nvedit.c) 14). find bootfile name from hash table (common/cmd_nvedit.c) 15). call board_late_init do nothing for GP_BOARD (board/ti/am335x/evm.c) 16). initialize net (net/eth.c) 17). call main_loop (common/main.c) (5) main_loop (common/main.c) 1). initialize hash parser for uboot (common/hush.c) 2). find bootdelay from hash table (common/cmd_nvedit.c) 3). find bootcmd from hash table (common/cmd_nvedit.c) 4). watch for bootdelay seconds for autoboot stop (common/main.c) 5). read and parse bootcmd (common/hush.c) start kernel typedef int boot_os_fn (int flag, int argc, char * const argv[],bootm_headers_t *images); /* pointers to os/initrd/fdt */ R0 flag R1 argc R2 argv R3 images 三、代码变动信息 本次u-boot代码是基于 u-boot-2012.10-psp05.06.00.00 版本基础上更改的 源代码下载地址: http://software-dl.ti.com/dsps/dsps_public_sw/am_bu/sdk/AM335xSDK/latest/index_FDS.html 下载 am335x-evm-sdk-src-05.06.00.00.tar.gz 文件 解压后在am335x-evm-sdk-src-05.06.00.00/board-support/u-boot-2012.10-psp05.06.00.00 目录下。 主要更改的文件 变动后的文件在 u-boot-2012-10 change file 目录下 ./include/configs/am335x_evm.h 更改bootcmd默认值 ./arch/arm/cpu/armv7/am33xx/board.c 更改读eeprom设置 ./common/cmd_usb.c 更改usb start返回值 ./drivers/usb/musb-new/musb_uboot.c 更改usb启动等待时间

下载文档,方便阅读与编辑

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 4 金币 [ 分享文档获得金币 ]
27 人已下载

下载文档

相关文档