说明
- flash是嵌入式开发中接触频繁的器件之一,有很多功能依赖于它,例如:升级时需要将升级文件写入flash;有些平台在flash上划分一块区域,实现保存配置(nvram)功能。
使用
- 应用层,我们平常会直接使用命令操作flash,例如:使用flashcp烧写flash分区,使用flash_eraseall清空flash分区,使用flash_lock_unlock对flash加锁取消锁等;即使是项目代码中也常看到直接调用这些命令操作flash。
- 为了更好理解命令的实现原理和实现自己的需求(当前平台没有nvram功能,需要保存一些配置在flash中)需要了解下命令的实现。
命令实现
- 嵌入式平台,flashcp等命令实现都在busybox中,代码量不大,实现很容易理解,以下以flashcp源码为例:
- 打开flash分区设备节点(字符设备 mtdx)和文件,获取设备信息,判断文件是否合理(文件大小是否超过设备空间)
struct mtd_info_user mtd;
fd_d = xopen(devicename, O_SYNC | O_RDWR);
if (ioctl(fd_d, MEMGETINFO, &mtd) < 0) {
....
}
if (statb.st_size > mtd.size) {
....
}
* 获取的主要数据
mtd.erasesize //擦除块大小
mtd.size //mtd分区大小
- 根据文件大小计算擦除次数,将flash分区循环按照块大小擦除。
struct erase_info_user e;
//循环擦除
if (ioctl(fd_d, MEMERASE, &e) < 0) {
....
}
* 主要是擦除参数 e,需要设置正确
e.start = 0; e.start += mtd.erasesize; //擦除起始地址
e.length = mtd.erasesize; //擦除大小,由第一步操作获取
- 将文件写入已擦除块
* 使用标准IO函数,lseek,read,write等对flash分区设备节点操作。
flashcp中执行了两次:
1. 将文件写入flash中。
2. 将flash分区中的数据读取出来和文件进行内存比较,如果不同则打印错误。
简单示例
#include <stdio.h>
#include <mtd/mtd-user.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
int main(int argc, char **args){
struct mtd_info_user mtd;
struct erase_info_user e;
int fd = open(args[1], O_SYNC | O_RDWR);
if (ioctl(fd, MEMGETINFO, &mtd) < 0) {
printf("%s is not a MTD flash device\n", args[1]);
return -1;
}
e.start = 0;
e.length = mtd.erasesize;
if (ioctl(fd, MEMERASE, &e) < 0) {
printf("erase error at 0x%llx on %s",
(long long)e.start, args[1]);
return -1;
}
write(fd, "test", 5);
lseek(fd, 0, SEEK_SET);
char buf[6] = {0};
read(fd, buf, 5);
printf("%s\n", buf);
close(fd);
return 0;
}