ram_flash驱动

20150418 ram_flash驱动

2015-04-18 Lover雪儿

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

  1 /* 利用内存来模拟flash操作
  2  * 参考devices\mtdram.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,定义在 mtd\mtd-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  * 参考devices\mtdram.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,定义在 mtd\mtd-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
时间: 2024-10-05 04:19:25

ram_flash驱动的相关文章

艰辛五天:Ubuntu14.04+显卡驱动+cuda+Theano环境安装过程

题记:从一开始不知道显卡就是GPU(虽然是学计算机的,但是我真的不知道-脑残如我也是醉了),到搞好所有这些环境前后弄了5天时间,前面的买显卡.装显卡和装双系统见另一篇博客装显卡.双系统,这篇主要记录我怎么配置后面的环境,虽然中间重装Ubuntu三次,后面安装过程也没差别. 基础平台:64-bit,Ubuntu14.04 1.安装NVIDIA驱动(参考技术文章,基本是复制啊,蟹蟹作者~) (1) 在官网下载NVIDIA驱动,根据自己买的型号选择下载,放到 /home/lvxia/ 目录下面,我下载

jdbc驱动jar导入eclipse

在使用JDBC编程时需要连接数据库,导入JAR包是必须的,导入其它的jar包方法同样如此,导入的方法是 打开eclipse 1.右击要导入jar包的项目,点properties 2.左边选择java build path,右边选择libraries 3.选择add External jars 4.选择jar包的按照路径下的确定后就行了. Java连接MySQL的最新驱动包下载地址 http://www.mysql.com/downloads/connector/j 有两种方法导入jar包,第一种

13.Linux键盘按键驱动 (详解)

版权声明:本文为博主原创文章,未经博主允许不得转载. 在上一节分析输入子系统内的intput_handler软件处理部分后,接下来我们开始写input_dev驱动 本节目标: 实现键盘驱动,让开发板的4个按键代表键盘中的L.S.空格键.回车键 1.先来介绍以下几个结构体使用和函数,下面代码中会用到 1)input_dev驱动设备结构体中常用成员如下: struct input_dev { void *private; const char *name; //设备名字 const char *ph

Linux-hexdump命令调试event驱动—详解(13)

hexdump: 查看文件的内容,比如二进制文件中包含的某些字符串,通常用来调试驱动用 1.调试 键盘驱动 讲解 当我们insmod挂载了键盘驱动后,找到键盘驱动被放在event1设备里, 此时没有按键按下,所以event1里面的数据是没有的,那么数据又是从来哪里来? 通过键盘驱动的read函数,若有按键按下,就会上传按键数据给用户层,此时的用户层就是hexdump 因为键盘驱动的input_handler 是:evdev_handler 所以键盘驱动的read函数是: evdev_handle

微软要做用云量挖掘机,以技术驱动数字化转型快公司

今年7月,首次更名为"Inspire"的微软WPC全球合作伙伴大会上,微软宣布将所有与合作伙伴相关的角色都重新整合为一个新的部门:统一商业合作伙伴部门(One Commercial Partner),并进行了一整套的组织和流程改组,以适应云计算时代的用户需求与"用云量"规律. 2017年9月12日,微软大中华区副总裁.全球渠道事业部总经理.商业客户事业部总经理包嘉峰与媒体分享了这两个月微软商业合作伙伴部转型以来,微软自身所发生的变化以及为客户所带来的价值.根据包嘉峰

STM32F4XX高效驱动篇2 I2C

说到I2C很多用过STMF10X硬件I2C方式的工程师,都感觉有点头痛.大部分还是使用软件模拟的方式,I2C由于一般的工作频率是400,100KHz.所以在平凡读取,或所读数据量大时,使用这模拟的方式,还是比较浪费CPU有效工作时间的. 在之前的使用I2C的经历中,主要是I2C死锁问题让我也困扰了一段时间.不过后来经过多方资料,最后还是把这个问题解决了.以下驱动程序已集成了此功能. 什么是死锁,在I2C主设备进行读写操作的过程中.主设备在开始信号后控制SCL产生8个时钟脉冲,然后拉低SCL信号为

STM32F4XX高效驱动篇1-UART

之前一直在做驱动方面的整理工作,对驱动的高效性有一些自己的理解这里和大家分享一下.并奉驱动程序,本程序覆盖uart1-8. 串口驱动,这是在每个单片机中可以说是必备接口.可以说大部分产品中都会使用,更有甚者一个产品中用到8个串口.这样一个高效的驱动是决定您产品优劣的关键因素.本文主要针对STM32F4XX系列芯片做的一个驱动接口层.以减少您在开发项目时驱动方面所花费时间,以及为程序达到高效的处理为目的. 从51,pic到现在的STM32,个人感觉STM32这方面做的非常突出,丰富的使用模式,强大

Qt编译好的OCI驱动下载

在上文,我累赘了一大堆,给大家写了一篇Qt如何编译OCI驱动,在这里自然就不再累赘了,直接附上编译好的文件供大家下载: <Qt5.3.1+OCI驱动下载地址> 有经济来源的请传送:http://download.csdn.net/detail/u012433546/9922424 无经济来源的请传送:链接:http://pan.baidu.com/s/1boKG9lH 密码:7yj5 <Qt5.3.2+OCI驱动下载地址> 有经济来源的请传送:http://download.csd

QT5.6.0+VS2015编译MQSQL(ACCESS)X64数据库驱动

QT5.6.0+VS2015编译MQSQL(ACCESS)数据库驱动 1 说明 l 不建议QT5.6.0使用ACCESS数据库.如果想使用轻量级的数据库,可以使用Sqlite数据库. QT想要访问Access.SQL Server等数据库可以通过ODBC的方式来访问,但是QT较高版本已不提供ODBC驱动库,需要自己编译.QT5.6.0编译出来的数据库驱动是64位,但是不建议安装Access数据库,微软本身也不建议安装64位office. PS:为什么QT5.6.0不编译32位数据库驱动:编译数据