一、移植环境 1.u-boot版本1.1.6 2.开发板Jz2440(ARM9 S3C2440 NAND K9F2G08 SDRAM K4S561632 * 2) 3.Linux: ubuntu 9.10 二、U-Boot移植概况 因为只是为了实验,为了方便的讲述这个过程,解压u-boot后,直接基于smdk2410修改,失败了删除再解压,所以修改文件直接在smdk2410文件夹下修改。如果使用其他开发板,请按照书中做法,新建开发板相关文件夹,这样比较规范。 没有特别说明,当前文件夹为u-boot-1.1.6根目录。 需要修改的文件及其路径:
各文件的作用说明: start.S:u-boot启动执行的第一个汇编文件。修改完成堆栈初始化、时钟初始化、SDRAM初始化(只是跳转,具体实现在lowlevel_init.S中)、拷贝代码到SDRAM中。 lowlevel_init.S:初始化Jz2440板上SDRAM。 smdk2410.c: Speed.c: boot_init.c: s3c24x0.h: | ||||||||||||||
西伯利亚的风 最后编辑于 2012-03-06 22:16:09
本主题由 版主 wuweidong 于 2012-3-3 17:14:52 执行 移动主题 操作
| ||||||||||||||
| ||||||||||||||
UID
3089
精华
6
西伯利亚的风
|
字体大小: t T 发表于 2012-03-02 21:01 | 三、U-Boot移植操作 我们先根据书上的指导,完成部分操作,然后根据开发板的实际情况(只有NAND,没有Nor FLASH)进行调整,最后针对遇到的问题,各个击破,从而解决问题。 1.引经据典 韦东山老师编著的《嵌入式Linux应用开发完全手册》是一部内容详实、通俗明了、非常适合自学的一本书。下面就根据书中提示,开始我们的移植工作。 (1)修改SDRAM的配置 参考《嵌入式Linux应用开发完全手册》第十五章15.2.5节,修改SDRAM的配置,主要修改lowlevel_init.S(路径:board/smdk2410/lowlevel_init.S)中 REFCNT寄存器的值。将 #define REFCNT 1113 改为 #define REFCNT 0x4f4 至于为什么这样修改,请参考《嵌入式Linux应用开发完全手册》,里面讲的很透彻。 (2)增加对S3C2440的支持 由于S3C2440与S3C2410的MPLL与UPLL计算公式不一样,FCLK、HCLK、和PCLK的分频设置也不一样,所以需要修改smdk2410.c (路径:board/smdk2410/smdk2410.c)中board_init()函数。由于代码太多,再次就不一一贴代码了,请参阅《嵌入式Linux应用开发完全手册》P266页的代码,完全一样。 (3)修改系统获取时钟的函数 最后一步:获取系统时钟的函数需要针对S3C2410、S3C2440的不同进行修改。 在后面设置串口波特率时需要获取系统时钟,如果此处没有设置,可能U-Boot启动后串口无输出或工作不正常。所以需要修改speed.c (路径:cpu/arm920t/s3c24x0/speed.c)中的get_PLLCLK()、get_HCLK()、get_PCLK()这三个函数。代码太多,请参阅《嵌入式Linux应用开发完全手册》P269—P272页,与其一样即可。 按照书上提示,完成以上三步,编译下载U-Boot就能看见串口有输出。我照着做了,可是很不幸,没有输出。不过没有关系,聪明的读者一眼就能发现问题,书上移植前提是代码在Nor FLASH上,而Jz2440开发板只有NAND FLASH,没有Nor FLASH,也就是说代码是存在NAND FLASH上的,怎么办?请看下一小节。 |
| |
UID
3089
精华
6
西伯利亚的风
|
字体大小: t T 发表于 2012-03-02 21:04 | 2.系统调整 (1)增加NAND支持 既然只有NAND FLASH,也就是说U-Boot存在于NAND FLASH上,在U-Boot启动的过程中,需要将U-Boot从NAND FLASH拷贝到已经初始化了的SDRAM中去运行,我们就额外增加一个文件boot_init.c实现读NAND FLASH的功能。文件boot_init.c是韦东山老师为Jz2440编写,主要根据NAND FLASH型号,实现了CopyCode2Ram()函数,将NAND FLASH上数据复制到SDRAM中。 我们需要做的是,获取boot_init.c文件,放在board/smdk2410/boot_init.c处,并修改该目录下的Makefile(board/smdk2410/Makefile)。 COBJS := smdk2410.o flash.o 改为 COBJS := smdk2410.o boot_init.o flash.o 然后在start.S(路径:cpu/arm920t/start.S)中修改,以调用CopyCode2Ram()函数,实现代码拷贝。 修改前: relocate: /* relocate U-Boot to RAM */ adr r0, _start /* r0 <- current position of code */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ cmp r0, r1 /* don't reloc during debug */ beq stack_setup ldr r2, _armboot_start ldr r3, _bss_start sub r2, r3, r2 /* r2 <- size of armboot */ add r2, r0, r2 /* r2 <- source end address */ copy_loop: ldmia r0!, {r3-r10} /* copy from source address [r0] */ stmia r1!, {r3-r10} /* copy to target address [r1] */ cmp r0, r2 /* until source end addreee [r2] */ ble copy_loop 修改后: relocate: /* relocate U-Boot to RAM */ adr r0, _start /* r0 <- current position of code */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ cmp r0, r1 /* don't reloc during debug */ beq stack_setup ldr r2, _armboot_start ldr r3, _bss_start sub r2, r3, r2 /* r2 <- size of armboot */ bl CopyCode2Ram /* 调用函数CopyCode2Ram()*/ #if 0 add r2, r0, r2 /* r2 <- source end address */ copy_loop: ldmia r0!, {r3-r10} /* copy from source address [r0] */ stmia r1!, {r3-r10} /* copy to target address [r1] */ cmp r0, r2 /* until source end addreee [r2] */ ble copy_loop #endif其中红色部分为添加的代码,蓝色部分为注释掉的代码。 (2)修改启动时钟初始化 在smdk2410的U-Boot启动代码中,第一阶段,start.S中将系统时钟初始化为120MHz,对于Jz2440,我们需要将时钟初始化为100MHz。 初始化函数clock_init()存放于boot_init.c中(board/smdk2410/boot_init.c)。在启动代码中我们调用clock_init()函数即可。在start.S(路径:cpu/arm920t/start.S)中,我们修改如下: #if 0 /* FCLK:HCLKCLK = 1:2:4 */ /* default FCLK is 120 MHz ! */ ldr r0, =CLKDIVN mov r1, #3 str r1, [r0] #endif #ifndef CONFIG_SKIP_LOWLEVEL_INIT bl clock_init #endif 绿色为预编译注释掉的代码(也就是smdk2410中将时钟设置为120MHz),蓝色是在其后增加的代码,用于调用clock_init()函数,初始化系统时钟。 |
| |
UID
3089
精华
6
西伯利亚的风
|
字体大小: t T 发表于 2012-03-02 21:09 | 四、疑难杂症 现在,按照书《嵌入式Linux应用开发完全手册》讲述的操作已经完成,也添加了从NAND FLASH启动的代码,想想 应该是可以了,我们编译试试看。 (1)初步编译 首先配置u-boot。在u-boot-1.1.6根目录(u-boot-1.1.6#)输入命令make smdk2410_config,回车运行。出现提示: Configuring for smdk2410 board... 表示配置完成。 然后编译,输入make命令,回车,开始编译。 出现了一堆错误: boot_init.c: In function `s3c2440_wait_idle': boot_init.c:133: error: `S3C2440_NAND' undeclared (first use in this function) … boot_init.c:221: error: `isS3C2410' undeclared (first use in this function) … make[1]: *** [boot_init.o] Error 1 make[1]: Leaving directory `/home/book/workspace/U-Boot/Jz_u-boot-1.1.6/board/smdk2410' make: *** [board/smdk2410/libsmdk2410.a] Error 2 看来还是不行,还有很多问题要解决,下面就根据各种错误进行修改。 (2)S3C2440_NAND未定义 经过仔细分析,发现一个文件s3c24x0.h (路径:include/s3c24x0.h)中有类似的定义S3C2410_NAND: /* NAND FLASH (see S3C2410 manual chapter 6) */ typedef struct { S3C24X0_REG32 NFCONF; S3C24X0_REG32 NFCMD; S3C24X0_REG32 NFADDR; S3C24X0_REG32 NFDATA; S3C24X0_REG32 NFSTAT; S3C24X0_REG32 NFECC; } /*__attribute__((__packed__))*/ S3C2410_NAND; 我们就仿照其定义S3C2440_NAND,在文件s3c24x0.h (路径:include/s3c24x0.h)中增加如下代码: typedef struct { S3C24X0_REG32 NFCONF; S3C24X0_REG32 NFCONT; S3C24X0_REG32 NFCMD; S3C24X0_REG32 NFADDR; S3C24X0_REG32 NFDATA; S3C24X0_REG32 NFMECCD0; S3C24X0_REG32 NFMECCD1; S3C24X0_REG32 NFSECCD; S3C24X0_REG32 NFSTAT; S3C24X0_REG32 NFESTAT0; S3C24X0_REG32 NFESTAT1; S3C24X0_REG32 NFMECC0; S3C24X0_REG32 NFMECC1; S3C24X0_REG32 NFSECC; S3C24X0_REG32 NFSBLK; S3C24X0_REG32 NFEBLK; } /*__attribute__((__packed__))*/ S3C2440_NAND; 然后再次make编译,看看还有什么错误。 提示: boot_init.c: In function `nand_reset': boot_init.c:221: error: `isS3C2410' undeclared (first use in this function) boot_init.c:221: error: (Each undeclared identifier is reported only once boot_init.c:221: error: for each function it appears in.) …… make[1]: *** [boot_init.o] Error 1 make[1]: Leaving directory `/home/book/workspace/U-Boot/Jz_u-boot-1.1.6/board/smdk2410' make: *** [board/smdk2410/libsmdk2410.a] Error 2 原来是isS3C2410未定义 (3)isS3C2410未定义 还是在文件s3c24x0.h (路径:include/s3c24x0.h)中,在其末尾增加两行宏定义,用于自动识别cpu是s3c2410还是s3c2440: #define rGSTATUS1 (*(volatile unsigned *)0x560000B0) #define isS3C2410 ((rGSTATUS1 & 0xffff0000) == 0x32410000) 添加完毕,再次make编译。出现错误: speed.c: In function `get_HCLK': speed.c:123: error: structure has no member named `CAMDIVN' speed.c: In function `get_PCLK': speed.c:171: error: structure has no member named `CAMDIVN' make[1]: *** [speed.o] Error 1 make[1]: Leaving directory `/home/book/workspace/U-Boot/Jz_u-boot-1.1.6/cpu/arm920t/s3c24x0' make: *** [cpu/arm920t/s3c24x0/libs3c24x0.a] Error 2 提示成员CAMDIVN未定义。 (4)CAMDIVN未定义 根据提示找到其结构体,发现是s3c2440中引入了一个寄存器CAMDIVN ,s3c2410中没有,所以S3C24X0_CLOCK_POWER中未定义。我们自己加上即可。 修改前: typedef struct { S3C24X0_REG32 LOCKTIME; S3C24X0_REG32 MPLLCON; S3C24X0_REG32 UPLLCON; S3C24X0_REG32 CLKCON; S3C24X0_REG32 CLKSLOW; S3C24X0_REG32 CLKDIVN; } /*__attribute__((__packed__))*/ S3C24X0_CLOCK_POWER; 修改后 typedef struct { S3C24X0_REG32 LOCKTIME; S3C24X0_REG32 MPLLCON; S3C24X0_REG32 UPLLCON; S3C24X0_REG32 CLKCON; S3C24X0_REG32 CLKSLOW; S3C24X0_REG32 CLKDIVN; S3C24X0_REG32 CAMDIVN;} /*__attribute__((__packed__))*/ S3C24X0_CLOCK_POWER; 红色就是我们自己添加的成员CAMDIVN。 然后再次make。提示: arm-linux-objcopy --gap-fill=0xff -O srec u-boot u-boot.srec arm-linux-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin 编译成功! 然后使用oflash下载到Jz2440开发板。连接好开发板与PC串口,打开串口工具(波特率:115200 8N1),重启开发板,观察串口输出。 串口没有输出!!! 看来还是存在问题,纠结啊! |
| |
UID
3089
精华
6
西伯利亚的风
|
字体大小: t T 发表于 2012-03-02 21:18 | (5)串口无输出 仔细分析串口文件serial.c(cpu/arm920t/s3c24x0/serial.c)发现没有问题,时钟初始化也没有问题,百思不得其解! 后来从头开始分析,从start.S(路径:cpu/arm920t/start.S)开始,分析u-boot第一阶段启动流程,U-Boot第一阶段启动流程如图1 所示。
(50.96 K)
2012-3-2 22:22:38
(49.76 K)
2012-3-2 22:22:38
附件: 免费视频下载地址: 第1期共33个视频,免费,下载后可以直接观看,下载地址: 第二期视频主要是驱动深入讲解,精华啊! 第二期视频需要收费的哦,具体见韦东山老师淘宝店铺: 书籍资料下载: 《嵌入式Linux应用开发完全手册》及相关资源电炉可以下载:
|