nor flash设备驱动程序

2017-08-11  本文已影响0人  sgy1993

为什么要把cpu的地址ADDR1连接到nor的A0上面
cpu读取时认为一个地址对应一个字节,而nor flash一个地址对应两字节,如果直连的话就会存在一个问题,cpu读0,nor返回0地址两字节的低字节,cpu读1时,nor返回1地址两字节的低字节,这样显然是有问题的
但是按照原理图就没有问题了
cpu读0,nor返回0地址两字节的低字节,cpu读1时,nor返回0地址两字节的高字节,因为00,01,addr1都是0,同样10,11都对应nor的1地址,因为addr0不接,怎么变都无所谓这样就相当于cpu连续两个地址对应nor的一个地址。
由于这样的特性,cpu如果发出地址0xa0,10100000,addr0没有接,对应nor flash地址1010000,hex:0x50.

nor flash 原理图

nor有两种规范jedec,cfi
通用的
1.进入cfi模式
2.查找进入cfi模式后的后续操作

读取厂家ID
1.555写入aa mw.w 0xaaa 0xaa
2.2aa写入55 mw.w 0x554 0x55
3.555写入90 mw.w 0xaaa 0x90
4.读取x00得到0xc2.厂家id,注意这里是两个字节为一个device id,高位在高地址

进入cfi模式
1.55写入98 mw.w aa 0x98
2.读取10


cfi指令集 flash 驱动程序框架

程序源码do_map_probe函数是识别nor flash的函数,厂家id,设备id,容量等信息

/*
 * 参考 drivers\mtd\maps\physmap.c
 */

#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>

static struct mtd_info *nor_mtd = NULL;

static struct map_info *my_map_info = NULL;
static struct mtd_partition my_partions[] = {
    [0] = {
        .name = "bootloader",
        .size = 0x80000,
        .offset = 0,
    },
    [1] = {
        .name = "root",
        .size = MTDPART_SIZ_FULL,
        .offset = MTDPART_OFS_APPEND,
    },
}; 
static int s3c_nor_init(void)
{
    int err = 0;
    /*
        1.分配一个map_info结构体,设置
    */

    my_map_info = kzalloc(sizeof(struct map_info), GFP_KERNEL);
    if (!my_map_info) {
        printk("error alloc my_map_info\n");
        return -ENOMEM;
    }

    
    my_map_info->name = "my_nor";
    my_map_info->phys = 0x0;
    my_map_info->size = 0x100000;
    my_map_info->bankwidth = 2;

    //映射地址空间,大小需要比nor flash大一点

    my_map_info->virt = ioremap(my_map_info->phys,my_map_info->size);
    if (!(my_map_info->virt)) {
        printk("Error ioremap\n");
        iounmap(my_map_info->virt);
        return -ENOMEM;
    }

    
    simple_map_init(my_map_info);

    //分配一个mtd_info结构体
    nor_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
    
    if (!nor_mtd) {
        printk("error alloc nor_mtd\n");
        iounmap(my_map_info->virt);
        return -ENOMEM;
    }
    nor_mtd = do_map_probe("cfi_probe", my_map_info);
    
    if (!nor_mtd) {
        printk("error do_map_probe\n");
        iounmap(my_map_info->virt);
        kfree(my_map_info);
        kfree(nor_mtd);
        return -ENOMEM;
    }
    err = add_mtd_partitions(nor_mtd, my_partions, 2);
    if (err) {
        printk("func:%s, line:%d\n", 
            __func__, __LINE__);
        return -1;
    }
    return 0;
}

static void s3c_nor_exit(void)
{
    int err = 0;
    
    iounmap(my_map_info->virt);
    kfree(my_map_info);
    kfree(nor_mtd);
    err = del_mtd_partitions(nor_mtd);
    if (!err) {
        
    printk("func:%s, line:%d, del mtd failed!\n", 
        __func__, __LINE__);
    }
}

module_init(s3c_nor_init);
module_exit(s3c_nor_exit);

MODULE_LICENSE("GPL");
上一篇下一篇

猜你喜欢

热点阅读