桂林电子科技大学毕业设计(论文)报告用纸 第 31 页 共 56 页
图4.1
编译内核:make linux; 编译库:make lib_only; 编译用户程序:make user_only; 制作romfs:make romfs; 生成镜像:make image;
最后make,之后,如果再修改的话只编译相应的选项即可,节省时间。 在uClinux-dist/images下生成romfs镜像romfs.img。
在uClinux-dist/linux-2.6.x下生成内核镜像vmlinux,此时的vmlinux并不能直接使用,还要对其进一步的处理。为了方便写了个shell: #/bin/sh
#build uImage for uclinux #piaozhiye
arm-linux-objcopy -O binary -R .note -R .comment -S vmlinux linux.bin gzip -9 linux.bin
/home/piaozhiye/u-boot-1.1.6/tools/mkimage -A arm -O linux -T kernel -C gzip -a 0xa0008000 -e 0xa0008000 -n \ uImage.bin
第一个是将vmlinux 转换成linux.bin的二进制格式。 第二个是用gzip压缩linux.bin生成linux.bin.gz。
第三个是使用编译u-boot生成的mkimage 将linux.bin.gz 转换成uImage.bin。 下面是mkimage的用法:
Usage: /home/piaozhiye/u-boot-1.1.6/tools/mkimage -l image
31
桂林电子科技大学毕业设计(论文)报告用纸 第 32 页 共 56 页
-l ==> list image header information
/home/piaozhiye/u-boot-1.1.6/tools/mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image -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)
现在uClinux基本上可以运行了,不过此时flash驱动、网卡等驱动都没有,只是在串口打印出一些相关信息。 通过tftp下载镜像:
首先将内核和romfs镜像复制到TFTP根目录下然后使用命令:
下载内核到a1000000:tftp a1000000 uImage.bin 下载romfs到a1800000:tftp a1800000 romfs 在内存中运行:bootm a1000000
4.2 Linux nor flash驱动移植
4.2.1 Linux mtd简介
MTD(memory technology device内存技术设备)是用于访问memory设备(ROM、flash)的Linux的子系统。MTD的主要目的是为了使新的memory设备的驱动更加简单,为此它在硬件和上层之间提供了一个抽象的接口。MTD的所有源代码在/drivers/mtd子目录下。将CFI接口的MTD设备分为四层(从设备节点直到底层硬件驱动),这四层从上到下依次是:设备节点、MTD设备层、MTD原始设备层和硬件驱动层。
一、Flash硬件驱动层:硬件驱动层负责在init时驱动Flash硬件,Linux MTD设备的NOR Flash芯片驱动遵循CFI接口标准,其驱动程序位于drivers/mtd/chips子目录下。NAND型Flash的驱动程序则位于/drivers/mtd/nand子目录下。
二、MTD原始设备:原始设备层有两部分组成,一部分是MTD原始设备的通用代码,
32
桂林电子科技大学毕业设计(论文)报告用纸 第 33 页 共 56 页
另一部分是各个特定的Flash的数据,例如分区。
三、MTD设备层:基于MTD原始设备,linux系统可以定义出MTD的块设备(主设备号31)和字符设备(设备号90)。MTD字符设备的定义在mtdchar.c中实现,通过注册一系列 fileoperation函数(lseek、open、close、read、write)。MTD块设备则是定义了一个描述MTD块设备的结构mtdblk_dev,并声明了一个名为mtdblks的指针数组,这数组中的每一个mtdblk_dev和mtd_table中的每一个mtd_info一一对应。 四、设备节点:通过mknod在/dev子目录下建立MTD字符设备节点(主设备号为90)和MTD块设备节点(主设备号为31),通过访问此设备节点即可访问MTD字符设备和块设备。
现在的NorFlash大多支持CFI或者JEDEC这样的规范,根据这些规范可以自动检测出芯片的一些参数并进行读写,所以uClinux将这些规范的驱动实现单独放在mtd/chips目录下。也就是说这个目录下放的是芯片的通用驱动代码,这些代码本身是不会主动去检测芯片的存在的,它仅仅是注册了一个驱动供其它模块调用。
在通用规范的基础上,每个不同的厂商有不同的实现,且芯片在不同的系统中可能有不同的参数,如基地址,位宽等。uClinux将这部分独立出来放在mtd/maps下。这个目录下的代码将根据芯片实现的不同规范调用相应的chips驱动。因此chips下的模块必须先于maps下的模块初始化。我们主要做的工作是在map目录下填写map_info结构体,并作相应的初始化。
4.2.2 Nor flash驱动移植
开发板nor flash分分区如下: //driver/mtd/maps/lpc2468nor.c /*????一些头文件*/
#define WINDOW_SIZE 0X200000 //2MB
#define WINDOW_ADDR 0X80000000 // 基地址 #define BUSWIDTH2 //16/8
#define PROBETYPES {\探测接口类型 #define MSG_PREFIX \前缀 #define MTDID \驱动
struct map_info lpc2468nor_map = {.name = \.size = WINDOW_SIZE, .bankwidth = BUSWIDTH,
33
桂林电子科技大学毕业设计(论文)报告用纸 第 34 页 共 56 页
.phys = WINDOW_ADDR };
#ifdef CONFIG_MTD_PARTITIONS
static struct mtd_partition static_partitions[]= {
{.name = \内核镜像 .offset = 0, .size = 0xd0000
},{.name = \做根文件系统 .offset = 0xd0000, .size = 0xb0000
},{.name = \用于JFSS2文件系统,系统启动之后挂载该分区
.offset = 0x180000, .size = 0x80000,} }; #endif
#define NUM_PARTITIONS ARRAY_SIZE(lpc2468nor_partitions) static struct mtd_info *mymtd; static int mtd_parts_nb = 0;
static struct mtd_partition *mtd_parts = 0; //norflash驱动模块的初始化代码
static int __init init_lpc2468nor_map(void) {
static const char *rom_probe_types[] = PROBETYPES; const char **type;
const char *part_type = 0; printk(KERN_NOTICE MSG_PREFIX \at 0xx \\n\
// 将物理地址映射到linux的内核空间
lpc2468nor_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE); if(!lpc2468nor_map.virt) {
printk(MSG_PREFIX \}
// 填充read, write, copy_from, copy_to几个函数指针为默认值。 simple_map_init(&lpc2468nor_map); mymtd = 0;
type =rom_probe_types;
for(; !mymtd && *type ; type++) {
/* do_map_probe这个函数位于drivers/mtd/chips/chipreg.c,用于查找指定名称的chip_driver,并调用它完成芯片的检测。*/
34
桂林电子科技大学毕业设计(论文)报告用纸 第 35 页 共 56 页
mymtd = do_map_probe(*type, &lpc2468nor_map); }
if(mymtd) {
mymtd->owner = THIS_MODULE;
printk(\mtd_parts = static_partitions;
mtd_parts_nb = ARRAY_SIZE(static_partitions); part_type = \add_mtd_device(mymtd); if(mtd_parts_nb == 0)
printk(KERN_NOTICE MSG_PREFIX \else {
printk(KERN_NOTICE MSG_PREFIX \add_mtd_partitions(mymtd, mtd_parts, mtd_parts_nb); }
return 0; }
iounmap((void *)lpc2468nor_map.virt); return - ENXIO; }
static void __exit cleanup_lpc2468nor_map(void) {
if(mymtd) {
del_mtd_partitions(mymtd); del_mtd_device(mymtd); map_destroy(mymtd); }
if(lpc2468nor_map.virt) {
iounmap((void *)lpc2468nor_map.virt); lpc2468nor_map.virt = NULL ; } }
module_init(init_lpc2468nor_map); module_exit(cleanup_lpc2468nor_map);
在driver/mtd/maps目录下在kconfig加上 config MTD_ARM_LPC2468NOR
tristate \depends on ARM && MTD
35