Linux内核2.6.29的配置---对nor flash和JFFS2提供支持

 

这是一篇实现linux内核对nor flash的支持的一点资料,很早以前写的,先整理如下:

nor flash芯片:JS28F128J3D -75-128Mb

网上有文章说了如何让linux内核支持nor flash。不过那些转载的文章中没有头文件(因为使用了<尖括号>,在HTML语言中是注释的意思)。后来研究了类似的驱动文件,发现它们都是大同小异,只是在一些参数上有改变而已。

MTD设备驱动程序在./driver/mtd下面,分为nor flash和nand flash两种。在chips中定义了几种访问nor的接口,包括cfi、jedec、map_ram和map_rom,而实际芯片所要添加的“驱动程序”放到maps目录下(比如本文使用的at91rm9200.c文件,详见后面)。从map这个单词来看,它描述的是一些映射信息,当然也包括了芯片信息,如总大小、块总数、访问接口等等。

这个过程其实是在内核代码树中添加自己的驱动的过程,当然是一些“标准”步骤了:在对应的代码树目录下,添加驱动源代码文件、在Makefile添加内容、在Kconfig添加内容,当然,还需要在make menuconfig里配置。

1、./driver/mtd/maps/Makefile

在这个Makefile最后添加:

obj-$(CONFIG_MTD_AT91RM9200) +=at91rm9200.o

这个CONFIG_MTD_ AT91RM9200由内核配置所得。

2、./driver/mtd/maps/Kconfig

在这个Kconfig文件最后添加(但在endmenu之前):

config MTD_ AT91RM9200

 tristate "CFI Flash device mapped on AT91RM9200"

 depends on ARM && MTD_CFI

 help

   This enables access to the CFI Flash on the SMDK2440 board.

   If you have such a board, say 'Y' here.

这里的MTD_AT91RM9200就是前面Makefile中的那个,注意,CONFIG_前缀是内核自己添加的。可以在编译内核后生成的autoconf.h文件中查看该宏定义。

3、内核配置

首先进入drivers/mtd/maps/目录下,编写flash芯片的map文件,例如文件名为at91rm9200.c。在map文件中需要定义flash的基地址、大小、宽度、分区表、读写函数、初始化和释放函数等。其中分区表的一个例子如下:

static struct mtd_partition at91rm9200_partitions[]=

{

 {

  name:"u-boot",

  size:0x00040000

  offer:0x0,

  mask_flags:mtd_writeable,

 },

 {

  name:"kernel",

  size:0x00200000,

  offset: 0x00040000,

 },

 {

  name:"JFFS2",

  size:mtdpart_siz_full,   //将所有剩余空间都分配给文件系统

  offset: 0x00260000,

 }

};

    这里将flash分成3个分区,分别存放引导装载程序(bootloader)、内核和根文件系统。mask_flags:mtd_writeabie表示分区是只读的;mtdpart_ofs_append或0x00040000表示分区位置紧挨着上一个分区;mtdpart_siz_full表示占用剩余的全部空间。文中将jffs2文件系统的映像存放在第3个分区上,作为系统的根文件系统。

    然后修改makefile文件,在其中加入以下语句:

obj -$(config_mid_ at91rm9200) + = at91rm9200.o

然后回到linux源码目录下,运行make menuconfig对操作系统内核进行配置与裁减,要在nor flash上使用jffs2文件系统,要特别注意以下两个选项:

1)在“memory technology devices(mtd)”选项中选择:

<*>memory technology device(mtd)support

<*>mtd partitioning support

<*>cashing block device access to mtd devices

ram/rom/flash chip drivers--->

<*> detect flash chips by common flash interface(cfi) probe

<*> support for intel/sharp flash chips

mapping drivers for chip access--->

<*> cfi flash device in physical memory map

(0)   physical start address of flash mapping

(1000000)physical length of flash mapping

(2)buswidthin octets

<*> intel strataflash device mapped on at91rm9200

    这里设置了flash芯片的起始地址、大小以及宽度,比如:起始地址为“0”,大小为“1000000”,即16mb,宽度为“2”,即16字节。然后选中自己加入的“intel strata flash device mapped on EDB7312”这一项。

2)在“file systems”选项中选择:

<*>joumalling flash file system v2(jffs2)support

    对于其他功能,可根据自己的实际情况,进行裁减,然后保存退出,接下来编译出操作系统内核映像。

4、./driver/mtd/maps/at91rm9200.c

/*

 * Handle mapping of the NOR flash on Cogent EDB7312 boards

 *

 * Copyright 2002 SYSGO Real-Time Solutions GmbH

 *

 * This program is free software; you can redistribute it and/or modify

 * it under the terms of the GNU General Public License version 2 as

 * published by the Free Software Foundation.

 */

 

#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 0x01000000

#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[] =

{

 

{

name: "U-boot",

size: 0x60000,

offset: 0x0,

mask_flags: MTD_WRITEABLE,

},

{

name: "kernel",

size: 0x200000,

offset: 0x60000,

mask_flags: MTD_WRITEABLE,

},

{

name: "jffs2(11M)",

size: 0xB00000,

offset: 0x260000

},

{

name: "patameters",

size: 0x20000,

offset: 0xd60000

},

};

 

static const char *probes[] = {  NULL };

 

#endif

 

static int                   mtd_parts_nb = 0;

static struct mtd_partition *mtd_parts    = 0;

 

static 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, MTDID);

        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");

猜你喜欢

转载自blog.csdn.net/zhanweizhao_111/article/details/7167446