工作前准备:
1.构建交叉编译环境:请参考其它文章,建议读者直接从网上down一个已经做好的cross或者用eldk编译一个cross,在现在这个讲效率的时代,我想我们应该搞清楚重点,毕竟我们的重点工作并不是制作环境变量,而是系统构建。
2.Jffs2文件映像制作:
编译安装mtd-utils工具,用于jffs2映像制作。
如果要把ramdisk作为根文件系统,请参考另一篇文章的讲解。假设你已经
做好的你的文件系统,包括命令,库,设备文件等等。就可以使用mkfs.jffs2进行jffs2文件格式制作了。为了你的查阅方便我这里列出mkfs.jffs2常用的命令参数:
-p, --pad[=SIZE] 用16進制來表示所要輸出檔案的大小,也就是root.jffs2的size。 很重要的是, 為了不浪費flash空間, 這個值最好符合flash driver所規劃的區塊大小。 如果不足则使用0xff来填充补满。 -r, -d, --root=DIR 指定要做成image的源資料夾.(默认:当前文件夹) -s, --pagesize=SIZE 节点页大小(默认: 4KiB) -e, --eraseblock=SIZE 设定擦除块的大小为(默认: 64KiB) -c, --cleanmarker=SIZE Size of cleanmarker (default 12) -m, --compr-mode=MODE Select compression mode (default: priortiry) -x, --disable-compressor=COMPRESSOR_NAME Disable a compressor -X, --enable-compressor=COMPRESSOR_NAME Enable a compressor -y, --compressor-priority=PRIORITY:COMPRESSOR_NAME Set the priority of a compressor -L, --list-compressors Show the list of the avaiable compressors -t, --test-compression Call decompress and compare with the original (for test) -n, --no-cleanmarkers 指明不添加清楚标记(nand flash 有自己的校检块,存放相关的信息。) 如果挂载后会出现类似: CLEANMARKER node found at 0x0042c000 has totlen 0xc != normal 0x0 的警告,则加上-n 就会消失。 -o, --output=FILE 指定輸出image檔案的文件名.(default: stdout) -l, --little-endian 指定使用小端格式 -b, --big-endian 指定使用大端格式 -D, --devtable=FILE Use the named FILE as a device table file -f, --faketime Change all file times to '0' for regression testing -q, --squash Squash permissions and owners making all files be owned by root -U, --squash-uids 将所有文件的拥有者设为root用户 -P, --squash-perms Squash permissions on all files --with-xattr stuff all xattr entries into image --with-selinux stuff only SELinux Labels into jffs2 image --with-posix-acl stuff only POSIX ACL entries into jffs2 image -h, --help 显示这些文字 -v, --verbose Verbose operation -V, --version 显示版本 -i, --incremental=FILE Parse FILE and generate appendage output for it |
制作好的jffs2.img,我们就可以在uboot中直接cp.b到相应的“分区”中了。
Protect off all Erase 0x10340000(jffs2文件分区起始地址) 0x103fffff(jffs2文件分区结束地址) Tftp 0x20000000(下载jffs2.img映像到ram中) jffs2.img Cp.b 0x20000000 0x10340000 0xdc(将刚才下载到ram中 jffs2映像写入到flash相应分区中,0xdc是jffs2的大小) Protect on all
|
3. 创建相应的/dev设备文件
# mknod -m 666 mtd0 c 90 0
# mknod -m 666 mtdblock0 b 31 0 这里有可能只需要后面一部分,视具体内核驱动代码而定。如果我们使用mdev 或者devfs进行设备文件创建的话,就不必进行设备创建了,但是让我很恼火的是mdev创建了众多的文件,让我的ram难的承受,(更确切的讲,应该是让我很难承受),如果你也无法接受的话,你可以手动创建必要文件。 这里如果要用mdev自动创建设备文件的话,我们需要在我们的启动脚本里做出如下动作: /sbin/init ->/etc/inittab->/etc/init.d/rcS (自定义) 在rcS中我们添加如下命令: #!/bin/sh mount -a mkdir /dev/pts mount -t devpts devpts /dev/pts echo /sbin/mdev > /proc/sys/kernel/hotplug mdev -s
#mount -t jffs2 /dev/mtdblock5 /mnt/
当然这里执行了mount -a自然要转向/etc/fstab中执行挂载命令: fstab中的内容如下(当然你也可以选择你需要的文件系统进行挂载): tmpfs /dev/shm tmpfs defaults 0 0 devpts /dev/pts devpts gid=5,mode=620 0 0 sysfs /sys sysfs defaults 0 0 proc /proc proc defaults 0 0
|
4.如果系统启动停止在uncompress ramdisk处就说明init进程没有正常启动,可能是busybox编译生成的/sbin/init文件不对或者其它问题。
5.还需要要注意的是init=linuxrc和ram0的区别。
6.下面我们参考 一位网友的文章 进行实际移植操作:
(1)构建配置选项
首先,由于kernel2.6的数据结构关系复杂,这里我们只需要照着例子做就行了,选择一个比较相似的驱动文件,根据edb7312.c构建自己的mtd分区表驱动。
$cd drivers/mtd/maps/ |
然后,修改Kconfig,增加自己的配置选项。
//拷贝EDB7312稍作修改即可 |
最后,修改Makefile,增加编译项目。
obj-$(CONFIG_MTD_EDB7312) += edb7312.o |
这里的at91rm9200.o来源于以下源文件at91rm9200.c,这样,自己建立的MTD分区表驱动就可以编译进内核了。
因为第一步的工作中,at91rm9200.c实际上还是edb7312.c的内容,所以需要根据自己的开发板nor flash的配置做一下修改。
/* * $Id: physmap.c,v 0.1.0 2009/05/15 09:14:50 mag Exp $ * * Normal mappings of chips in physical memory */ /************************************************** * Add for Olp by guohui luo 2009/5/15 * ***************************************************/
#include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/init.h> #include <asm/io.h> #include <linux/mtd/mtd.h> #include <linux/mtd/map.h>
#ifdef CONFIG_MTD_PARTITIONS #include <linux/mtd/partitions.h> #endif
#define WINDOW_ADDR 0x10000000 /* physical properties of flash */ #define WINDOW_SIZE 0x00400000 #define BUSWIDTH 2 /* #define FLASH_BLOCKSIZE_MAIN 0x20000 #define FLASH_NUMBLOCKS_MAIN 128 */ /* can be "cfi_probe", "jedec_probe", "map_rom", NULL }; */ #define PROBETYPES { "cfi_probe", NULL }
#define MSG_PREFIX "AT91RM9200-NOR:" /* prefix for our printk()'s */ #define MTDID "at91rm9200-%d" /* for mtdparts= partitioning */
static struct mtd_info *mymtd;
struct map_info at91rm9200nor_map = { .name = "NOR flash on AT91RM9200DK", .size = WINDOW_SIZE, .bankwidth = BUSWIDTH, .phys = WINDOW_ADDR, };
#ifdef CONFIG_MTD_PARTITIONS
/* * MTD partitioning stuff */ static struct mtd_partition at91rm9200nor_partitions[6] = { {/*1*/ .name = "Boot for AT9200",/* boot for uboot */ .size = 0x00020000,/* 1*128KB */ .offset = 0x00000000 }, {/*2*/ .name = "U-Boot",/* U-Boot firmware */ .size = 0x00020000,/* 1*128KB */ .offset = 0x00020000 }, {/*3*/ .name = "Environment", /* default env */ .size = 0x00020000, /* 1*128kb */ .offset = 0x00040000 }, {/*4*/ .name = "Linux Kernel", /* default kernel image */ .size = 0x00100000, /*8x128k=640k*/ .offset = 0x00060000 }, {/*5*/ .name = " rootfs ramdisk", /* default root filesystem */ //.size = 0x002c0000,/*22*128KB=2816KB*/ .size = 0x001e0000,/*15*128kb=2304kb*/ .offset = 0x00160000 }, {/*6*/ .name = "Jffs2", /* writen filesystem */ //.size = 0x00040000,/* 2*128KB=256KB */ //.offset = 0x003c0000, .size = 0x000c0000,/*6*128k=768k*/ .offset = 0x00340000 } };
//static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; static const char *probes[] = { NULL };
#endif
static int mtd_parts_nb = 0; static struct mtd_partition *mtd_parts = 0;
int __init init_at91rm9200nor(void) { static const char *rom_probe_types[] = PROBETYPES; const char **type; const char *part_type = 0;
printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x/n", WINDOW_SIZE, WINDOW_ADDR); at91rm9200nor_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
if (!at91rm9200nor_map.virt) { printk(MSG_PREFIX "failed to ioremap/n"); return -EIO; }
simple_map_init(&at91rm9200nor_map);
mymtd = 0; type = rom_probe_types; for(; !mymtd && *type; type++) { mymtd = do_map_probe(*type, &at91rm9200nor_map); } if (mymtd) { mymtd->owner = THIS_MODULE;
#ifdef CONFIG_MTD_PARTITIONS mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts, 0); if (mtd_parts_nb > 0) part_type = "detected";
if (mtd_parts_nb == 0) { mtd_parts = at91rm9200nor_partitions; mtd_parts_nb = ARRAY_SIZE(at91rm9200nor_partitions); part_type = "static"; } #endif add_mtd_device(mymtd); if (mtd_parts_nb == 0) printk(KERN_NOTICE MSG_PREFIX "no partition info available/n"); else { printk(KERN_NOTICE MSG_PREFIX "using %s partition definition/n", part_type); add_mtd_partitions(mymtd, mtd_parts, mtd_parts_nb); } return 0; }
iounmap((void *)at91rm9200nor_map.virt); return -ENXIO; }
static void __exit cleanup_at91rm9200nor(void) { if (mymtd) { del_mtd_device(mymtd); map_destroy(mymtd); } if (at91rm9200nor_map.virt) { iounmap((void *)at91rm9200nor_map.virt); at91rm9200nor_map.virt = 0; } }
module_init(init_at91rm9200nor); module_exit(cleanup_at91rm9200nor);
MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marius Groeger <[email protected]> "); MODULE_DESCRIPTION("Generic configurable MTD map driver"); |
增加MTD,和相应的文件系统的支持。
Devices Drivers ---> |
这里选择Jffs2的支持。
(4)编译,加载
make Image编译,然后制作成uImage。
可以修改Makefile 文件,添加cross工具和uboot工具处理命令。
TOPDIR=$($(which pwd)) |
或者直接按照Olp嵌入式系统构建中讲到的方法进行uImage 文件生成,uImage格式要比其它其中映像格式灵活,所以我们一向选择uImage。
系统启动过程中Jffs2信息:
AT91RM9200-NOR:0x00400000 at 0x10000000 NOR flash on AT91RM9200DK: Found 1 x16 devices at 0x0 in 16-bit bank Intel/Sharp Extended Query Table at 0x0031 Using buffer write method cfi_cmdset_0001: Erase suspend on write enabled mtd: Giving out device 0 to NOR flash on AT91RM9200DK AT91RM9200-NOR:using static partition definition Creating 6 MTD partitions on "NOR flash on AT91RM9200DK": 0x00000000-0x00020000 : "Boot for AT9200" mtd: Giving out device 1 to Boot for AT9200 0x00020000-0x00040000 : "U-Boot" mtd: Giving out device 2 to U-Boot 0x00040000-0x00060000 : "Environment" mtd: Giving out device 3 to Environment 0x00060000-0x00160000 : "Linux Kernel" mtd: Giving out device 4 to Linux Kernel 0x00160000-0x00340000 : " rootfs ramdisk" mtd: Giving out device 5 to rootfs ramdisk 0x00340000-0x00400000 : "Jffs2" mtd: Giving out device 6 to Jffs2
|
查看/proc文件系统中mtd信息:
# cat /proc/mtd dev: size erasesize name mtd0: 00400000 00020000 "NOR flash on AT91RM9200DK" mtd1: 00020000 00020000 "Boot for AT9200" mtd2: 00020000 00020000 "U-Boot" mtd3: 00020000 00020000 "Environment" mtd4: 00100000 00020000 "Linux Kernel" mtd5: 001e0000 00020000 " rootfs ramdisk" mtd6: 000c0000 00020000 "Jffs2" |
这里需要注意的是:
我们需要挂载mede生成 的dev设备,不然,后面的terminal 和设备都会找不到,当然如果你不选择用mdev或者devfs创建设备的话,就没有必要按下面的方式进行挂载,不过我不太喜欢medv创建的设备,实在是太多了,大大占用了我可贵的ram资源.
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
mount -t jffs2 /dev/mtdblock5 /mnt/
(5)Jffs2文件系统测试
挂载Jffs2文件分区:
Mount -t jffs2 /dev/mtdblock5 /mnt
Vi /mnt/test.txt
写入一段文字,然后umount /mnt ,再挂载,看一下刚才写入的文件是否存在,再掉电重启一下系统,确认jffs2文件系统支持良好。