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中的driversmtdnandmtdchar.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;
此设备号定义在includelinuxmtdmtd.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]#