您的位置:首页 > 其它

tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——移植u-boot.bin(修改显示信息)

2014-07-28 14:50 393 查看
我们平时在使用u-boot时 ,u-boot启动会打印一些基本信息,比如说cpu型号、内存大小、时钟等信息,我们这节实现这些信息。现在接着上节继续分析:

在设置堆栈指针之后,接着调用 board.c 中的 board_init_f 函数,给它传了一个参数 r0=0,事实上没有用到。这个函数使用到了一些全局变量,因此我们需要让 u-boot.bin 位于其链接地址,通过修改 tiny210.h 中的宏

CONFIG_SYS_TEXT_BASE 指定其链接地址。我们将其指定为 u-boot.bin 在 DDR 中的起始地址:



继续分析u-boot-2014.04/arch/arm/lib/board.c 下的 board_init_f:



首先定义了几个重要的变量:addr最终为重定位地址,addr_sp 为最终的用户栈指针地址。



初始化全局变量 gd,同时计算出 u-boot.bin 的大小,保存到 gd->mon_len。



依次调用数组 init_sequence 中的每个函数,进行一系列初始化操作。



虽然我们对u-boot进行了裁剪,只保留了我们需要的体系,但是代码量还是很庞大,所以我们可以建立sourceInsight工程来管理代码。在数组 init_sequence中,我们分析几个重要的:

arch_cpu_init 在 u-boot-2014.04/arch/arm/cpu/armv7/s5p-common/cpu_info.c 中定义,它调用了s5p_set_cpu_id 读取 CPU 版本和 ID,保存到 s5p_cpu_rev 和 s5p_cpu_id 中。接着调用 u-boot-2014.04/arch/arm/cpu/armv7/s5p-common/timer.c 中的 timer_init 初始化 PWM 定时器接着 调用
serial_init 初始化串口 ,通过跟踪代码发现在单板配置文件 tiny210.h 中通过宏CONFIG_SERIAL0 指定使用哪个串口:



默认使用的是串口 0,我们还需要为串口 0 配置 GPIO 端口,在u-boot-2014.04/board/samsung/tiny210/lowlevel_init.S 中添加代码 :



接着调用 display_banner,显示 u-boot 版本信息,我们可以在这个函数中添加显示自己的 log,例如:



接着调用 u-boot-2014.04/arch/arm/cpu/armv7/s5p-common/cpu_info.c 中的 print_cpuinfo,打印 CPU名称和时钟



s5p_get_cpu_name 得到 CPU 的名称,在 u-boot-2014.04/arch/arm/include/asm/arch-s5pc1xx/cpu.h 中定义为:



其中 s5p_cpu_id 为一个整数,对于 S5PC100 和 S5PC110 可以通过处理得到 0xc100 和 0xc110, 打印出来就是 S5PC100 和 S5PC110,但对于 S5PV210 就没法将那个 v 用整数表示了。我们直接修改为打印S5PV210。



get_arm_clk 根据 CPU 的 ID 决定调用那个函数来获取时钟,其定义在 u-boot-2014.04/arch/arm/cpu/armv7/s5pc1xx/clock.c 中:



我们仿照 s5pc110_get_arm_clk 为 S5PV210 实现一个函数 s5pv210_get_arm_clk,为了简单化,不用去判断cpu的型号, S5PC110 和 S5PV210比较相近,然后将 get_arm_clk 修改为:





在 s5pv210_get_arm_clk 中调用了 get_pll_clk(APLL)来获得 APLL 输出时钟,其定义为:



我们将其修改为:



同样仿照 s5pc110_get_pll_clk 为 S5PV210 实现一个函数 s5pv210_get_pll_clk





这里用到一个宏 CONFIG_SYS_CLK_FREQ_V210,在单板配置文件 tiny210.h 中定义:



其实为 S5PV210 添的这 2 个函数和 S5PC110 的基本一样。

继续回到 board.c 中的 init_sequence,接着调用u-boot-2014.04/board/samsung/tiny210/tiny210.c 中的 dram_init,其定义为:



这里用到的宏 PHYS_SDRAM_1 和 PHYS_SDRAM_1_SIZE 在tiny210.h 中定义,分别为 SDRAM 的基地址和大小。这里得到内存大小,赋值给全局变量 gd->ram_size。



到这里init_sequence完成,回到board_init_f继续往下执行:



这句执行后得到:addr=0x45880000,即内存的最高地址。



这里为重定位的 u-boot 预留一块内存空间,gd->mon_len 为 u-boot 的大小



这里开始计算栈指针地址,为 malloc 预留一块内存空间,作为堆内存



这里为 bd 预留一块内存空间,同时使 gd->bd 指向现在的 addr_sp 所在地址,bd 变量保存了单板的一些信息,比如机器码



这里将配置的机器码保存到 gd->bd->bi_arch_number, 这个机器码必须和内核的机器码相同,否则启动不了内核,我们可以在 smdkv210.h 中定义这个机器码。



这里为 gd 预留一块内存空间,同时让临时变量 id 指向现在 addr_sp 所在地址



这里为 IRQ 和 FIQ 预留一块内存空间



将一些关键变量的值保持到全局变量 gd 中, 这里的_start 的地址为 0x20000000,因为在前面分析中,我们通过宏 CONFIG_SYS_TEXT_BASE 将代码段的基地址设置为 0x20000000,addr - (ulong)&_start 刚好得到重定位地址相对 u-boot 当前所处的地址(0x20000000)的偏移地址。然后将全局变量 gd 的内容复制到 id 所指向的那块内存,后面的代码会将 gd 指向这块内存。
现在的内存布局如下图所示:



然后返回到 crt0.S 的_main 函数



r9 即 gd,其中 GD_START_ADDR_SP、GD_BD、GD_SIZE、GD_RELOC_OFF 和 GD_RELOCADDR 均在u-boot-2014.04/include/generated/generic-asm-offsets.h 中定义


只要知道这两点,再结合 u-boot 的注释,这段代码就很清楚了。执行这段代码后的内存布局为:



同时将标号 here 的相对地址赋值给 lr,然后将 lr 减去将要重定位的地址相对 u-boot 当前地址的偏移,结果是 lr 保存了 u-boot 重定位后的地址, 调用 relocate_code 重定位完成后,返回跳转到 lr 地址执行(现在已经位于重定位后的区域) 。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐