Chinaunix首页 | 论坛 | 博客
  • 博客访问: 88625
  • 博文数量: 22
  • 博客积分: 938
  • 博客等级: 准尉
  • 技术积分: 305
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-16 21:27
文章存档

2010年(22)

我的朋友

分类: 嵌入式

2010-06-15 09:36:21

移植时,tekkaman提供的代码解压,用其中的文件拷贝到原版的u-boot1.3.1目录中,如提示是否覆盖原文件,选覆盖。按照他的方法, 对其进行编译配置,这步顺利完成。然后,编译,我用的是arm-linux 3.4.1,编译报错,又试用了3.3.2,2.95.3,均报错。查了资料,知道这是u-boot的浮点数类型引起,于是自已编译了一新的arm- linux 4.1版,是用crosstool0.43编译的。编译过程很顺利。完了,再用新编译的arm-linux4.1版对u-boot1.3.1编译,顺利通 过。因为我的板子上是可以正常运行u-boot1.2的(扬创公司提供的u-boot),为了方便u-boot1.3.1调试,我想将u- boot1.3.1用1.2下载到内存中运行。查了网上的相关资料,试了多次,总算可以在内存中运行了,方法很简单,将/root/u-boot- 1.3.1/board/tekkaman/tekkaman2440目录下的u-boot.lds文件中的text_base改为 0x33000000,再将/root/u-boot-1.3.1/cpu/arm920t中的start.s中

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

       bl       cpu_init_crit

#endif

此段代码中的bl cpu_init_crit注释掉,即不进行CPU的初始化工作(此工作,当前在板子上运行的u-boot1.2已完成,故不能再次进行),即改为

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

       @bl       cpu_init_crit

#endif

在下面一段代码中增加一些语句

  1. #ifdef CONFIG_S3C2440_NAND_BOOT 
  2.        @ reset NAND 
  3.        mov r1, #NAND_CTL_BASE 
  4.        ldr   r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) ) 
  5.        str   r2, [r1, #oNFCONF] 
  6.        ldr   r2, [r1, #oNFCONF] 
  7.        ldr   r2, =( (1<<4)|(0<<1)|(1<<0) )       @ Active low CE Control 
  8.        str   r2, [r1, #oNFCONT] 
  9.        ldr   r2, [r1, #oNFCONT] 
  10.        ldr   r2, =(0x6)    @ RnB Clear 
  11.        str   r2, [r1, #oNFSTAT] 
  12.        ldr   r2, [r1, #oNFSTAT] 
  13.        mov r2, #0xff      @ RESET command 
  14.        strb  r2, [r1, #oNFCMD] 
  15.        mov r3, #0       @ wait 
  16. nand1: 
  17.        add  r3, r3, #0x1 
  18.        cmp r3, #0xa 
  19.        blt    nand1 
  20. nand2: 
  21.        ldr   r2, [r1, #oNFSTAT]       @ wait ready 
  22.        tst    r2, #0x4 
  23.        beq  nand2 
  24.  
  25.        ldr   r2, [r1, #oNFCONT] 
  26.        orr   r2, r2, #0x2       @ Flash Memory Chip Disable 
  27.        str   r2, [r1, #oNFCONT] 
  28.  
  29.        @ get read to call C functions (for nand_read()) 
  30.        ldr   sp, DW_STACK_START @ setup stack pointer 
  31.        mov fp, #0       @ no previous frame, so fp=0 
  32.  
  33.     //增加的语句 
  34.        adr   r0, _start             /* r0 <- current position of code   */ 
  35.        ldr   r1, _TEXT_BASE              /* test if we run from flash or RAM */ 
  36.        cmp     r0, r1                  /* don't reloc during debug         */ 
  37.        beq     stack_setup 
  38.     ////////////////////////////// 
  39.        @ copy U-Boot to RAM 
  40.        ldr   r0, =TEXT_BASE 
  41.        mov r1, #0x0 
  42.        mov r2, #0x30000 
  43.        bl       nand_read_ll 
  44.        tst    r0, #0x0 
  45.        beq       ok_nand_read 

增加的语句是为判断是否是已在内存中运行u- boot,如是,则不进行下面一段将nand flash中的程序拷贝到内存中的操作(此操作在从nand flash中启动时,是必须的,而在内存中运行时,则不能使用,因为此时,nand flash中不一定是要调试的u-boot代码)

编译。完成后,使用tftp将u- boot.bin下载到板子的内存中,注意,内存地址一定是0x33000000,再用u-boot命令go 0x33000000,即可在内存中运行u-boot。解释一下为什么要这么做,u-boot的启动分两个阶段,第一阶段完成一些必须初始工作,此阶段是 汇编写的,第二阶段则是进行一些较高级的操作,比如初始化板上的网卡芯片了,引导内核了什么的,这部分是用C写的。第一阶段的汇编程序在编写时,采用的是 代码位置无关的方式,即无论代码的开头放在内存的哪一个地址,都可以从这个位置正常运行程序,而不管编译器在编译时认可的代码起始地址是什么。实际上,前 面修改的text_base地址,就是编译器所认为的代码起始地址。U-boot中,第一阶段进入第二阶段是直接转入第二阶段的起始地址,而第二阶段的代 码编写是与位置有关的,即代码起始地址必须与编译器认可的起始地址一至,才能正常运行。第二阶段的起始地址在编译完成后,即已确定,是相对于 text_base的地址。那么我们将代码下载到text_base指定的地址中时,第二阶段代码的头就是在它应该在的位置上了。当我们从此 text_base的地址处运行程序时,没有任何问题。而当此代码是从nand flash中运行时,第一阶段的起始地址为0,但因为第一阶段代码是位置无关,所以第一阶段代码可以正常运行,但第二阶段代码的头却不在它应该在的位置 了,所以,第二阶段不能正常运行,因为,在第一阶段中,必须将u-boot自身拷贝到text_base的地址处,这样,第二阶段的代码就在它应该在的位 置了,此时,第一阶段的程序可以顺利跳转到第二阶段运行了。这个过程,是我看了很资料后总结出来的。

完成此工作后,即可以在内存中运行u-boot了,但因为tekkaman的程序中,用的网卡芯片是DM9000,我用的是CS8900,所以要在 tekkaman.h中,将DM9000的宏注释掉,将CS8900的宏开放。在此我犯了个错误,因为我一开始没有修改此处的宏编译的程序,而我在修改过 宏以后,没有执行make clean就直接make,结果,网卡不能正常工作,总是报告cs8900 not found,试了多次不能解决,耽搁了一些时间。后来,在make clean后,再make,想不到问题解决了,想来是有些与cs8900想关的文件在修改过宏后没有重新编译所置。真是无语了。

这个问题解决后,就是要用u-boot引导linux内核了,我用的是扬创提供的linux2.6.13的内核,扬创提供的内 核,loadaddress和entry都是30008000,我用u-boot1.2中的bootcmd参数,u-boot1.3.1 bootm却不能引导,报bad magic number,看了bootm的相关资料,得知,如果我们没用mkimage对内核进行处理的话,那直接把内核下载到0x30008000再运行就行,内 核会自解压运行(不过内核运行需要一个tag来传递参数,而这个tag建议是由bootloader提供的,在u-boot下默认是由bootm命令建立 的)。
 
2)如果使用mkimage生成内核镜像文件的话,会在内核的前头加上了64byte的信息,供建立tag之用。bootm命令会首先判断bootm xxxx 这个指定的地址xxxx是否与-a指定的加载地址相同。
(1)如果不同的话会从这个地址开始提取出这个64byte的头部,对其进行分析,然后把去掉头部的内核复制到-a指定的load地址中去运行之
(2)如果相同的话那就让其原封不同的放在那,但-e指定的入口地址会推后 64byte,以跳过这64byte的头部。

Bootm在没有参数时,是采用tekkaman.h中的#define CFG_LOAD_ADDR 的地址的,而我用bootm就是没有使用参数,所以出错了。正确的做法应该是用nand read命令将内核从nand flash中读到内存的某一地址中(注意不要与其它已分配的内存冲突),然后再用bootm 加地址参数,即可引导,也可以在上述的文件中,将CFG_LOAD_ADDR的地址定义为此地址,再用bootm就可以了,我最终就是这么用的。

做完这此,内核可以引导了,但却停在starting kernel不动了,好在我以前做过vivi+linux2.6.22的移植,知道此问题多半是由于mach_type不同而造成的。在u-boot中, 此mach_type是由tekkaman.c中的这段代码定义的

#if defined(CONFIG_S3C2440)

/* arch number of S3C2440 -Board */

       gd->bd->bi_arch_number = 5244 ; //改为和内核的MACH_TYPE一至

       //gd->bd->bi_arch_number = MACH_TYPE_S3C2440 ;

#endif

你可以象我一样直接在这里改数字,也可以在include/asm-arm/mach_types.h的文件中,改 MACH_TYPE_S3C2440的数值。将数值改为和内核的mach_type一至。至于内核的mach_type可以在内核linux源代码下的 arch/arm/tools中的mach_types文件查看到。

重新编译下载u-boot1.3.1后,内核正常引导了。到此,u-boot1.3.1的移植告一段落。下面,我要做的是移植yaffs,使u- boot1.3.1可以支持yaffs文件的烧写。

阅读(1763) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~