• 嵌入式Linux驱动学习之路(二十四)Nor Flash驱动程序


    Nor Flash和Nand Flash的不同:

    类型 NOR Flash  Nand Flash 
    接口 RAM-like,引脚多  引脚少
    容量 小(1M、2M...) 大(512M、1G)
    简单 复杂
    复杂 复杂
    价格 便宜
      无坏块、位反转 有位反转、坏块
      存储一些重要的文件 可以出错的文件比如视频
    xip 可以 不可以

     使用uboot来体验nor Flash操作。(Nor的A0接到Soc的A1上。所以地址应该左移1位。)

    1. 读数据(NOR Flash可以像内存一样直接来读)

        md.b  <address>

    2. 读ID

      NOR手册上 往地址555H写入AA。往2AA写入55,往555H写入90H。读0地址得到厂家IDC2H。读1地址得带22DAH或225dH。退出读ID状态

    OpenJTAG> mw.w aaa aa
    OpenJTAG> mw.w 554 55
    OpenJTAG> mw.w aaa 90
    OpenJTAG> md.w 0 1 
    00000000: 00c2    .. 
    OpenJTAG> md.w 2 1                                                              
    00000002: 2249    I"
    OpenJTAG> mw.w 0 90

    一般Nor有两种规范:jedec和cfi(common Flash interface);

      jedec不包含硬件信息,是一种老的规范。

      cfi包含内存大小,承受电压等信息。

    Linux内核中Flash框架:

    APP open、write、read
    虚拟文件系统 sys_open、sys_write、sys_read
      字符设备驱动 块设备驱动
        RAMBLOCK   硬盘   MTD
           

    Nand Flash

    Nor Flash
              jedec  cfi 

      Nand Flash协议层知道发什么信息来擦除、读写、识别。硬件相关层知道怎么发命令/地址。

      Nor Flash协议层知道如何发送读写、擦除命令。硬件相关层有一些微小差异来让用户做修改。

    通过配置内核支持NOR FLASH

     Device Drivers  --->  

      <*> Memory Technology Device (MTD) support  --->   

        Mapping drivers for chip access  ---> 

          [ ] Support non-linear mappings of flash chips │ │
          <M> CFI Flash device in physical memory map │ │    //编译为模块 
          (0x0) Physical start address of flash mapping │ │     //物理基地址 
          (0X1000000) Physical length of flash mapping │ │      // 长度
          (2) Bank width in octets                  //位宽

    cp drivers/mtd/maps/physmap.ko /home/jz2440/fsroot

    启动开发板。

    insmod physmap.ko

    然后会在相应的目录中增加设备文件:/dev/mtd*

    这是内核中自带的驱动程序。

    下面是自己编写的驱动程序代码:

    /*************************************************************************
        > File Name: s3c_nor.c
        > Author: 
        > Mail: 
        > Created Time: 2016年11月08日 星期二 15时41分05秒
     ************************************************************************/
    #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 <linux/mtd/physmap.h>
    #include <asm/io.h>
    
    static struct map_info *s3c_nor_map;
    static struct mtd_info *s3c_nor_mtd;
    
    struct mtd_partition s3c_nor_parts[] = {
        [0] = {
            .name   = "bootloader_nor",
            .size   = 0x00040000,
            .offset= 0,        
        },
        [1] = {
            .name   = "root_nor",
            .offset = MTDPART_OFS_APPEND,
            .size   = MTDPART_SIZ_FULL,       
        },
    };
    
    static int s3c_nor_init(void)
    {
        /* 分配map_info结构体 */
        s3c_nor_map = kzalloc(sizeof(struct map_info), GFP_KERNEL);
        
        /* 设置:物理基地址,大小,位宽,虚拟基地址 */
        s3c_nor_map->name = "s3c_nor";
        s3c_nor_map->phys = 0;
        s3c_nor_map->size = 0x1000000;  /* >= NOR真正大小 */
        s3c_nor_map->bankwidth = 2;
        s3c_nor_map->virt = ioremap( s3c_nor_map->phys, s3c_nor_map->size);
        
        simple_map_init(s3c_nor_map); 
        /* 调用NOR FLASH协议层提供的函数来识别 */
        s3c_nor_mtd = do_map_probe( "cfi_probe", s3c_nor_map);
        if(!s3c_nor_mtd)
        {
            printk("jedec probe
    ");
            s3c_nor_mtd = do_map_probe("jedec_probe",s3c_nor_map);
        }
        else
            printk("use cfi_probe
    ");
    
        if(!s3c_nor_mtd)
        {
            iounmap(s3c_nor_map->virt);
            kfree(s3c_nor_map);
            return -EIO;
        }
        /* add_mtd_partitions */
         add_mtd_partitions(s3c_nor_mtd,s3c_nor_parts,2);
        return 0;
    }
    
    static void s3c_nor_exit(void)
    {
        del_mtd_partitions(s3c_nor_mtd);
        iounmap(s3c_nor_map->virt);
        kfree(s3c_nor_map);
    }
    
    module_init(s3c_nor_init);
    module_exit(s3c_nor_exit);
    MODULE_LICENSE("GPL");

    Nor Flash识别过程:

    struct mtd_info *do_map_probe(const char *name, struct map_info *map)

    -drv = get_mtd_chip_driver(name);

    -ret = drv->probe(map); // struct mtd_info *cfi_probe(struct map_info *map)    //name=“cfi_probe”

    --struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp)

    ---static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp)

    ----static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,struct cfi_private *cfi)

    -----cp->probe_chip(map, 0, NULL, cfi)  //进入cfi模式,看看是否支持cfi

    -ret = drv->probe(map); // struct mtd_info *jedec_probe(struct map_info *map)    //name=“jedec_probe”

    --struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp)

    ---static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp)

    ----static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,struct cfi_private *cfi)

    -----cp->probe_chip(map, 0, NULL, cfi) //static int jedec_probe_chip(struct map_info *map, __u32 base,unsigned long *chip_map, struct cfi_private *cfi)

    ------进行和Nor Flash相关的一系列操作 

    sd

  • 相关阅读:
    web 服务器
    mysql
    Vue学习之路第二十篇:Vue生命周期函数-组件创建期间的4个钩子函数
    Vue学习之路第十九篇:按键修饰符的使用
    Vue学习之路第十八篇:私有过滤器的使用
    Vue学习之路第十七篇:全局过滤器的使用
    Vue学习之路第十六篇:车型列表的添加、删除与检索项目
    Vue学习之路第十五篇:v-if和v-show指令
    Vue学习之路第十四篇:v-for指令中key的使用注意事项
    Vue学习之路第十三篇:v-for指令
  • 原文地址:https://www.cnblogs.com/ynxf/p/6042690.html
Copyright © 2020-2023  润新知