因为需要,又不想自己写,所以就移植了一个文件系统。

说下我的硬件和开发工具:接成 TRUE IDE 模式下的CF卡(也就是相当于一块硬盘了),三星S3C2440的ARM9,开发工具是很老很老的D版的ADS1.2。

我在网上看到的嵌入式系统上面常用的文件系统有UCOSII公司的UC/FS ,支持CF卡,硬盘,SD/MMC卡,还有NAND FLASH等等,比较多,不过是商用的,需要银子的,有周立功的用于教学用(为什么说是用于教学用的,呵呵,等下就说)的ZLG/FS ,还找到了开源、免费的两个,其中一个叫做 efsl ,另一个叫做 FatFs 。

现在先不考虑版权的问题,选择一个比较合适的文件系统。第一个UC/FS 文件系统没得什么说的,UCOSII那个公司开发的,稳定性,兼容性应该都不会差。第二个是ZLG/FS 。周立功的很多的开发板上面都送了这个文件系统的源代码的,在网上找到一个现成的读写硬盘的,只是是基于LPC2200系列的处理器的。第三个是efsl, 是一个开源的项目,免费,只需要提供读扇区和写扇区 2个函数。第四个是FatFs,跟efsl一样,也是一个开源的项目,移植的时候比efsl多几个简单的函数。

这里补充一下CF卡和硬盘的简单的资料,CF卡有三种模式,其中有一个叫TRUE IDE,接成这个模式以后,就跟他的模式名字一样,他就是一个硬盘,对他进行读写,也就相当于对一个硬盘进行读写。当引脚OE(好像是叫OE,具体参考 CF卡文档)在上电的时候检测到拉低,那么CF卡就进入TRUE IDE模式。读写硬盘的时候,在只写一次LBA,只发送一个命令(读或者写)的情况下,最多可以读或者写256个扇区(当然也可以读一个扇区,读或者写多少个扇区在扇区 计数器 count里面),其中,发一个读或者写命令,读或者写256个扇区所需要的时间,比分256次去读写这些扇区所需要的时间要短得多,效率要高得多,我现在需要的是一个读写的速度比较快,效率比较高的文件系统,因此,底层的读写扇区必须要每写一个命令就可以读写多个扇区,读写扇区的函数必须要有扇区计数器(前面的count)这个参数,才可能满足要求 。

UC/FS也是在网上搜了个代码,看了下,很标准的几个层,什么硬件层,文件系统层,API层,等等(具体参见UC/FS的文档),跟UCOSII一个公司的,稳定性应该不错,需要提供的函数也是读扇区,写扇区等等几个。但是底层的读写扇区的函数不需要提供扇区计数器count这个参数,也就是说,这个文件系统不能在只写一个读或者写命令的情况下,读或者写多个扇区,本来效感觉不错的一个文件系统,效率就大大的降低了。

然后看了下efls这个文件系统,开源的项目,免费的项目,好东西,移植也很简单,同样移植的时候也是提供读写扇区等几个函数,但是面临的跟UC/FS同样的问题,每次读写的时候也只能读写一个扇区。

绝望之余看到了周立功的文件系统,大概看了下(没有仔细阅读源代码),硬件驱动上面能够在发一次读命令的情况下,读写多个扇区,而且感觉上比较简单,同样,层次也很清楚,移植需要做的事情也是修改后面的读写扇区等等几个函数。于是就开干了。功夫不负苦心人,过了几天,CF卡能够读写了,拿到电脑上面看写的数据,没问题。从CF卡里面读文件出来,打印到超级终端,也没有问题,以为就万事OK了,想了下,我们需要的,最关心的,第一是速度,然后就开始测试速度,不测不知道,一测吓一跳!太“快”了,TMD,才5,6个K Bytes 每秒!!!!!(我的驱动已经测试了,上M字节每秒的)   于是跟踪到写里面去,发现一个很,十分,非常严重的问题:ZLG/FS提供了读一个字节的函数,忘了叫做啥,这里暂时叫 ReadOneByte(***),然后读多个字节,或者说读大块字节的函数用的是啥,呵呵,

for(i=0;i < N ; i++) ReadOneByte(***) ,这种机制,不慢才怪事!!!于是伤心的抛弃了ZLG/FS,这东东,学习还是可以的,商用的话,差太远了!!!

我那点东西,文件系统可以不上,但是必须有个文件存储协议,或者说叫做自己的文件系统,自己写个简单的存储协议,试过,很麻烦。但是如果上文件系统,自己写的话,写要累死人的,写出来的不一定效率就高,速度就快,所以,还是在网上漫无目的的找,觉得应该有效率很高的文件系统的。

还是那句话,功夫不负苦心人,终于让我找到了,也就是现在所用的,FatFs,开源,免费,高效!(说一下这里几个文件系统都有的一个缺点,由于微软的 FAT版权的问题,FatFs,ZLG/FS,efsl都只支持 DOS 8.3 文件名 ,即8个字节的文件名,一个”.“,然后3个字节的扩展名,我找到的那个UC/FS也不支持,不知道在更新的版本里面支持不,看哪天有空了,把那个 FatFs改下,让他支持,呵呵)。FatFs 的底层可以写一次命令,读写多个扇区。FatFs 的设计的读写的思想 就很好,小块的数据,我就经过Buffer来存储,大块的数据,我就直接进行存取,那样速度,效率高了很多,看图 :

FatFs文件系统的结构也很清晰,也是看图 :

补充一点,FatFs的作者写了两个,一个是正宗的FatFs ,比较适合大的RAM的设备,另一个是FatFs/Tiny ,比较适合小RAM的系统,比如单片机,FatFs/Tiny占用较小的RAM,代价是更慢的读写速度和更少的API函数。不过两个都支持FAT12,FAT16,FAT32文件系统。

下载下来的FatFs的FatFs有两个文件夹,一个是 doc ,FatFs的说明,包括特性,系统函数,以及可能的一些问题,另一个就是源代码文件夹src了,总共8个文件,diskio.c和diskio.h是硬件层 ,ff.c和 ff.h是FatFs的文件系统层和文件系统的API层 ,integer.h是文件系统所用到的数据类型的定义, tff.c和tff.h是Tiny的文件系统层和文件系统的API层, 还有一个00readme.txt简要的介绍了FatFSHE FatFs/Tiny,包括他们所支持的API,怎么配置等等。

移植的问题,第一个是数据类型 ,在integer.h里面去定义好数据的类型 。第二个,就是配置 ,打开ff.h(我用的FatFs,不是 Tiny),_MCU_ENDIAN ,选择你的CPU是大端存储(big endding)还是小端存储(little endding),一般的都用的小端存储,1是小端,2是大端。这个相当重要,一会儿还要谈到这里。其他的,按照自己的需要来配置了,说明文档够清楚了,我就不多说啥了。

第三件事情,就是写底层的驱动函数,包括:

  • disk_initialize - Initialize disk drive
  • disk_status - Get disk status
  • disk_read - Read sector(s)
  • disk_write - Write sector(s)
  • disk_ioctl - Control device dependent features
  • get_fattime - Get current time

所有的函数都牵涉到了选择第几个磁盘的问题,如果仅仅用一个,可以不必理会这个drv 参数。

disk_initialize ,如果不需要的话,直接返回0就行

disk_status ,这个嘛,先不管了,直接返回0就OK

disk_read - Read sector(s)
disk_write - Write sector(s)
读写扇区,注意参数哦!

disk_ioctl 需要回应CTRL_SYNC,GET_SECTOR_COUNT,GET_BLOCK_SIZE 三个命令,正确返回0即   
RES_OK,不正确返回RES_ERROR。
              所有的命令都从 ctrl 里面去读,返回值仅仅返回这次操作是否有效,而需要传递回去的数据在buff
              里面,以下是我的:
              CTRL_SYNC 命令,直接返回0;
              GET_SECTOR_COUNT ,得到所有可用的扇区数目(逻辑寻址即LBA寻址方式)
              GET_BLOCK_SIZE ,得到每个扇区有多少个字节,比如 *((DWORD*)buff) = 512;
              其他的命令,返回RES_PARERR

disk_ioctl 这个函数仅仅在格式化的时候被使用 ,在调试读写的时候,这个函数直接让他返回0就OK 了。

get_fattime - 得到系统的时间,格式请见文档。不用的话,返回0就行。

这样移植了,也基本上就成功了,但是在我的板子上面死活不行,每次一执行到几个宏定义比如
LD_WORD(ptr)        (WORD)(*(WORD*)(BYTE*)(ptr)) 就产生数据终止异常 ( DATA ABORT exception),但是网上的一个兄弟的(ouravr上的一个兄弟,用的SD卡,IAR编译器,平台是STM32,已经成功了,还公布了源码的,这里没有问题啊),没问题。分析下这个几个宏的意思:

LD_WORD(ptr)        (WORD)(*(WORD*)(BYTE*)(ptr)) 是在little endding里面定义的

LD_WORD(ptr) ,LD就是load,WORD在integer.h里面定义的是16位的无符号数,那这个需要完成的就是载入一个16位的数,或者说是2个字节,后面的 ptr是参数。(WORD)(*(WORD*)(BYTE*)(ptr)) ,先将这个ptr转换成一个指向BYTE类型数据的指针(BYTE *) ,在将这个指针转换成一个指向 16位无符号数的指针(WORD *) ,然后用一个 ” * “将这个数据取出来,转换成一个无符号的16位数据,这个仅仅从C语言的角度来看,实际上呢,这个完成的就是从ptr指针指向的位置,取出2个字节,作为一个16位的无符号数取出,而这2个字节是little endding,即小端模式,低字节是低8位,高字节是高8位。

既然是这样的,测试了下,定义了一个BYTE buf[512] ,定义一个WORD类型 zz ,用一个指针pt ,让pt指向
buf[0] ,调用LD_WORD(ptr) ,zz=LD_WORD(pt) ;没问题,将pt指向 buf[1] ,呵呵,问题马上出来了,数据终止异常,然后测试了指针指向 buf[3],buf[5]等等奇数个,都是这样的问题,我就郁闷了啊,TMD,编译器的问题!!!!不过还好,找到问题了,就可以解决问题了,在 ff.h里面的宏定义里面把这即个东东给注释掉,然后在ff.c里面把这几个宏定义写成函数,这里贴一个出来:
WORD    LD_WORD(void *pt)
{
    BYTE *PT = (BYTE*)pt;     //定义一个指针,将当前的指针指向的地址的值赋给PT
    return (WORD)(PT[0]+PT[1]*256); //计算这个16位数,(低8位在前面,高8位在后面),并来个强制类型转
                                                     //换,并返回
}
需要注意的是,LD_WORD返回的就必须是WORD。这样做了,编译器大部分的也可以编译通过,但是ADS就是通不过,有3个地方,
    finfo->fsize = LD_DWORD (&dir[DIR_FileSize]);    /* Size */
    finfo->fdate = LD_WORD (&dir[DIR_WrtDate]);        /* Date */
    finfo->ftime = LD_WORD (&dir[DIR_WrtTime]);        /* Time */
其中,dir的是这样定义的:const BYTE *dir,编译器报错是类型不匹配,因此,这里的几个LD_WORD和LD_DWORD重写,定义成一致的类型即可:
    WORD    LD_WORD_1 (const BYTE *pt)
{
    BYTE *PT = (BYTE*)pt;
    return (WORD)(PT[0]+PT[1]*256);
}

DWORD    LD_DWORD_1 (const BYTE *pt)
{
    BYTE *PT = (BYTE*)pt;
    return ((DWORD)PT[0]+(DWORD)(PT[1]*256)+(DWORD)(PT[2]*65536)+(DWORD)(PT[3]*16777216));       
}

而后面改成:
    finfo->fsize = LD_DWORD_1 (&dir[DIR_FileSize]);    /* Size */
    finfo->fdate = LD_WORD_1 (&dir[DIR_WrtDate]);        /* Date */
    finfo->ftime = LD_WORD_1 (&dir[DIR_WrtTime]);        /* Time */

编译,一路OK,然后写一个文件,哇,哈哈哈哈!!!!终于出来了!!!!写文件没问题,读也没问题!@~~~~~测试了常用的函数,都没有问题,包括格式化(f_mkfs,前提是你的 disk_ioctl 没问题),测试
了下速度,读12.5M的MP3,大约3秒,写这个12.5M的MP3大约6.5秒,勉强达到要求,再优化下驱动那边就可以更快了!~~~~~~~

发个FatFs的官方网址 http://elm-chan.org/fsw/ff/00index_e.html

总结这次移植,差点失败就在于编译器的指针的转换问题,写出来,希望兄弟姐妹们在移植的时候不会遇到这种问题。

转fatfs 文件系统选择相关推荐

  1. FatFs文件系统的移植

    FatFs 的底层可以写一次命令,读写多个扇区.FatFs的设计的读写的思想就很好,小块的数据,我就经过Buffer来存储,大块的数据,我就直接进行存取,那样速度,效率高了很多,看图: FatFs文件 ...

  2. 基于SD卡的FatFs文件系统(FatFs移植到STM32)

    平台:STM32ZET6(核心板)+ST-LINK/V2+SD卡+USB串口线 工程介绍:主要文件在USER组中,bsp_sdio_sdcard.c,bsp_sdio_sdcard.h和main.c, ...

  3. STM32CubeMX学习笔记(25)——FatFs文件系统使用(操作SPI Flash)

    一.FatFs简介 FatFs 是面向小型嵌入式系统的一种通用的 FAT 文件系统.它完全是由 ANSI C 语言编写并且完全独立于底层的 I/O 介质.因此它可以很容易地不加修改地移植到其他的处理器 ...

  4. 2021-08-11 TM32F103 Buffer FatFs 文件系统移植

    FatFs 本文展示了STM32 FatFs文件系统移植 内容涉及 : FatFs 文件系统移植 SPI函数移植过程 SPI字节数据模拟输出独写 缓存读写 USART串口的识别 IO口输入输出 按键的 ...

  5. STM32CubeMX系列09——SDIO(SD卡读写、SD卡移植FATFS文件系统)

    文章目录 1. 准备工作 1.1. 简单扫盲 1.1.1. SD卡 1.1.2. TF卡 1.1.3. SDIO接口 1.2. 所用硬件及原理图 2. 创建工程 2.1. 选择主控 2.2. 系统配置 ...

  6. 模拟SPI进行TF卡操作+Fatfs文件系统移植

    FATFS版本:FATFS R0.13b SD卡容量:16G 概述 本文的重点是进行Fatfs文件系统的移植和初步的使用.TF卡的操作实际上是指令操作,即你想它发送固定的CMD指令,它接收到指令给你返 ...

  7. fatfs文件系统详解之f_mkfs函数分析

    前序 前面两篇文章分析了FAT文件系统,没有代码总感觉很空虚寂寞冷,fatfs正好是一个开源专门应对fat文件系统的代码,从这篇文章开始分析fatfs代码,"理论+实践"才是悟道的 ...

  8. STM32+雷龙SD NAND(贴片SD卡)完成FATFS文件系统移植与测试

    一.前言 在STM32项目开发中,经常会用到存储芯片存储数据. 比如:关机时保存机器运行过程中的状态数据,上电再从存储芯片里读取数据恢复:在存储芯片里也会存放很多资源文件.比如,开机音乐,界面上的菜单 ...

  9. 基于STM32采用CS创世 SD NAND(贴片SD卡)完成FATFS文件系统移植与测试

    一.前言 在STM32项目开发中,经常会用到存储芯片存储数据. 比如:关机时保存机器运行过程中的状态数据,上电再从存储芯片里读取数据恢复:在存储芯片里也会存放很多资源文件.比如,开机音乐,界面上的菜单 ...

  10. [笔记]STM32基于HAL库的SDIO+FATFS文件系统

    1.背景 要用到Bootloader升级,APP部分要写运行日志.所以在Bootloader部分的FATFS要做裁剪,裁剪到只剩只读的操作就可以了,而APP端做可读可写. 2.开发板 用的是野火的ST ...

最新文章

  1. 卸载一直在创建还原点_Win10电脑开机一直转圈无法进入系统的解决方法
  2. Android Gradle manifestPlaceholders 占位符详解
  3. 二十个你必须知道的SEO概念
  4. Spring-Cloud中的 熔断、限流、降级
  5. c mysql 视图_MySQL入门教程(七)之视图
  6. 小程序开发(1)-之目录结构和文件说明
  7. 【LeetCode】 Best Time to Buy and Sell Stock I II III IV 解题报告
  8. Flutter布局锦囊---验证码倒计时
  9. A 股暴跌,户均亏 2 万!刚写好的辞职信又撕了……
  10. java stream findlast_恕我直言你可能真的不会java第9篇-Stream元素的匹配与查找
  11. 转载:三种方式使得iOS应用能够在后台进行数据更新和下载
  12. tp框架修改后台访问地址
  13. 全图各省市乡镇数据交流
  14. 1fichier.com-1TB免费FTP空间的使用
  15. 2019最新升级【超能版】 vbox硬件级虚拟机系统 去虚拟化去vm标识 支持批量启动 批量克隆 CPA网赚挂机电商 virtualbox
  16. node在linux无法连接mysql,无法连接到Node.js上的MySQL数据库
  17. 使用Lambda(拉姆达)对集合进行排序,一行代码即可解决
  18. 4种高速安全混合云解决方案,助力您的云迁移之旅
  19. **购买外链必须注意的四点经验_购链网**
  20. 微信小程序云开发入门教程

热门文章

  1. 1.6秒能干什么?自动锁螺丝机表演给你看
  2. 华为流程解析流程的端到端
  3. 计算机excel函数试题,2014职称计算机考试Excel试题函数练习题
  4. SACD ISO提取DSF文件及添加封面
  5. 《遥感原理与应用》第三版——思维导图
  6. 机械硬盘显示无法访问由于IO设备错误的资料找回方法
  7. Java八大基本数据类型
  8. TCP|IP+WIFI无线远程网络RFID|NFC读卡器HX530-Q-A系列Server网络模式与 Client网络模式设置说明
  9. 关于软考,人事考试照片格式要求如何修改,且通过照片审核处理系统。要求295px*413px像素
  10. Z逆变换(2020.10.21)