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");
测试:
增加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");
使用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