Chinaunix首页 | 论坛 | 博客
  • 博客访问: 181820
  • 博文数量: 44
  • 博客积分: 627
  • 博客等级: 中士
  • 技术积分: 345
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-20 21:55
文章分类

全部博文(44)

文章存档

2012年(44)

分类: LINUX

2012-08-08 17:18:33

Nor flash 驱动和移植  

2010-07-22 10:14:06|  分类: arm linux设备驱 |  标签: |字号 

转载自http://blog.chinaunix.net/u2/63379/showart_503632.html

 

  开发板上只有Nor Flash,所以为了实现层次文件系统,需要为Linux2.6.20增加Nor Flash MTD驱动支持。其实工作量并不大,因为已经有现成的程序可供参考。

 

    MTD的驱动程序都集中在drivers/mtd里面。我们需要做的,仅仅是在drivers/mtd/maps下增加自己的分区表。因为有参考的代码,所以比较容易。

 

1)构建配置选项

 

    首先,根据edb7312.c构建自己的mtd分区表驱动。

 

$cd drivers/mtd/maps/
$cp edb7312.c at91rm9200.c

 

    然后,修改Kconfig,增加自己的配置选项。

 

//拷贝过EDB7312稍作修改即可
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 ATMEL AT91RM9200DK board.
          If you have such a board, say 'Y' here.

 

    最后,修改Makefile,增加编译项目。

 

 

    这样,自己建立的MTD分区表驱动就可以编译进内核了。

 

2)修改分区表信息

 

    因为第一步的工作中,at91rm9200.c实际上还是edb7312.c的内容,所以需要根据自己的开发板nor flash的配置做一下修改。

 

obj-$(CONFIG_MTD_EDB7312) += edb7312.o
obj-$(CONFIG_MTD_AT91RM9200) += at91rm9200.o

#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 0x00800000 /* intel 28F640J3A 8MB */
#define BUSWIDTH 2 /* data bus width 16bits */
/* 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[5] =
{
        {
                // U-boot 128KB
                .name = "U-boot",
                .size = 0x20000,
                .offset = 0
        },
        {
                // uImage 2MB
                .name = "Kernel",
                .size = 0x200000,
                .offset = 0x20000
        },
        {
                // RootFS 3MB
                .name = "RootFS",
                .size = 0x300000,
                .offset = 0x220000
        },
        {
                // UserFS
                .name = "Jffs2",
                .size = 0x2C0000,
                .offset = 0x520000
        },
        {
                // Parameters
                .name = "Parameters",
                .size = 0x20000,
                .offset = 0x7E0000
        },
};

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

 //mymtd为master mtd_info它不被添加到数组mtd_table[]中,它只用于初始化

 //每一个分区的mtd_info。而后将每一个分区对应的mtd_info添加到数组mtd_table[]

 //供上层调用。MTD原始设备驱动层的主要工作就是向 mtd_table[]中添加mtd_info。 
                        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 ");
MODULE_DESCRIPTION("Generic configurable MTD map driver");

 

3)配置内核

 

    增加MTD,和相应的文件系统的支持。

 

    Devices Drivers --->

            Memory Technology Devices (MTD) --->

                 <*> Memory Technology Device(MTD) support

                 <*> MTD partitioning support

                 <*> Direct char device access to MTD devices

                 <*> Caching 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 mapped on AT91RM9200

    File Systems --->

           Miscellaneous filesystems --->

                这里选择cramfs或者Jffs2的支持。

 

4)编译,然后加载

 

    make Image编译,然后制作成uImage

 

 

    这是JFFS2作为根文件系统的信息:

 

 

TOPDIR=$($(which pwd))
TMP=$TOPDIR/linux.bin
TARGET=$TOPDIR/uImage

arm-linux-objcopy -O binary -S vmlinux $TMP && gzip -v9 $TMP && \
mkimage -'RAM disk' -A arm -O linux -T kernel -C gzip \
        -a 0x20008000 -e 0x20008000 -d $TMP.gz $TARGET && \
cp $TARGET /mnt/hgfs/common && \
rm -f $TMP*

 

    可以看到MTD分区信息。进入shell界面,然后查看/proc/mtd,如下:

 

AT91RM9200-NOR:0x00800000 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
AT91RM9200-NOR:using static partition definition
Creating 5 MTD partitions on "NOR flash on AT91RM9200DK":
0x00000000-0x00020000 : "U-boot"
0x00020000-0x00220000 : "Kernel"
0x00220000-0x00520000 : "RootFS"
0x00520000-0x007e0000 : "Jffs2"
0x007e0000-0x00800000 : "Parameters"

 

    可以看到加载是正确的。

阅读(1484) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~