三言两语聊Kernel:flash驱动及文件系统

flash种类

flash分为nor flash和nand flash。nor flash的容量较小,但访问速度相对快;nand flash的容量较大。

访问flash的流程

用户访问flash的内容大概是要经历这些过程:

用户->vfs->具体文件系统->mtd设备(字符设备、块设备)->cfi命令字->flash。

现在的flash一般都满足cfi标准,对于不满足cfi标准的flash要使用其他的命令字.

flash空间可根据需要来灵活划分分区,比如32M的flash,做如下划分:1M(uboot),2M(kernel),4M(initrd),25M(log)。注意划分分区的大小必须要是block大小的整数倍。分区划分可以通过uboot传参的方式来做, 这样更灵活一些,当然也可以直接写死在内核里面。使用uboot传参的方式需要内核mencuonfig的支持,即打开开关:CONFIG_CMDLINE_PARTS。打开了这个开关后,内核启动时就会解析uboot传递的参数:”mtdparts=nor:1M(uboot),2M(kernel),4M(initrd),25M(log)“。在内核启动时,只是会将这些分区划分信息给存储起来, 只有真正的加载flash驱动后,即通过cfi probe具体的flash并加载其ko,然后在会读取分区划分信息并对flash空间进行划分。划分好分区后,通过/proc/mtd可以看到这些分区。同时在/dev目录下能够看到对应的mtd设备(包括块设备和字符设备),由于我们是划分的4个分区,所以可以看到mtd0、mtd1、mtd2、mtd3这四个设备。我们可以通过open这几个设备来读写对应的flash地址空间。例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if(open("/dev/mtd3", O_RDWR) < 0){
    perror(open);
    goto error;
}

if(-1 == write(fd, buff, LEN)){
    perror(write);
    goto error;
}

if(-1 == close(fd)){
    perror(close);
    goto error;
}

error:

通过mtd设备赖读写flash,这种方式会绕过文件系统层,即直接通过mtd接口来读写。这种方式和dd命令读写块设备是一致的,dd命令本质上也是用的这种方式, 比如我要随即产生1M大小的内容写入到mtd3对应的地址空间中可以这样:

dd if=/dev/urandom of=/dev/mtdblock3 bs=128k count=8

dd命令一般是用来测试flash的读写速度。

上述这种方式,在内核里的执行路径大概是这样子:

1
2
3
vfs_read/vfs_write
  part_read/part_write
      cfi_amdstd_read/do_write_buffer

这种方式会绕过flash的具体文件系统,而是从vfs直接到mtd层。

读写flash当然也可以使用/dev/mem的方式,/dev/mem是将外设的空间当做一块内存,然后mmap出来,这样就能直接在用户空间来操作物理地址。使用/dev/mem的示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if(-1 == open(/dev/mem, O_RDWR|O_SYNC)){
    perror(open);
    goto error;
}

unsigned char *map_base;
if((map_base = mmap(NULL, FLASH_SIZE,  PROC_READ|PROC_WRITE,
            MAP_SHARED,  fd, FLASH_BASE)) == NULL) {
    perror(mmap);
    close(fd);
    goto error;
}

/* get the content of the flash */
for(int i = 0; i < FLASH_SIZE; i++){
    buf[i] = *(map_base + i);
}

使用/dev/mem的这种方式,不会调用驱动接口,它是直接把flash当做一块内存来使用,所以 /dev/mem这种方式破坏性很大。

flash文件系统

flash文件系统,现在主流的有jffs2、yaffs2、ubifs。jffs2适用于nor flash,yaffs2适用于nand flash,ubifs两种flash都适用。yaffs2目前还未进入内核主线。jffs2则很早就进入了内核主线,且在业界有相对较广泛的应用。ubifs是比较新的文件系统,在性能上显著优于其余两者,不过稳定性上目前还不太好。这三种flash文件系统各自的邮件列表貌似都不太活跃,通常是好几天才能收到一封邮件:)

Comments