zoukankan      html  css  js  c++  java
  • ram_flash驱动

    20150418 ram_flash驱动

    2015-04-18 Lover雪儿

        参考linux内核中的device/mtdram.c,编写了一个ram_flash驱动程序,说实在主要就是分配mtd_info结构体,初始化mtd_info结构体,以及提交结构体三步。

      1 /* 利用内存来模拟flash操作  
      2  * 参考devicesmtdram.c
      3  */
      4 #include <linux/module.h>
      5 #include <linux/slab.h>
      6 #include <linux/ioport.h>
      7 #include <linux/vmalloc.h>
      8 #include <linux/init.h>
      9 #include <linux/mtd/compatmac.h>
     10 #include <linux/mtd/mtd.h>
     11 #include <linux/mtd/mtdram.h> 
     12 
     13 
     14 #define RAM_FLASH_SIZE    (10 * 1024 * 1024)    //定义ram_flash的大小为10M
     15 unsigned char *ram_flash_addr;        //用于保存为ram_flash申请的内存的指针,也保存在mtd_info->priv中
     16 
     17 //构建一个mtd_info结构体
     18 static struct mtd_info *mtd_info;
     19 
     20 //内存擦除函数
     21 static int ram_erase(struct mtd_info *mtd, struct erase_info *instr){
     22     if (instr->addr + instr->len > mtd->size)
     23         return -EINVAL;
     24 
     25     memset((char *)mtd->priv + instr->addr, 0xff, instr->len);
     26 
     27     instr->state = MTD_ERASE_DONE;
     28     mtd_erase_callback(instr);
     29 
     30     return 0;
     31 }
     32 
     33 static int ram_point(struct mtd_info *mtd, loff_t from, size_t len,size_t *retlen, void **virt, resource_size_t *phys){
     34     if (from + len > mtd->size)
     35         return -EINVAL;
     36 
     37     /* can we return a physical address with this driver? */
     38     if (phys)
     39         return -EINVAL;
     40 
     41     *virt = mtd->priv + from;
     42     *retlen = len;
     43     return 0;
     44 }
     45 
     46 static void ram_unpoint(struct mtd_info *mtd, loff_t from, size_t len){
     47     
     48 }
     49 
     50 //重映射函数
     51 static unsigned long ram_flash_get_unmapped_area(struct mtd_info *mtd,unsigned long len,unsigned long offset,unsigned long flags){
     52     return (unsigned long) mtd->priv + offset;
     53 }
     54 
     55 //读函数
     56 static int ram_flash_read(struct mtd_info *mtd, loff_t from, size_t len,size_t *retlen, u_char *buf){
     57     if (from + len > mtd->size)
     58         return -EINVAL;
     59 
     60     memcpy(buf, mtd->priv + from, len);
     61 
     62     *retlen = len;
     63     return 0;
     64 }
     65 
     66 //写函数
     67 static int ram_flash_write(struct mtd_info *mtd, loff_t to, size_t len,size_t *retlen, const u_char *buf){
     68     if(to + len > mtd->size)
     69         return -EINVAL;
     70     memcpy((char *)mtd->priv + to, buf, len);
     71     *retlen = len;        //返回已经成功写入的大小
     72     return 0;
     73 }
     74 
     75 //入口函数
     76 static int ram_flash_init(void){
     77     // 1.分配mtd_Info结构体
     78     mtd_info = kmalloc(sizeof(struct mtd_info),GFP_KERNEL); 
     79     if(!mtd_info)
     80         return -ENOMEM;
     81     
     82     // 2.申请ram_flash的内存大小
     83     ram_flash_addr = vmalloc(RAM_FLASH_SIZE);    //申请内存
     84     
     85     // 3.初始化mtd_info结构体
     86     mtd_info->name = "ram_flash_device";    //名字
     87     mtd_info->type = MTD_RAM;                //1设备类型为RAM,定义在 mtdmtd-abi.h中
     88     mtd_info->flags = MTD_CAP_RAM;            //标志,通用
     89     mtd_info->size = RAM_FLASH_SIZE;        //大小
     90     mtd_info->writesize = 1;
     91     mtd_info->erasesize = RAM_FLASH_SIZE;
     92     mtd_info->priv = ram_flash_addr;        //内存地址
     93     
     94     mtd_info->owner = THIS_MODULE;            
     95     mtd_info->erase = ram_flash_erase;        //从此开始关联一些操作函数
     96     mtd_info->point = ram_flash_point;
     97     mtd_info->unpoint = ram_flash_unpoint;
     98     mtd_info->get_unmapped_area = ram_flash_get_unmapped_area;
     99     mtd_info->read = ram_flash_read;
    100     mtd_info->write = ram_flash_write;
    101     
    102     // 4.注册mtd结构体
    103     add_mtd_device(mtd_info); //整块flash只作为一个分区,使用add_mtd_device就够了
    104     
    105     // 5.清除,初始化ram_flash,内容全部为FF表示初始化成功
    106     memset(mtd_info->priv,0xff,RAM_FLASH_SIZE);
    107     
    108     return 0;
    109 }
    110 //出口函数 
    111 static void ram_flash_exit(void){
    112     if(mtd_info){
    113         del_mtd_device(mtd_info);
    114         vfree(mtd_info->priv);
    115         kfree(mtd_info);
    116     }
    117 }
    118  
    119 module_init(ram_flash_init);
    120 module_exit(ram_flash_exit);
    121 MODULE_AUTHOR("Lover雪儿");
    122 MODULE_LICENSE("GPL");
    ram_flash1.c

    测试:

    增加flash的分区:

        由于前面程序总注册mtd结构体使用的是add_mtd_device函数,它是将整块flash当做一个分区,为了为了实现多分区,我们此处须使用add_mtd_partitions函数来注册mtd_info结构体。

      1 /* 利用内存来模拟flash操作  
      2  * 参考devicesmtdram.c
      3  */
      4 #include <linux/module.h>
      5 #include <linux/slab.h>
      6 #include <linux/ioport.h>
      7 #include <linux/vmalloc.h>
      8 #include <linux/init.h>
      9 #include <linux/mtd/compatmac.h>
     10 #include <linux/mtd/mtd.h>
     11 #include <linux/mtd/mtdram.h> 
     12 
     13 
     14 #define RAM_FLASH_SIZE    (10 * 1024 * 1024)    //定义ram_flash的大小为10M
     15 unsigned char *ram_flash_addr;        //用于保存为ram_flash申请的内存的指针,也保存在mtd_info->priv中
     16 
     17 //构建一个mtd_info结构体
     18 static struct mtd_info *mtd_info;
     19 
     20 
     21 //定义分区表
     22 static struct mtd_partition ram_flash_part[] = {
     23     [0] = {
     24         .name     = "first_part",
     25         .offset = 0,
     26         .size    = 0x200000,                //2M
     27     },
     28     [1] = {
     29         .name     = "second_part",
     30         .offset = MTDPART_OFS_APPEND,    //紧跟着上一个分区
     31         .size    = 0x200000,                //2M
     32     },
     33     [2] = {
     34         .name     = "third_part",
     35         .offset = MTDPART_OFS_APPEND,    //紧跟着上一个分区
     36         .size    = MTDPART_SIZ_FULL,        //6M
     37     },
     38 };
     39 
     40 
     41 //内存擦除函数
     42 static int ram_erase(struct mtd_info *mtd, struct erase_info *instr){
     43     if (instr->addr + instr->len > mtd->size)
     44         return -EINVAL;
     45 
     46     memset((char *)mtd->priv + instr->addr, 0xff, instr->len);
     47 
     48     instr->state = MTD_ERASE_DONE;
     49     mtd_erase_callback(instr);
     50 
     51     return 0;
     52 }
     53 
     54 static int ram_point(struct mtd_info *mtd, loff_t from, size_t len,size_t *retlen, void **virt, resource_size_t *phys){
     55     if (from + len > mtd->size)
     56         return -EINVAL;
     57 
     58     /* can we return a physical address with this driver? */
     59     if (phys)
     60         return -EINVAL;
     61 
     62     *virt = mtd->priv + from;
     63     *retlen = len;
     64     return 0;
     65 }
     66 
     67 static void ram_unpoint(struct mtd_info *mtd, loff_t from, size_t len){
     68     
     69 }
     70 
     71 //重映射函数
     72 static unsigned long ram_flash_get_unmapped_area(struct mtd_info *mtd,unsigned long len,unsigned long offset,unsigned long flags){
     73     return (unsigned long) mtd->priv + offset;
     74 }
     75 
     76 //读函数
     77 static int ram_flash_read(struct mtd_info *mtd, loff_t from, size_t len,size_t *retlen, u_char *buf){
     78     if (from + len > mtd->size)
     79         return -EINVAL;
     80 
     81     memcpy(buf, mtd->priv + from, len);
     82 
     83     *retlen = len;
     84     return 0;
     85 }
     86 
     87 //写函数
     88 static int ram_flash_write(struct mtd_info *mtd, loff_t to, size_t len,size_t *retlen, const u_char *buf){
     89     if(to + len > mtd->size)
     90         return -EINVAL;
     91     memcpy((char *)mtd->priv + to, buf, len);
     92     *retlen = len;        //返回已经成功写入的大小
     93     return 0;
     94 }
     95 
     96 //入口函数
     97 static int ram_flash_init(void){
     98     // 1.分配mtd_Info结构体
     99     mtd_info = kmalloc(sizeof(struct mtd_info),GFP_KERNEL); 
    100     if(!mtd_info)
    101         return -ENOMEM;
    102     
    103     // 2.申请ram_flash的内存大小
    104     ram_flash_addr = vmalloc(RAM_FLASH_SIZE);    //申请内存
    105     
    106     // 3.初始化mtd_info结构体
    107     mtd_info->name = "ram_flash_device";    //名字
    108     mtd_info->type = MTD_RAM;                //1设备类型为RAM,定义在 mtdmtd-abi.h中
    109     mtd_info->flags = MTD_CAP_RAM;            //标志,通用
    110     mtd_info->size = RAM_FLASH_SIZE;        //大小
    111     mtd_info->writesize = 1;
    112     mtd_info->erasesize = RAM_FLASH_SIZE;
    113     mtd_info->priv = ram_flash_addr;        //内存地址
    114     
    115     mtd_info->owner = THIS_MODULE;            
    116     mtd_info->erase = ram_flash_erase;        //从此开始关联一些操作函数
    117     mtd_info->point = ram_flash_point;
    118     mtd_info->unpoint = ram_flash_unpoint;
    119     mtd_info->get_unmapped_area = ram_flash_get_unmapped_area;
    120     mtd_info->read = ram_flash_read;
    121     mtd_info->write = ram_flash_write;
    122     
    123     // 4.注册mtd结构体
    124     //add_mtd_device(mtd_info); //整块flash只作为一个分区,使用add_mtd_device就够了
    125     add_mtd_partitions(mtd_info,ram_flash_part,3);    //三个分区
    126     // 5.清除,初始化ram_flash,内容全部为FF表示初始化成功
    127     memset(mtd_info->priv,0xff,RAM_FLASH_SIZE);
    128     
    129     return 0;
    130 }
    131 //出口函数 
    132 static void ram_flash_exit(void){
    133     if(mtd_info){
    134         //del_mtd_device(mtd_info);
    135         del_mtd_partitions(mtd_info);
    136         vfree(mtd_info->priv);
    137         kfree(mtd_info);
    138     }
    139 }
    140  
    141 module_init(ram_flash_init);
    142 module_exit(ram_flash_exit);
    143 MODULE_AUTHOR("Lover雪儿");
    144 MODULE_LICENSE("GPL");
    ram_flash2.c

    使用mtd的flash-erase

    下载: mtd-utils_1.5.1.orig.tar.gz

    http://ftp.debian.org/debian/pool/main/m/mtd-utils/

    在编译的过程中,你或许会遇到下面的问题:

     1 (In compile process, you will meet the following problem.)
     2 
     3 1. sys/acl.h: No such file or directory
     4 --> sudo apt-get install libacl1-dev
     5 
     6 2. compr_lzo.c:29:23: error: lzo/lzo1x.h: No such file or directory
     7 --> sudo apt-get install liblzo-dev (Maybe use liblzo2-dev replace it)
     8 
     9 3. uuid/uuid.h: No such file or directory
    10 --> sudo apt-get install uuid-dev
     
  • 相关阅读:
    鼠标拖放div 实现
    layerX offsetX pageX
    960 grid 使用
    960 grid 分析
    WebMatrix安装和使用
    Sass使用教程
    CSS预处理器实践之Sass、Less比较
    node.js 入门教程(beginnder guide
    node.js NPM 使用
    《Head First 设计模式》学习笔记——状态模式
  • 原文地址:https://www.cnblogs.com/lihaiyan/p/4438174.html
Copyright © 2011-2022 走看看