logo资料库

AM335x UBOOT移植记录.pdf

第1页 / 共10页
第2页 / 共10页
第3页 / 共10页
第4页 / 共10页
第5页 / 共10页
第6页 / 共10页
第7页 / 共10页
第8页 / 共10页
资料共10页,剩余部分请下载后查看
UBOOT 的编译命令 直接一次性编译 make O=am335x CROSS_COMPILE=arm-arago-linux-gnueabi ARCH=arm am335x_evm 配置 make ARCH=arm CROSS_COMPILE=arm-arago-linux-gnueabi- am335x_evm_config 编译 make ARCH=arm CROSS_COMPILE=arm-arago-linux-gnueabi- 清理 make clean ARCH=arm CROSS_COMPILE=arm-arago-linux-gnueabi- make distclean ARCH=arm CROSS_COMPILE=arm-arago-linux-gnueabi- 编译器环境变量的设置 这个环境变量是 TI 的 SDK 包里面带的编译器,不是之前的 arm-gcc- export PATH=$PATH:/mnt/disk1/ti-sdk-am335x-evm-05.05.00.00/linux-devkit/bin/ UBOOT 里面的 MLO(u-boot-spl) 如果使用 NAND 启动,那么这个文件就是相当于 NBOOT,进行第一次的引导 这个 MLO 实际上就是 u-boot-spl.bin 生成的, 在编译完 uboot 后,SPL 的目录里面会产生了许多的.o 文件,这里文件就是 uboot 的文件, 可以打开 Makefile,有一些对应的宏定义,可以取消,减少 MLO 文件的大小 UBOOT 的链接脚本 lds UBOOT\arch\arm\cpu\armv7\u-boot.lds 正常运行 UBOOT 的 lds UBOOT\arch\arm\cpu\armv7\omap-common\u-boot.lds 这个是 nboot,加载 uboot 用 有 2 个 lds,不同的作用,注意要区别开 增加新的单板支持 在 boards.cfg 文件中,找到加入,例如 单板名字 arm armv7 对应 board 的目录 ti ti81xx 以后就可以执行 make 单板名字 来生成 uboot,这里被 ti 改写了,所以不是原版的 uboot 生成方法 一些代码的定位 u-boot-2011.09-psp04.06.00.08/arch/arm/cpu/armv7 这个目录下的几个文件,start.s 这个是程序的入口执行文件 u-boot-2011.09-psp04.06.00.08/arch/arm/cpu/armv7/omap-common u-boot-2011.09-psp04.06.00.08/arch/arm/cpu/armv7/ti81xx 这 2 个目录是和平台板子相关,AM335X 是 ti81xx 的版本 以上都是和 CPU 有关 u-boot-2011.09-psp04.06.00.08/arch/lib
ARM 平台的公用代码 u-boot-2011.09-psp04.06.00.08/lib 通用的库代码,无论什么平台都编译 board/ti/xxx 这个目录就是单板的配置
Makefile 文件分析 在终端中输入后 make ARCH=arm CROSS_COMPILE=arm-arago-linux-gnueabi- am335x_evm_config 命令后,会生成 3 个文件 1、.boards.depend 2、include/config.h /* Automatically generated - do not edit */ #define CONFIG_BOARDDIR board/ti/am335x #include #include #include #include 3、include/config.mk ARCH = arm CPU = armv7 BOARD = am335x VENDOR = ti SOC = ti81xx 终端中会输出 awk '(NF && $1 !~ /^#/) { print $1 ": " $1 "_config; $(MAKE)" }' boards.cfg > .boards.depend Configuring for am335x_evm board... 支持的配置 am335x 配置有 am335x_evm am335x_evm_restore_flash am335x_evm_spiboot 解析 Makefile 文件, sinclude $(obj).boards.depend $(obj).boards.depend: boards.cfg awk '(NF && $$1 !~ /^#/) { print $$1 ": " $$1 "_config; $$(MAKE)" }' $< > $@ 我们搜索 am335x_evm 并没有在 makefile 文件中找到对应的关键字,但是发现 boards.cfg 中有此关键词, 可能 am335x_evm_config 输入后,是到 boards.cfg 中寻找的
通过 TI CCS 调试 uboot 通过 makefile 文件建立 ccs 工程 1、打开 CCS,选择 File->New->Project 2、打开新建窗口后,选择 c/c++下的 Makefile Project with Existing Code 3、点击下一步,选择 uboot 的存放的目录,然后点击完成 4、等待右下角的进度,一直到达 100%后,在继续操作 5、最后在属性设置里,取消 C 的自动编译 调试的时候,如果目标代码是汇编,则不会现实源码,只有 C 才会现实出 uboot 的代码运行流程 u-boot-2011.09-psp04.06.00.08/arch/arm/cpu/armv7 start.s 入口运行文件 bl save_boot_params 跳转到 lowlevel_init.S 该 文 件 在 (arch\arm\cpu\armv7\omap-common) , 如 果 是 MLO 则 会 定 义 CONFIG_SPL_BUILD 宏,uboot 没有定义,保存 CPU ROM 的参数到一个地方中 bl cpu_init_crit SPL 里面调用,初始化底层相关的(函数就在本文件中最下面) bl lowlevel_init 保存旧的堆栈指针,设置新的堆栈指针 在 lowlevel_init.S (arch\arm\cpu\armv7\omap-common)文件中 bl s_init 此函数在 Evm.c (board\ti\am335xwecon)文件中, 不同的平台初始化不同的内容 初始化堆栈指针 跳转到 C 语言,board_init_f,C 言从 个函数开始 行 语 这 执 board_init_f 在 Board.c (arch\arm\lib)文件中 init_sequence 数 , 组 继续进 行初始化 relocate_code 函数,重新回到 汇编 start.s 文件中 relocate_code:在 start.s 文件中 主要 了实现 uboot 的重新定位代 ,和码 bss 段的清零 ldr r0, _board_init_r_ofs 通 个方式 取 过这 获 board_init_r 函数入口 adr r1, _start add lr, r0, r1 mov pc, lr 最后 里个到这 C 函数,board_init_r 里面 board_init_r 第 2 段的初始化,在 阶 board.c 文件中 enable_caches 个函数没有做什么内容 这 board_init 第 2 次初始化平台, 里可以初始化其他内容了,和平台相关 这 mem_malloc_init 初始化 malloc 内存 nand_init 初始化 NAND(CONFIG_CMD_NAND 需要定 )义 mmc_initialize 初始化 SD(CONFIG_GENERIC_MMC 需要定 )义
/drivers/mmc/mmc.c board_mmc_init 平台相关 omap_mmc_init(ID)/drivers/mmc/omap_hsmmc.c 文件中 文件中 env_relocate 初始化 境 量环 变 /common/env_common.c 文件中 stdio_init jumptable_init console_init_r misc_init_r 平台相关,目前不知道什么用 interrupt_init enable_interrupts eth_initialize(gd->bd); 初始化以太网 /net/eth.c 文件中 board_eth_init 平台相关的代 中码 cpsw_register /driver/net/cpsw.c 注册一个以太网设备 main_loop(); 入控制台 进 init_sequence 数 里的内容 组 #if defined(CONFIG_ARCH_CPU_INIT) arch_cpu_init, /* basic arch cpu dependent setup */ #endif #if defined(CONFIG_BOARD_EARLY_INIT_F) board_early_init_f, #endif timer_init, Timer.c (arch\arm\cpu\armv7\omap-common)默 的定 器, 开始运行 认 时 刚 uboot ,那个倒 多少 后按空格 入 计时 时间 进 uboot 时 #ifdef CONFIG_FSL_ESDHC get_clocks, #endif env_init, Env_nand.c (common) uboot默 的参数,都在 里初始化 认 这 init_baudrate, 本文件中,初始化uboot使用的默 的串口波特率 认 serial_init, Serial.c (drivers\serial)初始化串口,在UBOOT中,使用的默 串口名认 字是叫NS16550,可能是因 原来就存在此代 的 故,然后 码 缘 为 继续调 ns16550.c里面的函数初 用了 始化串口 console_init_f, Console.c (common)初始化控制台 display_banner, 本文件中, 出一些信息,代表运行到了 里 输 这 #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, 本文件中,初始化IIC,然后 用继续调 Omap24xx_i2c.c (drivers\i2c), 具体的CPU IIC初始化的实现 #endif dram_init, /* configure available RAM banks */ UBOOT 用到的结构体 register volatile gd_t *gd asm ("r8") 此结构体记录了 UBOOT 所有的参数内容 typedef struct global_data { bd_t *bd; 个 是一个 构体 这 还 结 unsigned long flags; unsigned long baudrate; UBOOT串口 端所使用的串口波特率 终 unsigned long have_console; 串口控制台是否初始化 ?过 =1初始化过 //UBOOT 境 量相关的 量 环 变 变 unsigned long env_addr; 这 个是地址,存放了 uboot使用的 境 量参数存放在内 环 变 存中 的地址,例如 了 记录 uboot的ip地址, 入进 uboot默 的延 认 时时间 对应 等,和 default_environment 起来对应 unsigned long env_valid; 默 的 境 量是否有效, 认 环 变 =1代表有效 unsigned long fb_base; /* base address of frame buffer */ #ifdef CONFIG_FSL_ESDHC unsigned long sdhc_clk; #endif #ifdef CONFIG_AT91FAMILY /* "static data" needed by at91's clock.c */ unsigned long cpu_clk_rate_hz; unsigned long main_clk_rate_hz; unsigned long mck_rate_hz; unsigned long plla_rate_hz; unsigned long pllb_rate_hz; unsigned long at91_pllb_usb_init; #endif #ifdef CONFIG_ARM
/* "static data" needed by most of timer.c on ARM platforms */ unsigned long timer_rate_hz; unsigned long unsigned long tbl; tbu; unsigned long long timer_reset_value; unsigned long lastinc; #endif #ifdef CONFIG_IXP425 unsigned long timestamp; #endif unsigned long relocaddr; /* Start address of U-Boot in RAM */ phys_size_t ram_size; 内存的大小 unsigned long mon_len; uboot整个bin文件的大小 代码段+bss段 unsigned long irq_sp; IRQ中断堆 指栈 针 unsigned long start_addr_sp; /* start_addr_stackpointer */ unsigned long reloc_off; #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) unsigned long tlb_addr; #endif void char } gd_t; **jt; /* jump table */ env_buf[32]; /* buffer for getenv() before reloc. */ bi_ip_addr; IP 地址 bi_baudrate; 串口控制台波特率 typedef struct bd_info { int unsigned long ulong bi_arch_number; 传递给 LINUX 内核,告诉当前是板子的 ID ulong bi_boot_params; 传递给 linux 内核,告诉其参数存放的位置 struct { /* RAM configuration */ ulong start; ulong size; }bi_dram[CONFIG_NR_DRAM_BANKS];这个用于给 LINUX 传递启动信息的,内存大小和起始 地址,如果有多块内存,则这个变量是一个数组 } bd_t; SPL 的代码 /arch/arm/cpu/armv7/start.s 入口 /arch/arm/cpu/armv7/omap-common C 文件,
Uboot 的重定位 relocate_code: 要有 pie 选项(arm-linux-ld 命令中) mov r4, r0 mov r5, r1 /* save addr_sp */ 新的堆栈地址 /* save addr of gd */ gd_t 变量的内容地址,因为重定位后,这个地址会 改变 mov r6, r2 /* save addr of destination */ 目标地址 /* Set up the stack stack_setup: */ mov sp, r4 设置堆栈 adr r0, _start uboot 的起始运行地址 cmp r0, r6 moveq r9, #0 /* no relocation. relocation offset(r9) = 0 */ 如果代码段已经是目 标了,那么不要复制了直接跳转到 clear_bss /* skip relocation */ beq clear_bss mov r1, r6 ldr add r2, r0, r3 /* r1 <- scratch for copy_loop */ 代码段的目标地址 r3, _image_copy_end_ofs 要复制的长度 /* r2 <- source end address */ 代码段的结束地址 开始循环复制代码段 copy_loop: ldmia stmia cmp r0, r2 blo copy_loop r0!, {r9-r10} r1!, {r9-r10} /* copy from source address [r0] */ /* copy to target address [r1] */ /* until source end address [r2] */ 重定位代码,修改代码为新的地址 #ifndef CONFIG_SPL_BUILD R0 是目标内存,修改后放入目标的内存中 r0, _TEXT_BASE ldr sub r9, r6, r0 代码段的基地址 /* r0 <- Text base */ 代码段的基地址 /* r9 <- relocation offset */ 重定位的偏移值 r9=代码段目标地址 – ldr add r10, r10, r0 r10, _dynsym_start_ofs /* r10 <- sym table ofs */ r10=动态起始地址 /* r10 <- sym table in FLASH */ r10 = 动态符号表的目标存放地址 r2 是 rel_dyn 段的内容,这个段就是代表要修改的数据. 这个段都是放一个要修改的值,然后放一个标记. 偏移值分为两种:相对位移和绝对位移 ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */ 要修改地址的信息的一些变量都 放在这里 add r2, r2, r0 /* r2 <- rel dyn start in FLASH */
分享到:
收藏