Linux-2.6.32.2内核在mini2440上的移植(四)---根文件系统制作(3)

 

移植环境(红色粗字体字修改后内容,蓝色粗体字为特别注意内容)

1,主机环境:VMare下CentOS 5.5 ,1G内存。

2,集成开发环境:Elipse IDE

3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-linux-gnueabi-gcc v4.5.1。

4,开发板:mini2440,2M nor flash,128M nand flash。

5,u-boot版本:u-boot-2009.08

6,linux 版本:linux-2.6.32.2

7,参考文章:

嵌入式linux应用开发完全手册,韦东山,编著。

Mini2440 之Linux 移植开发实战指南

制作linux下根文件系统

系统启动挂载根文件系统时Kernel panic

 接上篇,回到nand flash分区的挂载问题

【6】将上篇文章中制作好的mtd-uitls工具位于/root/linux-test/mtdtools/mtd-utils/usrdir/sbin目录下工具复制到已经制作的根文件系统的usr/sbin目录下

[root@localhost mtdtools]# cp -a mtd-utils/usrdir/usr/sbin/* /nfsboot/rootfs/usr/sbin/
[root@localhost mtdtools]#

【7】测试mtd工具的正确性,有关mtd工具的使用请参考mtd-utils 工具的使用

在min2440启动后,在终端中运行

[root@mini2440 /]#flash_info
Illegal instruction
[root@mini2440 /]#

      网上搜索发现,illegal instruction是非法指令,出现 illegal instruction 的原因是程序收到了SIGILL信号,而这个信号是cpu在发现非法指令之后发出一个异常,然后由负责处理该异常的内核的ISR对含有这个非法指令的进程发出的。程序收到这个信号,一般就是报告 illegal instruction 错误信息。

       可执行程序含有非法指令的原因,一般也就是cpu架构不对,编译时指定的march和实际执行的机器的march不同。这种情况,因为工具链一样,连接脚本一样,所以可执行程序可以执行,不会发生exec format error。但是会包含一些不兼容的指令。还有另外一种可能,就是程序的执行权限不够,比如在目态下运行的程序只能执行非特权指令,一旦CPU遇到特权指令,将产生illegal instruction错误。

       在系统运行过程中,处理机状态是动态变化的。从目态转换为管态只能通过中断来实现。从管态到目态的转换可通过修改程序状态字PSW来实现。很有可能是你编译和运行的CPU架构或者内核不一样导致。

       另外,linux是sysV风格的UNIX系统,freeBSD是BSD风格的UNIX系统。

编译器支持新的嵌入式应用程序二进制接口标准EABI,而kernel默认并未打开对eabi的支持,编绎使用的是非EABI的编译器。这时需要

Kernel Features  ---> 

 [*] Use the ARM EABI to compile the kernel (CONFIG_AEABI=y)                       
 [*]   Allow old ABI binaries to run with this kernel (EXPERIMENTA) (CONFIG_OABI_COMPAT=y)

尝试方式一

配置内核打开eabi 和old eabi支持选项,然后复制编译器下lib库文件到目标板lib库中(arm-linux-gcc v4.4.3)

[root@localhost ~]# cp -a  /usr/local/arm/4.4.3/lib/ /nfsboot/rootfs/lib
[root@localhost ~]#

然后用arm-linux重新编译生成的工具位于mtdtools/mtd-utils/mtd_install/usr/sbin复制到根目录usr/sbin

[root@localhost ~]# cp -a  ./linux-test/mtd-utils-1.4.4/mtd_install/usr/sbin/ /nfsboot/rootfs/usr/sbin

再次启动min2440后,在终端中运行

[root@mini2440 /]#flash_info
Illegal instruction
[root@mini2440 /]#

经过仔细检查,上面的操作有点问题,就是cp的的结果是lib下又建了一个lib目录,sbin下又建了一个sbin目录,现在分别将lib下的lib子目录和sbin下的sbin子目录的文件移动到上一级的目录中,替换掉之前已经存在相应文件,正确的操作

[root@localhost ~]# cp -av  /usr/local/arm/4.4.3/lib/* /nfsboot/rootfs/lib

[root@localhost ~]# cp -av  ./linux-test/mtd-utils-1.4.4/mtd_install/usr/sbin/* /nfsboot/rootfs/usr/sbin

[root@mini2440 /]#flash_info
Usage: flash_info device

OK,总算得到了可以在目标板上执行的mtd操作工具!

尝试方式二

参考Illegal instruction的解决方法这篇文章,把/usr/local/arm/compiler/arm-none-linux-gnueabi/libc/armv4t/lib目录(也就是你的编译器的库目录)下的所有文件拷贝到根目录的lib目录下,然后修改内核Makefile使CROSS=arm-none-linux-gnueabi- (即v4.5.1版本,arm-linux-是友善官方提供的4.4.3版本)。

(1)修改linux-2.6.32.2根目录下Makefile的CROSS_COMPILE

[root@localhost linux-2.6.32.2]# vim Makefile
打开编辑器后在命令模式下执行

/CROSS

然后定位到

export KBUILD_BUILDHOST := $(SUBARCH)
ARCH            ?= arm
CROSS_COMPILE   ?=
arm-none-linux-gnueabi-

# Architecture as present in compile.h
然后保存退出,执行

[root@localhost linux-2.6.32.2]# make clean
[root@localhost linux-2.6.32.2]# make uImage
重新生成uImage映像

(2)将编译内核的编译器用lib库复制到目标板根文件系统的lib目录下

[root@localhost linux-2.6.32.2]# cp -a /usr/local/arm/compiler/arm-none-linux-gnueabi/libc/armv4t/lib/* /nfsboot/rootfs/lib

这里将方式二作为备用处理手段放到这里。

【8】首先了解下/dev/mtd和/dev/mtdblock的区别

(1)/dev/mtdn是linux中的MTD架构中,系统自己实现的mtd分区所对应的字符设备,其里面添加了一些ioctl,支持很多命令,如MEMGETINFO,MEMERASE等。而mtd-util中的flash_eraseall等工具,就是以这些ioctl为基础而实现的工具,实现一些关于flash的操作,比如,mtd工具中的flash_erase等。

if(ioctl(fd,MEMGETINFO,&meminfo) != 0)
 {
  perror("MEMGETINFO");
  close(fd);
  exit(1);
 }

其中,MEMGETINFO,就是linux mtd中的\drivers\mtd\nand\mtdchar.c中的:

 case MEMGETINFO:
  info.type = mtd->type;
  info.flags = mtd->flags;
  info.size = mtd->size;
  info.erasesize = mtd->erasesize;
  info.writesize = mtd->writesize;
  info.oobsize = mtd->oobsize;
  /* The below fields are obsolete */
  info.ecctype = -1;
  info.eccsize = 0;
  if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))
   return -EFAULT;
  break;

而/dev/mtdblockn,是NandFlash驱动中,驱动在用add_mtd_partitions()添加MTD设备分区而生成的对应的块设备。根据以上内容也更加明白,为什么不能用nandwrite,flash_eraseall,flash_erase等工具去对/dev/mtdblockn去操作了,因为/dev/mtdblock中不包含对应的ioctl,不支持你这么操作。

(2)mtd char设备的主设备号是90;而mtdblock设备的主设备号是31;

     此设备号定义在\include\linux\mtd\mtd.h中

(3)mtd块设备的大小可以通过查看分区信息来得到:

[root@mini2440 /]#cat proc/partitions
major minor  #blocks  name

  31        0        256 mtdblock0
  31        1        128 mtdblock1
  31        2       5120 mtdblock2
  31        3     125568 mtdblock3
  31        4     131072 mtdblock4
[root@mini2440 /]#

上面显示的块设备的大小,是block的数目,每个block是1KB;而每个字符设备,其实就是对应着上面的饿每个设备,即/dev/mtd0对应/dev/mtdblock0,以此类推,换句话说,mtdblockn的一些属性,也就是mtdn的属性,比如大小。

(4)对每个mtd字符设备的操作,比如利用nandwrite去对/dev/mtd0写数据,实际就是操作/dev/mtdblock0。而这些操作里面涉及到得offset都指的是mtd分区内的偏移。比如向/dev/mtd1的offset为0的位置写入数据,实际操作的物理偏移是offset=/dev/mtd0的大小=128KB。

【9】向mtdblock3分区中写入根文件系统

(1)查看分区信息

[root@mini2440 /]#mtd_debug info /dev/mtd3
mtd.type = MTD_NANDFLASH
mtd.flags = MTD_CAP_NANDFLASH
mtd.size = 128581632 (122M)
mtd.erasesize = 131072 (128K)
mtd.writesize = 2048 (2K)
mtd.oobsize = 64
regions = 0

(2)擦除nand 的mtd3分区
 [root@mini2440 /]#flash_erase dev/mtd3 0x560000 0x1e0
Erasing 128 Kibyte @ 4140000 -- 100 % complete
[root@mini2440 /]#mount -t yaffs dev/mtd3 mnt/yaffs
mount: mounting dev/mtd3 on mnt/yaffs failed: Block device required
[root@mini2440 /]#mount -t yaffs dev/mtdblock3 mnt/yaffs
yaffs: dev is 32505859 name is "mtdblock3" rw

(3)挂载/dev/mtdblock3 到/mnt/yaffs

[root@mini2440 /mnt]#ls yaffs
[root@mini2440 /mnt]#mount -t yaffs /dev/mtdblock3 yaffs
yaffs: dev is 32505859 name is "mtdblock3" rw
yaffs: passed flags ""

(4)将打包好的rootfs.tar.gz文件系统解压到刚刚挂载的yaffs目录下,注意要去掉其结对路径,解压后显示的是根文件系统内容

[root@mini2440 /mnt]#ls yaffs
bin         etc         lib         mnt         sbin        usr
boot        home        linuxrc     proc        sys         var
dev         init        lost+found  root        tmp         www

【10】修改u-boot启动参数,从mtdblock3引导

[u-boot@MINI2440]# setenv bootargs 'noinitrd console=ttySAC0,115200 init=/linuxr
c mem=64M root=/dev/mtdblock3 rw rootfstype=yaffs ip=10.1.0.129:10.1.0.128:10.1.
0.1:255.255.255.0::eth0:off'
[u-boot@MINI2440]# saveenv
Saving Environment to NAND...
Erasing Nand...
Erasing at 0x4000000000002 --   0% complete.
Writing to Nand... done
[u-boot@MINI2440]#

【11】重启开发板后,检查启动信息

... ...

IP-Config: Complete:
     device=eth0, addr=10.1.0.129, mask=255.255.255.0, gw=10.1.0.1,
     host=10.1.0.129, domain=, nis-domain=(none),
     bootserver=10.1.0.128, rootserver=10.1.0.128,
rootpath=
yaffs: dev is 32505859 name is "mtdblock3" rwyaffs: passed flags ""
VFS: Mounted root (yaffs filesystem) on device 31:3.
Freeing init memory: 112K
----------munt all----------------
***********************************************
************booting to mini2440 *****************
Kernel version:linux-2.6.32.2
the fans:singleboy
Date:2011.5.30
***********************************************

Please press Enter to activate this console.

可以看根系统成功地引导起来了。

这也说明之前用来制作yaffs映像的工具存在问题。

【12】总结

为了能够从nand flash 引导根文件系统,整个过程可谓比较曲折,不过通过学习和研究,获得了其它途径来解决此问题也有简便办法。

(1)挂载nfs文件系统,确保整个系统能够从nfs正确引导。

(2)确保能够在启动信息中看到有关yaffs信息,否则说明yaffs文件系统本身存在问题

(3)尝试从nfs启动的系统中挂载mtdblockx分区,由于系统本身并未带mtd工具,注意mtd工具的制作。

(4)在挂载mtdblockx成功后,可以nfs服务器端直接将根文件系统打包到nfs根文件系统的root或home目录下,然后再到开发板的控制终端中将根文件系统解压到mtdblock分区中,注意一定要去掉其绝对路径。

(5)修改u-boot启动参数从mtdblockx引导。

遗留问题,UBI文件系统在u-boot和linux系统上的移植

接下来,将进行内核的RTC驱动移植

你可能感兴趣的:(linux,内核模块)