构建自己的嵌入式系统——根文件系统制作篇

这里的目标是创建一个最小的根文件系统,使其启动后进入shell命令行。

制作步骤:

一、              移植Busybox

Busybox将众多的命令集合进一个很小的可执行程序中,可用来替换GNU fileutils、shellutils等GNU核心工具集,它非常适合用在嵌入式系统。

获取源码:从http://www.busybox.net/downloads/ 下载busybox,我选的是1.15.0版本。

Busybox也有与Linux 内核类似的配置界面,在其顶层目录下执行make menuconfig即可对其配置。如果没有特别的要求,只需注意Build Options的配置选项,它决定busybox是否使用静态链接,其它的先按默认配置即可。

修改busybox顶层目录的Makefile,为ARCH和CROSS_COMPILE变量指定默认值:

         ARCH                          ?=arm

         CROSS_COMPILE     ?=arm-linux-

执行make,编译busybox。

执行make CONFIG_PREFIX=/opt/nfsshare/fs_mini/ install,将busybox安装在/opt/nfsshare/fs_mini/目录之下,生成bin/、sbin/、usr/三个目录和一个链接文件linuxrc。

注意生成的linuxrc文件,它是bin/busybox这个可执行程序的符号链接,从uboot传给kernel的命令行参数可知,bin/busybox就是kernel启动所需的init程序。 

二、              安装glibc库

对Build Options选项,如果指定静态链接,最好使用uclibc库,因为glibc库较大,不适合惜寸土如金的嵌入式系统。我这里选择动态链接,使用glibc库,因为glibc库提供的接口实现更加全面。

         glibc库的来源可以是自己制作交叉编译工具链时生成的,也可以从http://ftp.gnu.org/gnu/glibc/中下载所需的版本,然后在某个目录下编译安装它。我就图个省事,直接从已经安装好的交叉编译工具链的相应目录下找到。有了glibc库,就可以把里面需要的文件拷贝到所构建的根文件系统lib目录下。(glibc库下的文件较多,有些是gcc工具本身生成的,并不属于glibc库,目前我只把重要的文件拷贝过去。)

         我使用的工具链版本是4.3.2,它所使用的是glibc库是2.8版本,glibc库分布在两个不同的目录下:

/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib/

/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/usr/lib/

低级的版本一并放在一个目录,如:

/usr/local/arm/3.4.1/arm-linux/lib/

在fs_mini目录下新建lib/目录,将常用的库文件拷贝过去,包括加载器和常用的动态库:

ld-2.8.so                     ld-linux.so.3

libc-2.8.so                 libc.so.6

libm-2.8.so               libm.so.6

libcrypt-2.8.so         libcrypt.so.1

以上四对文件中,后者均是前者的符号连接。

对于busybox可执行程序,使用arm-linux-readelf –d busybox命令查看其依赖的动态库有libc.so.6和libm.so.6。 

三、              构建根文件系统

继续构造最小根文件系统所需要的目录及相应文件。

1. etc/:

inittab文件——init进程根据该文件创建其它子进程,如调用脚本文件,启动shell等:

        # /etc/inittab

        ::sysinit:/etc/init.d/rcS

        s3c2410_serial0::askfirst:-/bin/sh

        ::ctrlaltdel:/sbin/reboot

    ::shutdown:/bin/umount -a –r

fstab文件——指明当执行“mount –a”时,需要挂接的文件系统:

        # device    mount-point    type     options    dump    fsck order

            proc        /proc         proc       defaults    0         0

            tmpfs   /tmp          tmpfs     defaults    0         0

            sysfs   /sys              sysfs     defaults    0         0

            tmpfs   /dev          tmpfs     defaults    0         0

./init.d/rcS文件——shell脚本文件:

        #!/bin/sh

        ifconfig eth0 192.168.115.130

        mount –a                                    #挂接fstab文件指定的所有文件系统

        mkdir /dev/pts

        mount -t devpts devpts /dev/pts     #支持外部网络连接(telnet)的虚拟终端

        echo /sbin/mdev > /proc/sys/kernel/hotplug #有设备插拔时调用/bin/mdev程序

        mdev –s                         #在/dev目录下生成内核支持的所有设备结点

2. dev/:使用mdev创建该目录下的设备文件,首先建立/dev目录。

    udev是个用户程序,依赖于内核支持的sysfs文件系统,它能够根据系统中硬件设备的状态动态地更新设备文件,包括设备文件的创建、删除等。mdev是udev的简化版本。为减少对Nand Flash的读写,上面的fstab文件已设置将/dev挂载为tmpfs文件系统。

mdev是通过init进程来启动的,在使用mdev构造/dev之前,init进程至少要用到设备文件/dev/console、/dev/null,所以,在/dev目录下:

mknod console c 5 1

mknod null c 1 3 

3. proc/、mnt/、tmp/、sys/、root/等:均为空目录

以上就在fs_mini目录下构建好了最小根文件系统,开发板可以将它作为网络根文件系统直接启动,若要烧入Nand Flash,还要就将它制作为映像文件。 

四、              制作并烧写yaffs文件系统映像文件

制作不同类型的文件系统映像文件需要使用不同的工具,对于yaffs文件系统,其制作工具的源码在yaffs源码下的utils目录里,两个.c文件mkyaffsimage.c和mkyaffs2image.c分别能被编译成mkyaffsimage和mkyaffs2image两个工具,前者用来制作yaffs1映像文件,后者用来制作yaffs2映像文件。

起初,我想在我的系统上使用yaffs2文件系统,于是使用mkyaffs2image工具:

mkyaffs2image fs_mini rootfs.yaffs

打开tftp服务器,烧写过程如下:

tftp 0x33000000 rootfs.yaffs

nand erase 0x00400000 0x02800000

nand write.yaffs 0x33000000 0x00400000 $(filesize)

注:$(filesize)是rootfs.yaffs映像文件的大小,根据yaffs文件系统的特点,其值必须是Nand Flash的页大小(包括OOB区大小)的整数倍,对于64M的Nand Flash,应为528(512+16)的整数倍(还有页大小为(256+8)、(2048+64)的Nand Flash)。

 然后通过boot命令启动系统,似乎根文件系统的制作将告一段落,而实际上,根本不是如我所愿,系统的启动信息让人大失所望,这也预示,接下来的工作绝不会一帆风顺。今年的“两会”刚刚闭幕,温总理就在中外记者会上引用古语:“行百里者半九十”。这提醒我们,在工作完成之前,绝不能高兴太早,更多的荆棘与挑战还在后头。

 首先,上面的启动信息中,包含一堆系统检测出的坏块提示,而且提示的坏块均位于烧写yaffs的分区。经过一番百度后,得知这些坏块均是假坏块(Nand Flash若有坏块,在芯片出厂时就做了标记,不过一般寥寥无几,或者没有),也不奇怪,Nand Flash在使用中哪有那么容易出现坏块呢!然而,具体是什么原因造成这么多的假坏块,我折腾了很久也没有个结果。后来分析,既然系统检测出来的是坏块,那一定是那些块的OOB区里被设置了坏块标记(通常OOB区里存放坏块标记、ECC校验码和yaffs相关的信息标记tag)。yaffs文件系统映像文件的格式比较特别,文件本身就包含了OOB区数据,所以Nand Flash里的yaffs分区的OOB区的信息全部来自yaffs映像文件本身,问题就出在所烧写的rootfs.yaffs文件。那进一步想想,导致rootfs.yaffs出问题的罪魁祸首只可能在这三个之中:所制作的根文件系统fs_mini、uboot里的yaffs烧写命令nand write.yaffs、rootfs.yaffs的制作工具mkyaffs2image。不过,一般根文件系统如果制作的有问题,只会影响最终的启动,如init进程能否成功运行,文件系统能否成功挂载,不会影响烧写到OOB区的信息。对于uboot的nand write.yaffs命令,深入到其函数代码查看,似乎也没什么破绽。那难道是mkyaffs2image工具出了问题?但自己又懒得去看mkyaffs2image.c里的代码(其实如果看了也如同“鸡蛋里挑骨头”,无济于事)。一时问题陷入了僵局。不过,我还没放弃网络搜索,继续百度之…

一个偶然的帖子引起了我的注意,其实不是就我的问题而问,但它让我发现了我的一个认识错误。原来我的mkyaffs2image工具只能制作页大小为(2048+64)的yaffs2文件系统,所以必须烧写到128M或以上的Nand Flash才行。要获得页大小为(512+16)的yaffs2文件系统,即烧写到64M的Nand Flash中的,需要专门的yaffs2映像制作工具,友善有这个工具:mkyaffs2image-64M,不过我也没找到。后来从CSDN上下到了由广州天嵌计算机科技有限公司制作的一套工具,里面有mkyaffs2image-64M。

 在烧写yaffs映像之前,先得将上面造成的假坏块消除掉,而nand erase命令不会对标记为坏块的那些块进行操作,即跳过那些块;nand scrub命令会试图对标记为坏块的块进行擦除,这样可以把误标记的块擦成好块,不过也可能把出厂标记为坏块的那些标记擦掉,造成坏块变成好块,所以也慎用。还好,我的Nor Flash里还有supervivi,使用分区命令:bon part 0,就起到格式化整个Nand Flash芯片的作用,假坏块自然就化为乌有了。

随后问题就柳暗花明,使用makeyaffsimage-64M工具来制作yaffs2文件系统映像。结果,启动信息中再没有假坏块的提示了。这个问题搞定!

不过此时的启动信息中,没有yaffs根文件系统成功挂载的信息,却多了如下错误:

uncorrectable error : <3>uncorrectable error : <3>end_request: I/O error, dev mtdblock3, sector 64

isofs_fill_super: bread failed, dev=mtdblock3, iso_blknum=16, block=32 

对于这个错误,是因为我把内核配置了下面的第二个选项:

--- NAND Device Support

[*] Verify NAND page writes

[ ] NAND ECC Smart Media byte order

上面的第一项是否选上不影响启动,但第二项不要选上,没搞清为什么,哪位大侠知道指出来,先谢了。

之后的启动信息阻塞在下面一句(此时yaffs文件系统已挂载),表明init进程不能成功启动:

         Kernel panic - not syncing: Attempted to kill init!

出现这种现象一般都与带有EABI的工具链有关,所以要把内核的支持EABI的配置选项选上:

         Kernel Features --->

         [*] Use the ARM EABI to compile the kernel                  

         [*]   Allow old ABI binaries to run with this kernel (EXPERIMENTA)

 因为采用的工具链支持EABI,内核编译时也要选上,否则用这个编译器编出来的用户程序无法运行,最典型的错误是busybox无法运行。

若还存在同样的问题,就可能是busybox采用动态链接而lib/库加的不正确,对于arm-linux-gcc-4.3.2工具链,其libc目录下包含三个不同用途的glibc库(不知为什么要这样划分,而以前的非EABI工具链只有一个),对于Samsung S3C2440A,必须使用libc/armv4t下的glibc库。

 这个问题解决后,系统启动便畅通无阻,顺利进入了shell命令行,至此,最小根文件系统的制作在经历一番曲折后终于完成。以下是最终的系统启动信息:

Starting kernel ...

Uncompressing

Linux..............................................................................................................

........ done, booting the kernel.

Linux version 2.6.29.4 (root@My-Fedora-10) (gcc version 4.3.2 (Sourcery G++ Lite 2008q3-72) ) #7 Sun Mar 14

15:21:55 CST 2010

CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177

CPU: VIVT data cache, VIVT instruction cache

Machine: SMDK2440

Memory policy: ECC disabled, Data cache writeback

CPU S3C2440A (id 0x32440001)

S3C24XX Clocks, (c) 2004 Simtec Electronics

S3C244X: core 405.000 MHz, memory 101.250 MHz, peripheral 50.625 MHz

CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on

Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16256

Kernel command line: noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0

irq: clearing subpending status 00000003

irq: clearing subpending status 00000002

PID hash table entries: 256 (order: 8, 1024 bytes)

Console: colour dummy device 80x30

console [ttySAC0] enabled

Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)

Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)

Memory: 64MB = 64MB total

Memory: 61012KB available (3364K code, 323K data, 144K init)

Calibrating delay loop... 201.93 BogoMIPS (lpj=504832)

Mount-cache hash table entries: 512

CPU: Testing write buffer coherency: ok

net_namespace: 716 bytes

NET: Registered protocol family 16

S3C2410 Power Management, (c) 2004 Simtec Electronics

S3C2440: Initialising architecture

S3C2440: IRQ Support

S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics

DMA channel 0 at c4808000, irq 33

DMA channel 1 at c4808040, irq 34

DMA channel 2 at c4808080, irq 35

DMA channel 3 at c48080c0, irq 36

S3C244X: Clock Support, DVS off

bio: create slab <bio-0> at 0

SCSI subsystem initialized

usbcore: registered new interface driver usbfs

usbcore: registered new interface driver hub

usbcore: registered new device driver usb

NET: Registered protocol family 2

IP route cache hash table entries: 1024 (order: 0, 4096 bytes)

TCP established hash table entries: 2048 (order: 2, 16384 bytes)

TCP bind hash table entries: 2048 (order: 1, 8192 bytes)

TCP: Hash tables configured (established 2048 bind 2048)

TCP reno registered

NET: Registered protocol family 1

NetWinder Floating Point Emulator V0.97 (extended precision)

JFFS2 version 2.2. (NAND) (SUMMARY)  ?? 2001-2006 Red Hat, Inc.

yaffs Mar 14 2010 14:18:23 Installing.

msgmni has been set to 119

io scheduler noop registered

io scheduler anticipatory registered (default)

io scheduler deadline registered

io scheduler cfq registered

Console: switching to colour frame buffer device 30x40

fb0: s3c2410fb frame buffer device

lp: driver loaded but no devices found

ppdev: user-space parallel port driver

Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled

s3c2440-uart.0: s3c2410_serial0 at MMIO 0x50000000 (irq = 70) is a S3C2440

s3c2440-uart.1: s3c2410_serial1 at MMIO 0x50004000 (irq = 73) is a S3C2440

s3c2440-uart.2: s3c2410_serial2 at MMIO 0x50008000 (irq = 76) is a S3C2440

brd: module loaded

loop: module loaded

dm9000 Ethernet Driver, V1.31

Uniform Multi-Platform E-IDE driver

ide-gd driver 1.18

ide-cd driver 5.00

Driver 'sd' needs updating - please use bus_type methods

S3C24XX NAND Driver, (c) 2004 Simtec Electronics

s3c2440-nand s3c2440-nand: Tacls=3, 29ns Twrph0=7 69ns, Twrph1=3 29ns

NAND device: Manufacturer ID: 0xec, Chip ID: 0x76 (Samsung NAND 64MiB 3,3V 8-bit)

Scanning device for bad blocks

Bad eraseblock 2182 at 0x000002218000

Creating 5 MTD partitions on "NAND 64MiB 3,3V 8-bit":

0x000000000000-0x000000080000 : "Uboot"

0x000000080000-0x000000100000 : "Env Data"

0x000000100000-0x000000400000 : "Kernel"

0x000000400000-0x000002c00000 : "Yaffs"

0x000002c00000-0x000004000000 : "App"

usbmon: debugfs is not available

ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver

s3c2410-ohci s3c2410-ohci: S3C24XX OHCI

s3c2410-ohci s3c2410-ohci: new USB bus registered, assigned bus number 1

s3c2410-ohci s3c2410-ohci: irq 42, io mem 0x49000000

usb usb1: configuration #1 chosen from 1 choice

hub 1-0:1.0: USB hub found

hub 1-0:1.0: 2 ports detected

usbcore: registered new interface driver libusual

usbcore: registered new interface driver usbserial

USB Serial support registered for generic

usbcore: registered new interface driver usbserial_generic

usbserial: USB Serial Driver core

USB Serial support registered for FTDI USB Serial Device

usbcore: registered new interface driver ftdi_sio

ftdi_sio: v1.4.3:USB FTDI Serial Converters Driver

USB Serial support registered for pl2303

usbcore: registered new interface driver pl2303

pl2303: Prolific PL2303 USB to serial adaptor driver

mice: PS/2 mouse device common for all mice

S3C24XX RTC, (c) 2004,2006 Simtec Electronics

s3c2440-i2c s3c2440-i2c: slave address 0x10

s3c2440-i2c s3c2440-i2c: bus frequency set to 98 KHz

s3c2440-i2c s3c2440-i2c: i2c-0: S3C I2C adapter

S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics

s3c2410-wdt s3c2410-wdt: watchdog inactive, reset disabled, irq enabled

TCP cubic registered

NET: Registered protocol family 17

RPC: Registered udp transport module.

RPC: Registered tcp transport module.

drivers/rtc/hctosys.c: unable to open rtc device (rtc0)

yaffs: dev is 32505859 name is "mtdblock3"

yaffs: passed flags ""

yaffs: Attempting MTD mount on 31.3, "mtdblock3"

yaffs: block 1926 is marked bad

block 1927 is bad

yaffs_read_super: isCheckpointed 0

VFS: Mounted root (yaffs filesystem) on device 31:3.

Freeing init memory: 144K

ifconfig: SIOCSIFADDR: No such device 

Please press Enter to activate this console.

/ #    

最小系统是搭建起来了,但它还不是健全的,一些外设仍不能拿来就用,如eth0、USB、LCD、LED等,因为这些硬件在系统启动时还没有初始化或正确初始化,虽然一些驱动已编译进内核。所以,要针对mini2440这个平台,修改内核的初始化部分,使系统启动时,以上硬件的驱动初始化程序能正确初始化硬件,即硬件被识别,这样,才能在这个嵌入式平台上进行后续的各种各样的开发。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值