Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1223112
  • 博文数量: 322
  • 博客积分: 10010
  • 博客等级: 上将
  • 技术积分: 3276
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-17 09:21
文章分类

全部博文(322)

文章存档

2010年(155)

2009年(167)

我的朋友

分类: 嵌入式

2009-12-24 17:13:15

首先引用《嵌入式系统 Boot Loader 技术内幕》的一段话:Boot Loader 的设计与实现是一个非常复杂的过程。如果不能从串口收到那激动人心的"uncompressing linux.................. done, booting the kernel……"内核启动信息,恐怕谁也不能说:"嗨,我的 boot loader 已经成功地转起来了!" 我对此深有体会,这就是为什么这篇文章推迟一个星期才出来的原因。

u-boot实现linux内核引导步骤:

1、U-BOOT给linux内核传递合适参数的定义

修改include/configs/fs2410.h如下:

……

……

/************************************************************

 * RTC

 ************************************************************/

#define       CONFIG_RTC_S3C24X0   1

/* allow to overwrite serial and ethaddr */

#define CONFIG_ENV_OVERWRITE

#define CONFIG_BAUDRATE        115200

 

/************************************************************/

/* enable passing of ATAGs       */

#define CONFIG_CMDLINE_TAG  1

#define CONFIG_SETUP_MEMORY_TAGS 1

#define CONFIG_INITRD_TAG       1

 

/***********************************************************

 * Command definition

 ***********************************************************/

#define CONFIG_COMMANDS \

                     (CONFIG_CMD_DFL    | \

                     CFG_CMD_CACHE     | \

                     CFG_CMD_NAND | \

                     /*CFG_CMD_EEPROM |*/ \

                     /*CFG_CMD_I2C    |*/ \

                     /*CFG_CMD_USB  |*/ \

                     CFG_CMD_REGINFO  | \

                     CFG_CMD_DATE  | \

                     CFG_CMD_ELF)

……

……

2、修改UBOOT的2410CPU频率

smdk2410的U-BOOT原来运行频率是202.8M,而FS2410的BIOS里面是200M,所以不修改频率可能会出点问题。按照网上的说法,内核中,在\arch\arm\mach_s3c2410\s3c2410.c 中,fclk = s3c2410_get_pll(MPLLCON, xtal);   //读出来的fclk结果和bootloader的频率不一致。

修改board/fs2410/fs2410.c文件如下:

#define FCLK_SPEED 1

#if FCLK_SPEED==0  /* Fout = 203MHz, Fin = 12MHz for Audio */

#define M_MDIV 0xC3

#define M_PDIV 0x4

#define M_SDIV 0x1

#elif FCLK_SPEED==1  /* Fout = 202.8MHz */

//#define M_MDIV 0xA1

//#define M_PDIV 0x3

//#define M_SDIV 0x1

#define M_MDIV 0x5c  /* Fout = 200MHz */

#define M_PDIV 0x4

#define M_SDIV 0x0

#endif

3、修改include/configs/fs2410.h中的CFG_LOAD_ADDR的地址为0x30007FC0

这是内核的加载地址,board/smdk2410/config.mk文件注释中提到Linux内核希望自己被加载到0x30008000的内存地址,而由于uImage会在kernel镜像之前加上大小为0x40的头文件消息,所以需要减去0x40。

4、制作uImage

在编译内核的时候如果用命令make uImage来生成uImage的话,我发现Load Address 30008000,  Entry Point  30008000,为什么这样我没细研究,所以我用mkimage来生成uImage,做法如下:

[root@localhost tftpboot]#mkimage -n 'linux-2.6.25' -A arm -O linux -T kernel -C none -a 0x30007fc0 -e 0x30008000 -d zImage uImage

Image Name   linux-2.6.25

Created      Thu Jul 3 101845 2008

Image Type   ARM Linux Kernel Image (uncompressed)

Data Size    1556188 Bytes =1556252 kB = 1.5 MB

Load Address 0x30007fc0

Entry Point  0x30008000

 

这里解释一下参数的意义:

        -A == set architecture to 'arch'

        -O == set operating system to 'os'

        -T == set image type to 'type'

        -C == set compression type 'comp'

        -a == set load address to 'addr' (hex)

        -e == set entry point to 'ep' (hex)

        -n == set image name to 'name'

        -d == use image data from 'datafile'

        -x == set XIP (execute in place)

这里我移植的是2.6.25内核,当然也可以:Load Address 0x30008000 、Entry Point  0x30008040

5、固化

       make修改好的u-boot,将u-boot.bin和uImage写入flash相应位置,然后设置u-boot启动命令:

[FS2410]#setenv bootargs root=1f02 init=/linuxrc console=ttySAC0,115200 devfs=mount

[FS2410]#setenv bootcmd nand read 0x30007fc0 0x40000 0x1c0000\;bootm 0x30007fc0

[FS2410]#saveenv

Saving Environment to NAND...

Erasing Nand...Writing to Nand... done

好了,可以通过printenv、bdinfo等命令查看自己的u-boot参数了,最后reset一下,如果运气好点的话,就会看到那激动人心的

Uncompressing Linux....................................................... done, booting the kernel.

之后就是一阵洋文飘过……

后记:

s3c2410上移植uboot和linux2.6内核.虽然网上的文章多多,但真正要在自己的板子上跑起来还真是问题多。其间参考了不少网上同行们的文章,受益匪浅。最后我还将调制过程中遇到的问题总结列出,供后人参考。

问题一:Load Address  、Entry Point 设置问题
Starting kernel ...
undefined instruction
pc : [] lr : []
sp : 33f4fc10 ip : 00000001 fp : 33f4fca4
r10: 33f9e70c r9 : 33ece9cd r8 : 33f4ffdcc
r7 : 33f4ffb8 r6 : 00000000 r5 : 00000000 r4 : 00000000
r3 : 30008000 r2 : c0000100 r1 : 000000c1 r0 : 00000000
Flags: nZCv IRQs off FIQs off Mode SVC_32
Resetting CPU ...

引导内核在这里进不去,网上也没一个很好的说法,由上图可知:Load Address 0x30008000 、Entry Point  0x30008000 ,#bootm的时候,显示是的内核前头加上的64byte的信息r1:000000c1 r0:00000000……按照上述制作uImage的方法设Load Address  、Entry Point 就ok。

/************下面引用了网上文章的原话********************************************************/

u-boot  调用 Linux 内核的方法是直接跳转到内核的第一条指令处,也即直接跳转到 MEM_START + 0x8000 地址处。在跳转时,要满足下列条件:

a) CPU 寄存器的设置: R0 = 0 ; R1 =机器类型 ID ,本系统的机器类型 ID = 193 。 R2 =启动参数标记列表在 RAM 中的起始基地址;

b) CPU 模式:必须禁止中断 (IRQs 和 FIQs) ; CPU 必须工作在 SVC 模式;

c) Cache 和 MMU 的设置: MMU 必须关闭;指令 Cache 可以打开也可以关闭;数据 Cache 必须关闭。

系统采用下列代码来进入内核函数:

theKernel = (void (*)(int, int))ntohl(hdr->ih_ep);

theKernel(0, bd->bi_arch_number); 其中, hdr 是 image_header_t 类型的结构体, hdr->ih_ep 指向内核的第一条指令地址,即 Linux 操作系统下的 /kernel/arch/arm/boot/compressed/head.S 汇编程序。 theKernel() 函数调用应该不会返回,如果该调用返回,则说明出错。

//theKernel(0, bd->bi_arch_number); 应该是:
      theKernel (0, bd->bi_arch_number, bd->bi_boot_params);

问题二:Starting kernel ...就没显示了.

郁闷吧,解决了第一个问题,又来了这个问题,什么都没显示了,错在哪呢?

theKernel (0, bd->bi_arch_number, bd->bi_boot_params);没有给内核正确传递参数?经过setenv修改启动参数、修改bi_arch_number的机器ID号,都未果,结果发现,优龙的linux-2.6.8.1-pxt1不能引导,我交叉编译Linux-2.6.25,制作uImage,结果正常启动,至于为什么linux-2.6.8.1-pxt1不能引导,我没做深入分析。

问题三:Uncompressing Linux....................................................... done, booting the kernel   就不动了

我没有遇到,摘用网上解法:一般这个错误有两种原因:
一个内核的commandline ,一个是由于主频设置的问题
1. 通过go启动内核的话参数用的是编译时的..而bootm则是启动的经过处理的uImage(加了一个头)
所以用bootm就会把uboot设置的commandline传给内核..如果是用bootm启动出现bootint the 
kernel没显示了.则应该好好检查一下.可以printenv打印看uboot有没设置对commandline

2.主频问题,就是在MPLLCON这个寄存器的配置上。(board/s3c2410/s3c2410.c)
在VIVI:MPLLCON = 0x0005c040;计算出来的Mpll = 200Mhz
Uboot116:MPLLCON = 0x000a1031;计算出来的Mpll = 202Mhz
 那么,及有可能就是内核已经启动,而波特率不对,使打印出问题
把MPLLCON改成 = 0x0005c040就有显示了.

问题四:Error: unrecognized/unsupported machine ID (r1 = 0x33f4fca8)

分析:

tftp uImage到0x30008000,然后,go 0x30008000,这样uboot没有传参数给内核,go命令是不传递内核参数的所以会有Error: unrecognized/unsupported machine ID (r1 = 0x33f4fca8)这样的错误
一种方法是修改common/cmd_boot.c
/*#if defined(CONFIG_I386)*/          
  DECLARE_GLOBAL_DATA_PTR;        
/*#endif*/                                        
#if !defined(CONFIG_NIOS)
      /*******************add here*******************************/    
if(argc==2)
        rc = ((ulong (*)(int, char *[]))addr) (0, gd->bd->bi_arch_number);
  else      
/*********************add end *****************************/  
          rc = ((ulong (*)(int, char *[]))addr) (--argc, &argv[1]);
解决
还可以在arch/arm/kernel/head.S写死r1
mov    r1, #0xc1

个人建议不修改,用bootm命令。

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