根据朱有鹏老师课堂Uboot 2013.10版本移植到S5pv210开发板上第一阶段

前期准备:

1.uboot下载地址 ftp://ftp.denx.de/pub/u-boot/

2.参照物开发板的选择

我们开发板使用的CPUS5PV210,所以要找uboot中针对S5PV210或者S5PC110进行移植的作为参考。根据规律,我们应该参考include/configs/s5p_goni.h,对应的boarduboot/board/samsung/goni这个目录。

3.删除无关文件和文件夹,其实不删除也可以,但是删除更好。

4.建立SI工程并预解析

 



 

(1)参照物开发板为:55p_goni make s5p_goni_config

(2)配置对应的cpuboard文件夹分别为:

cpu: u-boot-2013.10\arch\arm\cpu\armv7

board: u-boot-2013.10\board\samsung\goni

 

开始移植

1.添加交叉编译工具链

  在主Makefile CROSS_COMPILE = /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-

2.配置,编译,测试

(1)编译过程:

make distclean

make s5p_goni_config

make

(2)结果:得到u-boot.bin即可

3.推荐linux下脚本烧入

 移植原来的版本的uboot中的sd_fusing文件夹到官方uboot版本中,使用这个文件夹中的sd_fusing.sh脚本来进行烧录

4.烧入后,串口现象;

(1)串口接串口2,串口有输出。但是这个串口输出不是uboot输出的,而是内部iROM中的BL0运行时输出的。

(2)输出错误信息分析:

第一个SD checksum Error:是第一顺序启动设备SD0iNand)启动时校验和失败打印 出来的;

第二个SD checksum Error:是第二顺序启动设备SD2(外部SD卡)启动时校验和失败 打印出来的;

剩下的是串口启动和usb启动的东西,可以不管。

总结:从两个SD checksum Error,可以看出:外部SD卡校验和失败了。

分析:SD卡烧录出错了,导致SD卡校验和会失败。发现是mkbl1程序和start.S中前16个字节校验和的处理上面不匹配造成的,解决方法是在start.S最前面加上16个字节的占位。

 

5.上述问题的解决方法:

参考之前的start.S发现有16字节占位。直接复制粘贴到本版本的start.S的相应位置。

\u-boot-2013.10\arch\arm\cpu\armv7\start.S  

根据朱有鹏老师课堂Uboot 2013.10版本移植到S5pv210开发板上第一阶段_第1张图片


重新编译烧录运行,发现结果只显示一个SD checksum Error。这一个就是内部SD0通道inand启动校验和失败打印出来的。剩下的没有了说明外部SD卡校验和成功了,只SD卡上的uboot是错误的,没有串口输出内容,所以没有输出了。

 

3.继续分析start.S


(1)#define CONFIG_SYS_TEXT_BASE 0x34800000  可以看出我们的uboot连接地址是在0x34800000位置

(2)cpu_init_cp15这个函数功能是设置MMUcache等。这个版本的uboot中未使用虚拟地址,因此MMU在这里直接关掉。

(3)cpu_init_crit,这个函数里只有一句跳转指令,短跳转到lowlevel_init函数。

Lowleve_init 分析:

lowlevel_init函数在board/samsung/goni目录下,主要作用是时钟设置、串口设置、复位状态判断···这个函数是S5PC100S5PC110两个CPU共用的。

经过浏览,发现lowlevel_init函数中做的有意义的事情有:关看门狗、调用uart_asm_init来初始化串口、并没有做时钟初始化(下面有时钟初始化的函数,但是实际没调用。如果uboot中没有初始化时钟,那么时钟就是iROM中初始化的那种配置)

 

7.添加开发板制锁和串口打印字符"O"

(1)我们为了调试uboot的第一阶段,就要看到现象。为了看到现象,我们向lowlevel_init函数中添加2个代码,一个是开发板制锁,在watchdog

// 我们添加的开发板供电制锁的代码

ldr r0, =0xE010E81C

ldr r1, =0x301

str r1, [r0]

一个是串口打印"O"在串口初始化最后

// 串口2输出字符'O'

ldr r1, =0x4f4f4f4f

ldr r2, =0xE2900820

str r1, [r2] @'O'

 

(2)这两段代码可以直接从ARM裸机全集课程中的代码中来。其实也可以从三星移植版本的uboot中来,但是因为三星移植版本中用到了很多寄存器定义,涉及到头文件的, 所以移植过来不方便。

(3)实践添加。

实践结果及分析

(1)实验结果是:没看到开发板制锁,串口也没有输出任何东西。实验失败。

(2)结论:因为开发板制锁没有成功,所以我们判定,在开发板制锁代码运行之前uboot 就已经挂掉了。下面就是去跟踪代码运行,然后判定问题点再去解决

 

8.添加LED点亮代码跟踪程序运行

(1)在基础代码阶段,串口还没有运行,串口调试工具还无法使用时,使用LED点亮的方式来调试程序就是一个有力的手段。

(2)有些情况下可以用Jlink等调试工具来调试这种基础代码。

(3)从程序的基本运行路径端出发,隔一段给他添加一个LED点亮代码,然后运行时根据现象来观察,判定哪里执行了哪里没执行。从而去定位问题。

(4)从以前的裸机代码中组织出一个标准的LED点亮然后延时一段的一个标准代码段:

ldr r0, =0x11111111

ldr r1, =0xE0200240

str r0, [r1]

ldr r0, =((1<<3) | (0<<4) | (1<<5)) // 1是灭,0是亮

ldr r1, =0xE0200244

str r0, [r1]

ldr r2, =9000000 //延时函数

ldr r3, =0x0

delay_loop:

sub r2, r2, #1

cmp r2, r3

bne delay_loop

(5)之前做实验时发现一个现象:我们的uboot运行时按住电源开关时所有4LED都是亮的。所以我们做实验时给LED点亮是看不到现象的,所以我们的代码关键是要熄灭某些LED来判断。

(6)我们将熄灭LED的函数在start.S中隔一段的关键部位放上1个,然后运行时通过观察LED的点亮熄灭状态,就知道程序运行到哪里了。

(7)经过判断我们发现:start.S中工作一切正常,但是函数一旦放到lowlevel_init.S中就完全不工作了。通过分析得出结论:b lowlevel_init这句代码出了问题。

 

9.解决问题

(1)问题分析:跳转代码出了问题。分析问题出在代码的连接上。

(2)三星S5PV210要求BL1大小为8KB,因此uboot第一阶段代码必须在整个uboot镜像的前8KB内,否则跳转不到。

(3)对比三星移植版本的ubootu-boot.lds和官方版本uboot的连接脚本u-boot.lds(注意这两个版本的uboot的连接脚本的位置是不同的),就发现lowlevel_init.S的代码段没有被放在前面。

(4)u-boot.ldsstart.o后面添加board/samsung/goni/lowlevel_init.o (.text*),这个就保证了lowlevel_init函数被连接到前面8kb中去。

 

 

(5)报错,lowlevel_init重复定义了。

修改board/samsung/goni/Makefile解决编译问题

(1)问题分析:为什么会重复定义。因为lowlevel_init这个函数被连接时连接了2次。一次是board/samsung/goni这个目录下生成libgoni.o时连接了1次,第2次是连接脚本最终在连接生成u-boot时又连接了一次,所以重复定义了。

(2)这个错误如何解决?思路是在libgoni.o中不要让他连接进lowlevel_init,让他只在最终连接u-boot时用1次,就可以避免重复定义。

(3)参考当前版本的ubootstart.S文件的处理技巧,解决了这个问题。

实践验证。

结果是开发板制锁和串口输出'O'都成功了

 

DDR初始化

分析下一步移植路线

(1)cpu_init_crit函数成功初始化串口、时钟后,转入_main函数,函数在arch/arm/lib/crt0.S文件中。

(2)crt0.S中首先设置栈,将sp指向DDR中的栈地址;然后调用board_init_f函数进行板级初始化。函数在arch/arm/lib/board.c中。

(3)在这个版本的uboot中,把以前uboot的第二阶段start_armboot函数分成了2部分:board_init_fboard_init_r。所以在这里就和以前版本的uboot接轨上了,推测board_init_f中肯定是做了板级初始化,board_init_r中进入了uboot的命令行。

(4)分析到这里,在uboot2013.10版本中思路已经很清晰了:uboot的第二阶段就在crt0.

(5)分析到这里,下一步工作方向就确定了。我们要先在cpu_init_crit函数中添加DDR初始化,然后在start.Sbl _main之前添加uboot的重定位,然后将bl _main改成ldr pc, __main(__main: .word _main)长跳转。然后在crt0.Sboard_init_f后删除那些重定位代码,至此uboot的第二阶段就应该能启动起来了。后续的移植就是第二阶段了。

根据朱有鹏老师课堂Uboot 2013.10版本移植到S5pv210开发板上第一阶段_第2张图片


该版本没有DDR初始化代码需要从三星官方移植

动手移植

(1)添加cpu_init.S文件到uboot2013.10中。注意,这里的代码必须保证在前8kb内,所以必须和lowlevel_init.S文件一样的链接处理。主要是在board/samsung/goni/Makefile中和arch/arm/cpu/u-boot.lds文件中做修改添加。

(2)Lds

根据朱有鹏老师课堂Uboot 2013.10版本移植到S5pv210开发板上第一阶段_第3张图片

Makefile中:

根据朱有鹏老师课堂Uboot 2013.10版本移植到S5pv210开发板上第一阶段_第4张图片

(2)添加头文件s5pc110.hinclude目录下。

(3)cpu_init.S文件代码进行修整,把一些无用的代码去掉,把一些相关的条件编译人工处理一下。

(4)SourceInsigt工程中添加入这两个文件。然后重新解析一遍。然后对新添加的代码进行分析修整,把里面一些明显的宏定义缺失给补上。

(5)DDR配置参数,从三星版本的smdkv210single.h中复制到s5p_goni.h

lowleve_init.S中,调用mem_ctrl_asm_init 然后在后面打印“K

根据朱有鹏老师课堂Uboot 2013.10版本移植到S5pv210开发板上第一阶段_第5张图片

(6)s5pc110.h中进行修整。

(7)结果:看到了"OK"标志,说明DDR添加实验成功

DDR初始化:1复制三星的cpu_init.S到和lowleve_init.S在同一文件下,并进行修改删除,再makefile中作为依赖添加上;再在链接脚本u-boot.lds中链接到前面。2将所需要的配置宏定义从本来的.h文件中复制到本版本的配置头文件.h中。3cpu_init.S所需要的板级宏定义的头文件s5pc110.h复制到相对位置一样的文件夹中,并进行修改删除。4lowleve_init.S中,调用mem_ctrl_asm_init 然后在后面打印“K

 

重定位

 

 bl cpu_init_critb lowlevel_init @ go setup pll,mux,memory里面只有这一句)也可以说在b lowlevle后开始重定位相关代码。

/重定位开始

 

/* get ready to call C functions设置栈 */

ldr sp, _TEXT_BASE /* setup temp stack pointer */

sub sp, sp, #12

mov fp, #0 /* no previous frame, so fp=0 */

 

/* when we already run in ram, we don't need to relocate U-Boot.

 * and actually, memory controller must be configured before U-Boot

 * is running in ram.检查需不需要重定位

 */

ldr r0, =0xff000fff

bic r1, pc, r0 /* r0 <- current base addr of code */

ldr r2, _TEXT_BASE /* r1 <- original base addr in ram */

bic r2, r2, r0 /* r0 <- current base addr of code */

cmp     r1, r2                  /* compare r0, r1                  */

beq     after_copy /* r0 == r1 then skip flash copy  */

若相等则不需要重定位直接跳到after_copy

 

/* If BL1 was copied from SD/MMC CH2 *判断通道2 sd卡启动*/

ldr r0, =0xD0037488

ldr r1, [r0]

ldr r2, =0xEB200000

cmp r1, r2

beq     mmcsd_boot

 

mmcsd_boot:

bl movi_bl2_copy /*跳转重定位函数copy,在movi.c

 

after_copy:

clear_bss:

ldr r0, _bss_start /* find start of bss segment        */

ldr r1, _bss_end /* stop here                        */

mov r2, #0x00000000 /* clear                            */

/*bss段,注意链接地址,需要移植修改*/

/*

 * These are defined in the board-specific linker script.

 */

.globl _bss_start

_bss_start:

.word __bss_start

 

.globl _bss_end

_bss_end:

.word _end

 

 

clbss_l:

str r2, [r0] /* clear loop...                    */

add r0, r0, #4

cmp r0, r1

ble clbss_l

 

//bl _main 第一阶段和第二阶段的过度,分析得_mian函数为uboot第二阶段,做长跳转

 

ldr pc, __main

 

 __main:

.word _main

 

需要移植movi_bl2_cop函数,

所在的文件movi.c复制到\u-boot-2013.10\board\samsung\goni,lowleve.S同样的操作在Makefikeu-boot.lds,删除不需要的函数,再确保宏定义可用,在s5p_goni配置头文件中添加修改。

复制所需要的头文件到相应位置movi.h

 

后续:将_main(在crt0.S)中的有关重定位的代码删掉

编译中出现问题解决

(1)movi.h中宏定义出错,最后在s5p_goni.h中添加了CONFIG_EVT1这个宏解决了

(2)连接错误:u-boot contains relocations other thanR_ARM_RELATIVE

uboot下用grep "R_ARM_RELATIVE" -nR *搜索,发现Makefile中有一个检查重定位的规则,屏蔽掉这个规则后编译连接成功。

 

结果验证及下阶段展望

(1)看到了uboot启动打印出来的一系列信息,但是uboot没有进入命令行。

(2)这说明uboot中的DDR初始化和重定位功能都已经完美实现,后面就是第二阶段的继续移植了。

 根据朱有鹏老师课堂Uboot 2013.10版本移植到S5pv210开发板上第一阶段_第6张图片



你可能感兴趣的:(根据朱有鹏老师课堂Uboot 2013.10版本移植到S5pv210开发板上第一阶段)