历史上的今天
返回首页

历史上的今天

今天是:2024年09月09日(星期一)

正在发生

2020年09月09日 | stm32+sdio+文件系统 源码分析

2020-09-09 来源:eefocus

一、概述
1、目的
在移植之前,先将源代码大概的阅读一遍,主要是了解文件系统的结构、各个函数的功能和接口、与移植相关的代码等等。


2、准备工作
在官方网站下载了0.07c版本的源代码,利用记事本进行阅读。


二、源代码的结构
1、源代码组成
源代码压缩包解压后,共两个文件夹,doc是说明,src里就是代码。src文件夹里共五个文件和一个文件夹。文件夹是option,还有00readme.txt、diskio.c、diskio.h、ff.c、ff.h、integer.h。对比网上的文章,版本已经不同了,已经没有所谓的tff.c和tff.h了,估计现在都采用条件编译解决这个问题了,当然文件更少,可能编译选项可能越复杂。


2、00readme.txt的说明
  Low level disk I/O module is not included in this archive because the FatFs
  module is only a generic file system layer and not depend on any specific
  storage device. You have to provide a low level disk I/O module that written
  to control your storage device.主要是说不包含底层IO代码,这是个通用文件系统可以在各种介质上使用。我们移植时针对具体存储设备提供底层代码。


接下来做了版权声明-可以自由使用和传播。

然后对版本的变迁做了说明。


3、源代码阅读次序
先读integer.h,了解所用的数据类型,然后是ff.h,了解文件系统所用的数据结构和各种函数声明,然后是diskio.h,了解与介质相关的数据结构和操作函数。再把ff.c和diskio.c两个文件所实现的函数大致扫描一遍。最后根据用户应用层程序调用函数的次序仔细阅读相关代码。


三、源代码阅读
1、integer.h头文件
这个文件主要是类型声明。以下是部分代码。
typedef int    INT;
typedef unsigned int UINT;
typedef signed char  CHAR;/* These types must be 8-bit integer */
都是用typedef做类型定义。移植时可以修改这部分代码,特别是某些定义与你所在工程的类型定义有冲突的时候。


2、ff.h头文件
以下是部分代码的分析
#include "integer.h" 使用integer.h的类型定义
#ifndef _FATFS
#define _FATFS 0x007C  版本号007c,0.07c
#define _WORD_ACCESS 0 //如果定义为1,则可以使用word访问。
中间有一些看着说明很容易弄清楚意思。这里就不例举了。

#define _CODE_PAGE 936
/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
OEM code page什么意思不大明白。
/   936  - Simplified Chinese GBK (DBCS, OEM, Windows)跟据这个中国应该是936.
打开option文件夹看一下。打开cc936.c文件,里面有一个很大的数组static const WCHAR uni2oem[] 。

根据英文说明,这个数组用于unicode码和OEM码之间的相互转换。
接下来又有两个函数ff_convert()和ff_wtoupper()具体执行码型转换和将字符转换为大写。
 
百度一下:看OEM码什么意思。
unicode是一种双字节字符编码,无论中文还是英文,或者其他语言统一到2个字节。与现有的任何编码(ASCII,GB等)都不兼容。WindowsNT(2000)的内核即使用该编码,所有数据进入内核前转换成UNICODE,退出内核后在转换成版本相关的编码(通常称为OEM,在简体中文版下即为GB).(百度所得)继续往下阅读。


#define _USE_LFN 1   //这个估计是长文件名支持了,以前的0.06版本好像是不支持。
#define _MAX_LFN 255 //最长支持255个双字节字符。


#define _FS_RPATH 0  //是否文件相对路径选项。
/* When _FS_RPATH is set to 1, relative path feature is enabled and f_chdir,
/  f_chdrive function are available.  //有些函数会受影响。
/  Note that output of the f_readdir fnction is affected by this option. */

#define _FS_REENTRANT 0  //如果要支持文件系统可重入,必须加入几个函数。
#define _TIMEOUT  1000 /* Timeout period in unit of time ticks of the OS */
#define _SYNC_t   HANDLE /* Type of sync object used on the OS. e.g. HANDLE,

OS_EVENT*, ID and etc.. */
/* To make the FatFs module re-entrant, set _FS_REENTRANT to 1 and add user
/  provided synchronization handlers, ff_req_grant, ff_rel_grant, ff_del_syncobj
/  and ff_cre_syncobj function to the project. */

#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */
#define _DF1S 0x81
#define _DF1E 0xFE
#define _DS1S 0x40
#define _DS1E 0x7E
#define _DS2S 0x80
#define _DS2E 0xFE
接下来很大一部分都是与语言相关的因素,略过。

/* Character code support macros */ 三个宏判断是否大写、小写、数字。
#define IsUpper(c) (((c)>='A')&&((c)<='Z'))
#define IsLower(c) (((c)>='a')&&((c)<='z'))
#define IsDigit(c) (((c)>='0')&&((c)<='9'))

#if _DF1S     /* DBCS configuration */双字节编码相关的设定,暂时不理会它。

#if _MULTI_PARTITION         /* Multiple partition configuration */

//该变量定义为1时,支持一个磁盘的多个分区。

typedef struct _PARTITION {

       BYTE pd;     /* Physical drive# */

       BYTE pt;      /* Partition # (0-3) */

} PARTITION;

Extern  const  PARTITION Drives[];//如果支持分区,则声明变量Drivers   

#define LD2PD(drv) (Drives[drv].pd)      /* 获得磁盘对应的物理磁盘

#define LD2PT(drv) (Drives[drv].pt)       /*获得磁盘对应的分区

#else                                         /* Single partition configuration */

#define LD2PD(drv) (drv)  /* Physical drive# is equal to the logical drive# */

#define LD2PT(drv) 0        /* Always mounts the 1st partition */

 

#if _MAX_SS == 512  //一般扇区长度取512字节。

#define   SS(fs)     512U

 

#if _LFN_UNICODE && _USE_LFN

typedef WCHAR XCHAR;       /* Unicode */ XCHAR是文件名的码型所用。

#else

typedef char XCHAR;        /* SBCS, DBCS */

#endif

 

typedef struct _FATFS_ {

       BYTE    fs_type;         /* FAT sub type */

       BYTE    drive;             /*对应实际驱动号01--- */

       BYTE    csize;             /* 每个簇的扇区数目 */

先查一下簇的含义:应该是文件数据分配的基本单位。

       BYTE    n_fats;           /* 文件分配表的数目 */

FAT文件系统依次应该是:引导扇区、文件分配表两个、根目录区和数据区。

       BYTE    wflag;            /* win[] dirty flag (1:must be written back) */

//文件是否改动的标志,为1时要回写。

       WORD  id;                 /* File system mount ID 文件系统加载ID*/

       WORD  n_rootdir;      /* 根目录区目录项的数目 */

#if _FS_REENTRANT

       _SYNC_t     sobj;              /* 允许重入,则定义同步对象 */

#endif

#if _MAX_SS != 512

       WORD  s_size;           /* Sector size */

#endif

#if !_FS_READONLY  //文件为可写

       BYTE    fsi_flag;   /* fsinfo dirty flag (1:must be written back) */

//文件需要回写的标志

       DWORD      last_clust;      /* Last allocated cluster */

       DWORD      free_clust;      /* Number of free clusters */

       DWORD      fsi_sector;      /* fsinfo sector */

#endif

#if _FS_RPATH

       DWORD      cdir;              /* 使用相对路径,则要存储文件系统当前目录

#endif

       DWORD      sects_fat;       /*文件分配表占用的扇区

       DWORD      max_clust;     /* 最大簇数

       DWORD      fatbase;  /*文件分配表开始扇区

       DWORD      dirbase;  /*  如果是FAT32,根目录开始扇区需要首先得到。

       DWORD      database;       /* 数据区开始扇区

       DWORD      winsect;  /* Current sector appearing in the win[] */

//目前的扇区在win[]里面,这个win[]数组暂时还不知道含义。

       BYTE    win[_MAX_SS];/* Disk access window for Directory/FAT */

//这是一个win[512]数组,存储着一个扇区,好像作为扇区缓冲使用。

} FATFS;

 

typedef struct _DIR_ {

       FATFS* fs;/* Pointer to the owner file system object */指向相应文件系统对象。

       WORD  id;                 /* 文件系统加载ID*/

       WORD  index;     /* Current read/write index number */目前读写索引代码

       DWORD      sclust;     /* Table start cluster (0:Static table) */文件数据区开始簇

       DWORD      clust;             /* Current cluster */ 目前处理的簇

       DWORD      sect;              /* Current sector */ 目前簇里对应的扇区

       BYTE*  dir;  /* Pointer to the current SFN entry in the win[] */

       BYTE*  fn;                 /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */

#if _USE_LFN

       WCHAR*     lfn;   /* Pointer to the LFN working buffer */ 指向长文件名缓冲。

       WORD  lfn_idx;   /* Last matched LFN index number (0xFFFF:No LFN) */

#endif

} DIR;

 

typedef struct _FIL_ {

       FATFS* fs;                  /* Pointer to the owner file system object */

       WORD  id;                 /* Owner file system mount ID */

       BYTE    flag;        /* File status flags */文件状态标志

       BYTE    csect;            /* Sector address in the cluster */扇区偏移

推荐阅读

史海拾趣

Display Engineering Services公司的发展小趣事

以下是五个电子行业里Display Engineering Services公司发展起来的相关故事:

故事一:
在科技日新月异的今天,XX公司凭借其在Display Engineering Services领域的专业技术和创新能力,逐渐崭露头角。起初,XX公司只是一家专注于显示屏研发的小型技术公司,但在市场需求的驱动下,公司意识到为客户提供定制化的显示屏解决方案具有巨大潜力。于是,XX公司开始将重心转移到Display Engineering Services上,通过深入了解客户需求,提供从设计、制造到安装的全流程服务。经过数年的努力,XX公司不仅积累了丰富的经验,还建立起一支专业的技术团队,赢得了业界的广泛认可。

故事二:
YY公司的发展历程颇具传奇色彩。该公司最初只是一家为电子产品提供显示屏配件的供应商。然而,随着市场竞争的加剧,YY公司意识到单纯提供配件已无法满足客户需求。于是,公司决定转型为Display Engineering Services提供商,致力于为客户提供显示屏的定制设计和优化服务。YY公司凭借其卓越的技术实力和敏锐的市场洞察力,成功转型,并在短时间内实现了业务的快速增长。如今,YY公司已成为行业内的佼佼者,其显示屏解决方案广泛应用于各个领域。

故事三:
ZZ公司是一家专注于Display Engineering Services的创业公司。在创立之初,公司面临着资金短缺、技术瓶颈等诸多困难。然而,创始人凭借对技术的热爱和对市场的敏锐洞察,带领团队攻克了一个又一个技术难题。同时,ZZ公司还积极寻求外部合作,与多家知名企业建立了紧密的合作关系,共同开发具有市场竞争力的显示屏产品。在团队成员的共同努力下,ZZ公司逐渐在Display Engineering Services领域崭露头角,成为了一家备受瞩目的创新型企业。

故事四:
AA公司的发展历程充满了挑战与机遇。在成立初期,公司面临着激烈的市场竞争和不断变化的客户需求。为了应对这些挑战,AA公司决定加大研发投入,不断提升自身的技术实力。同时,公司还积极拓展国际市场,与全球多家知名企业建立了合作关系。通过不断的技术创新和市场拓展,AA公司逐渐在Display Engineering Services领域树立了良好的品牌形象,赢得了客户的信赖和支持。

故事五:
BB公司是一家历史悠久的Display Engineering Services企业。多年来,公司始终坚持以客户需求为导向,不断提升服务质量和技术水平。为了保持竞争优势,BB公司不断引进先进的生产设备和技术人才,加强内部管理和质量控制。同时,公司还积极参与行业交流和合作,与国内外多家知名企业建立了良好的合作关系。在多年的发展中,BB公司积累了丰富的经验和技术优势,成为了行业内的领军企业之一。其显示屏解决方案广泛应用于各个领域,并获得了多项国内外技术专利和荣誉。

Geo Semiconductor Inc公司的发展小趣事
采用更先进的微处理器或PLC(可编程逻辑控制器)作为控制核心,以提高控制精度和响应速度。
BRIGHT公司的发展小趣事

BRIGHT公司不仅在电子产品领域取得了成功,还积极拓展酒店业务。他们成立了伯瑞特酒店集团,并在全国范围内开设了多家酒店。这些酒店以高品质的服务和独特的文化特色赢得了广大消费者的喜爱。其中,宁波伯瑞特酒店荣获了全国钻级酒店评定中的五钻酒家称号,千岛湖伯瑞特度假酒店也获得了金鼎特色文化主题饭店的荣誉。这些荣誉的获得不仅彰显了BRIGHT公司在酒店业务方面的实力,也为其未来的发展奠定了坚实的基础。

Econais公司的发展小趣事

随着技术的不断成熟和市场的日益扩大,Econais开始将目光投向全球市场。公司积极参加各类国际展会和研讨会,与全球各地的客户和合作伙伴建立联系。同时,Econais还针对不同地区的市场需求,推出定制化的产品和解决方案。这些努力使得Econais在全球范围内的市场份额逐渐扩大。

Aavid Thermalloy公司的发展小趣事

为了加速产品的市场推广和应用,Econais积极寻求与行业内其他优秀企业的合作。XXXX年,Econais与Xively公司达成战略合作,共同为工业、商业和住宅市场提供一站式的物联网解决方案。通过这次合作,Econais的WiSmart Wi-Fi用户能够无缝连接到Xively云,为各种物联网应用提供强有力的支持。

Defense Supply Center Columbus公司的发展小趣事

Defense Supply Center Columbus公司自成立之初,就深知技术创新对于电子行业的重要性。公司投入大量资源,建立起一支专业的研发团队,专注于研发先进的军事电子设备和系统。通过不断的技术创新,公司成功开发出了一系列高性能、高可靠性的军事电子产品,为国防事业做出了重要贡献。这些产品的成功推出,不仅提升了公司的市场地位,也为公司赢得了众多客户的信赖和好评。

问答坊 | AI 解惑

问一下

如果感应头不工作是什么原因啊,工作的发光二极管亮,但是感应头不工作。谁知道有那些原因啊 程序好使,只是从硬件上找。…

查看全部问答>

Linux2.6完全 移植教程,基于TQ2440开发板

开发板移植好教程,入门者的福音 还在为Linux移植入门而烦恼吗?还在为Linux驱动而头痛吗?还在为没有一本从入门到真正移植的好书苦闷吗? 现在您有一个好的选择,天嵌科技推出一部和开发板完美结合的教程:从下载源码到将内核移植适合于TQ2440开 ...…

查看全部问答>

51和fpga通信

那个知道51怎么和FPGA通信啊?高手指点下啊!!…

查看全部问答>

ce ActiveSync连接的问题

ActiveSync通过USB接口连接设备一直挺好的,可今天我拔usb线断开连接啊,机子死机了,重启过后就不行了,ce设备起来后无法自动连上,我只好手动运行repllop.exe进行连接,连上后,下载程序,运行很慢。我卸载重装都不行,换USB接口也不行,请问我改 ...…

查看全部问答>

at89c51芯片加上cd4511bcn做一个计数器出错,请教下挫在那里?

at89c51芯片的p0管脚作为2个四位bcd码的输出到cd4511bcn中去,然后通过cd4511bcn输出到2个8段显示器中,但是总是没有任何反应,请各位帮忙看看:以下是代码: -+         COUNT        EQU     ...…

查看全部问答>

wince下怎么显示图像阴影

填充圆内的颜色, wince里不能用CreateHatchBrush显示各种阴影,那有什么其他函数能显示呢? 画直线, wince里不能用CreatePen的另一种函数,那如果我想画各种线该怎么做呢?比如点线…

查看全部问答>

诺基亚卖了Qt,未来还会卖什么?

  已经决定和微软合作开发Windows Phone手机的诺基亚,就把原来收购的 Qt放到了角落。据国外媒体报道,诺基亚决定将QT商业授权和服务业务出售给一家芬兰Digia公司,Digia计划雇用19名的诺基亚原来QT 相关雇员。        ...…

查看全部问答>

请大哥看看我的这个问题

我的MCU与上位机通信,同时需要处理一些事务,但当处理某些事务时是不允许上位机通信中断的,这样上位机通信有些时候就不通,当比较严重的时候是无法接受的,这是不是就要用到多任务操作系统了,专门用一个任务来与上位机中断通信,另外的任务来处 ...…

查看全部问答>

开关电源讲议

开关电源讲议,对初学者很有帮助的! [ 本帖最后由 aishuang 于 2011-7-17 07:43 编辑 ]…

查看全部问答>