伦伦影院久久影视,天天操天天干天天射,ririsao久久精品一区 ,一本大道香蕉大久在红桃,999久久久免费精品国产色夜,色悠悠久久综合88,亚洲国产精品久久无套麻豆,亚洲香蕉毛片久久网站,一本一道久久综合狠狠老

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

瑞薩RA系列FSP庫開發(fā)實戰(zhàn)指南之基于FLASH的FatFs文件系統(tǒng)移植實驗

瑞薩嵌入式小百科 ? 來源:野火電子 ? 2026-03-18 13:53 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

24.4

FatFs文件系統(tǒng)移植實驗

24.4.1

硬件設計及FSP

FatFs屬于軟件組件,不需要附帶其他硬件電路。我們使用串行Flash芯片作為物理存儲設備,其硬件電路在上一章已經(jīng)做了分析,這里就直接使用。

24.4.2

FatFs移植步驟概述

基本步驟:

實現(xiàn)底層驅動接口

修改配置文件

移植FatFs之前我們先通過FatFs的程序結構圖了解FatFs在程序中的關系網(wǎng)絡,見圖FatFs程序結構圖。

a62d3156-2280-11f1-90a1-92fbcf53809c.png

用戶應用程序需要由用戶編寫,想實現(xiàn)什么功能就編寫什么的程序,一般我們只用到f_mount()、f_open()、f_write()、f_read()就可以實現(xiàn)文件的讀寫操作。

FatFs組件是FatFs的主體,文件都在源碼src文件夾中,其中ff.c、ff.h、ffsystem.c以及ffunicode.c4個文件我們不需要改動,只需要修改ffconf.h和diskio.c/.h3個文件。

底層設備輸入輸出要求實現(xiàn)存儲設備的讀寫操作函數(shù)、存儲設備信息獲取函數(shù)等等。我們使用串行Flash芯片作為物理設備,在上一章節(jié)已經(jīng)編寫好了串行Flash芯片的驅動程序,這里我們就直接使用。

24.4.2.1

實現(xiàn)底層驅動接口

FatFs文件系統(tǒng)與底層介質(zhì)的驅動分離開來,對底層介質(zhì)的操作都要交給用戶去實現(xiàn),它僅僅是提供了一個函數(shù)接口而已。表FatFs移植需要用戶支持函數(shù)為FatFs移植時用戶必須支持的函數(shù)。

通過表FatFs移植需要用戶支持函數(shù)我們可以清晰知道很多函數(shù)是在一定條件下才需要添加的,只有前三個函數(shù)是必須添加的。我們完全可以根據(jù)實際需求選擇所需用到的函數(shù)。

前三個函數(shù)是實現(xiàn)讀文件最基本需求。接下來三個函數(shù)是實現(xiàn)創(chuàng)建文件、修改文件需要的。為實現(xiàn)格式化功能,需要在disk_ioctl添加兩個獲取物理設備信息選項。我們一般只要實現(xiàn)前面六個函數(shù)就可以了,已經(jīng)足夠滿足大部分功能。

為支持簡體中文長文件名稱需要添加ff_uni2oem、ff_oem2uni和ff_wtoupper 函數(shù),實際這三個已經(jīng)在ffunicode.c文件中實現(xiàn),我們只要直接把ffunicode.c文件添加到工程中就可以。

a6874510-2280-11f1-90a1-92fbcf53809c.png

底層設備驅動函數(shù)是存放在diskio.c文件,我們的目的就是把diskio.c中的函數(shù)接口與串行Flash芯片驅動連接起來。總共有五個函數(shù),分別為設備狀態(tài)獲取(disk_status)、設備初始化(disk_initialize)、扇區(qū)讀取(disk_read)、扇區(qū)寫入(disk_write)、其他控制(disk_ioctl)。

接下來,我們對每個函數(shù)結合串行Flash芯片驅動做詳細講解。

24.4.2.2

修改配置文件

ffconf.h文件是FatFs的配置文件。

下面是ffconf.h文件中,需要修改的部分,只把需要修改的部分放出來:

列表1:

代碼清單24?1 FatFs的配置文件:ffconf.h

左右滑動查看完整內(nèi)容


/********************/
/* 下面是經(jīng)過修改部分 */
/********************/

#define FF_USE_MKFS          1   //此選項切換是否啟用 f_mkfs() 函數(shù),用于格式化 Flash、SD卡等
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */


#define FF_CODE_PAGE 936     //此選項指定使用的OEM代碼頁
/* This option specifies the OEM code page to be used on the target system.
/  Incorrect code page setting can cause a file open failure.
/
/   437 - U.S.
/   720 - Arabic
/   737 - Greek
/   771 - KBL
/   775 - Baltic
/   850 - Latin 1
/   852 - Latin 2
/   855 - Cyrillic
/   857 - Turkish
/   860 - Portuguese
/   861 - Icelandic
/   862 - Hebrew
/   863 - Canadian French
/   864 - Arabic
/   865 - Nordic
/   866 - Russian
/   869 - Greek 2
/   932 - Japanese (DBCS)
/   936 - Simplified Chinese (DBCS)
/   949 - Korean (DBCS)
/   950 - Traditional Chinese (DBCS)
/     0 - Include all code pages above and configured by f_setcp()
*/


#define FF_USE_LFN           2       //此選項切換對長文件名的支持
#define FF_MAX_LFN           255     //設置長文件名的最長長度
/* The FF_USE_LFN switches the support for LFN (long file name).
/
/   0: Disable LFN. FF_MAX_LFN has no effect.
/   1: Enable LFN with static  working buffer on the BSS. Always NOT thread-safe.
/   2: Enable LFN with dynamic working buffer on the STACK.
/   3: Enable LFN with dynamic working buffer on the HEAP.


#define FF_LFN_UNICODE       2       //此選項設置是否啟用 Unicode 字符編碼
/* This option switches the character encoding on the API when LFN is enabled.
/
/   0: ANSI/OEM in current CP (TCHAR = char)
/   1: Unicode in UTF-16 (TCHAR = WCHAR)
/   2: Unicode in UTF-8 (TCHAR = char)
/   3: Unicode in UTF-32 (TCHAR = DWORD)
/
/  Also behavior of string I/O functions will be affected by this option.
/  When LFN is not enabled, this option has no effect. */


#define FF_VOLUMES           2       //要使用的卷(邏輯驅動器)的數(shù)量。范圍(1-10)
/* Number of volumes (logical drives) to be used. (1-10) */


#define FF_MIN_SS            512
#define FF_MAX_SS            4096    //這組選項配置支持的扇區(qū)大小范圍
/* This set of options configures the range of sector size to be supported. (512,
/  1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
/  harddisk, but a larger value may be required for on-board flash memory and some
/  type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
/  for variable sector size mode and disk_ioctl() function needs to implement
/  GET_SECTOR_SIZE command. */
/* 若 FF_MIN_SS != FF_MAX_SS。則需要在 disk_ioctl() 中指定所需操作的設備的扇區(qū)大小
 * 在 case GET_SECTOR_SIZE 項中指定 */

#define FF_FS_NORTC          1   //設置為1關閉時間戳  啟用時間戳功能需要RTC
#define FF_NORTC_MON 1
#define FF_NORTC_MDAY        1
#define FF_NORTC_YEAR        2022
/* The option FF_FS_NORTC switches timestamp feature. If the system does not have
/  an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the
/  timestamp feature. Every object modified by FatFs will have a fixed timestamp
/  defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
/  To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
/  added to the project to read current time form real-time clock. FF_NORTC_MON,
/  FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
/  These options have no effect in read-only configuration (FF_FS_READONLY = 1). */

24.4.3.路徑名格式說明

在 FatFs 的 API 函數(shù)中,經(jīng)常能看到 “const TCHAR* path” 這樣的函數(shù)參數(shù),比如:

FRESULT f_mount (
    FATFS* fs,                      /* 指向要注冊的文件系統(tǒng)對象的指針(NULL:卸載) */
    const TCHAR* path,      /* 要裝載/卸載的邏輯驅動器號 */
    BYTE opt                        /* 裝載選項:0=不裝載(延遲裝載),1=立即裝載 */
)

FRESULT f_open (
    FIL* fp,                        /* 指向空白文件對象的指針 */
    const TCHAR* path,      /* 指向文件名的指針 */
    BYTE mode                       /* 訪問模式和打開模式標志 */
)

這就要求我們要知道 path 這個參數(shù)的可輸入值是什么,也就是我們要了解FatFs的文件命名規(guī)范。

24.4.3.1.文件命名格式

FatFs模塊上的路徑名格式與DOS/Windows的文件名規(guī)范類似,如下所示:

[drive#:][/]"directory 目錄"/"file 文件"

FatFs 模塊支持長文件名(LFN) 和 8.3 格式的文件名 (SFN)。長文件名(LFN) 可在 FF_USE_LFN >= 1 時使用。 子目錄用 \ 或 / 分隔,方式與DOS/Windows API相同。 重復的分隔符和終止分隔符將被忽略,例如:“//animal///cat/”。 唯一不同的是,F(xiàn)atFs中指定邏輯驅動器(FAT卷)的標題驅動器前綴是數(shù)字(0-9)+冒號,而在DOS/Windows中是字母(A-Z)+冒號。 邏輯驅動器編號是指定要訪問的卷的標識符。 如果省略驅動器前綴,則假定邏輯驅動器編號為默認驅動器。

注解

LFN 和 SFN

8.3 命名規(guī)則,又稱短文件名(Short File Name,SFN)是一種限制文件名長度的方法,這在DOS和Windows 95及Windows NT 3.51以前的Microsoft Windows版本中,在FAT文件系統(tǒng)中的常用方法。

長文件名,(Long file name,LFN)也指長文件名支持。在舊版本的DOS操作系統(tǒng)下,因為文件名稱有8.3格式的限制,凡文件主檔名超過8字節(jié)或擴展名超過3字節(jié)的文件名,都被稱為“長文件名”,在Windows下正常的文件名置換于DOS(或“命令提示字符”)環(huán)境下則可能無法完整顯示,如“Program files”資料夾可能會顯示成其對應的8.3文件名“PROGRA~1”。

24.4.3.2.FF_FS_RPATH

在默認配置 (FF_FS_RPATH==0) 中, 是沒有當前目錄的概念的。 卷上的每個對象始終以從根目錄開始的完整路徑名指定。 不可以使用點目錄名稱(“.”,“..”)。標題分隔符被忽略, 它可以存在或省略。默認驅動器固定為驅動器0。

啟用相對路徑功能時(FF_FS_RPATH>=1),如果存在分隔符, 則從根目錄跟隨指定的路徑。如果沒有分隔符,則從默認驅動器的當前目錄開始。 路徑名也允許使用點目錄名。 當前目錄由f_chdir函數(shù)設置,默認驅動器為f_chdrive函數(shù)設置的當前驅動器。

wKgZO2m6P1iAf4yfAAJUjib56NU881.png

此外,驅動器前綴可以采用預定義的任意字符串。 當選項FF_STR_VOLUME_ID == 1 時,也可以將任意字符串卷 ID 用作驅動器前綴。 例如 “flash:file1.txt”、“ram:temp.dat” 或 “sd:” 。 如果 srting 與任何卷 ID 都不匹配,則該函數(shù)將失敗并返回 FR_INVALID_DRIVE。

當FF_STR_VOLUME_ID == 2 時,可以使用 Unix 樣式的驅動器前綴。 例如 “/flash/file1.txt”、“/ram/temp.dat” 或 “/sd” 。

FF_STR_VOLUME_ID 和 FF_VOLUME_STRS

#define FF_STR_VOLUME_ID    0  //FF_STR_VOLUME_ID開關支持任意字符串形式的卷ID。
#define FF_VOLUME_STRS              "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
/  When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
/  number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
/  logical drives. Number of items must not be less than FF_VOLUMES. Valid
/  characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
/  compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
/  not defined, a user defined volume string table needs to be defined as:
/
/  const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
*/

FF_STR_VOLUME_ID: 此選項切換對字符串卷 ID 的支持。

FF_STR_VOLUME_ID 為不同數(shù)值時,對應的可選項
數(shù)值 描述 示例
0 只能使用數(shù)字 ID 中的 DOS/Windows 樣式驅動器前綴。 1:/filename
1 還可以使用字符串 ID 中的 DOS/Windows 樣式驅動器前綴。 flash:/filename
2 也可以使用字符串ID中的Unix樣式驅動器前綴。 /flash/filename

FF_VOLUME_STRS: 此選項定義每個邏輯驅動器的卷 ID 字符串。項目數(shù)量不得少于FF_VOLUMES。 卷 ID 字符串的有效字符是 A-Z、a-z 和 0-9,不區(qū)分大小寫。 如果FF_STR_VOLUME_ID == 0,則此選項不起作用。 如果 FF_STR_VOLUME_ID >= 1 并且未定義此選項, 則需要定義用戶定義的卷字符串表,如下所示。不應動態(tài)修改該表。

用戶定義卷ID字符串

/* 0: ~ 3: 的用戶定義卷ID字符串: */
const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb"};

這里我們并沒有用到任意字符串形式的卷ID,就沒有開啟 FF_STR_VOLUME_ID 宏。

24.4.4.接口函數(shù)

主要的接口文件都在 diskio.c 文件中了,我們只需要根據(jù)函數(shù)所提供的輸入?yún)?shù)和返回參數(shù), 來實現(xiàn)函數(shù)的功能,提供給FatFs調(diào)用就好了。

FatFs文件系統(tǒng)與存儲設備的連接函數(shù)在diskio.c文件中,主要有5個函數(shù)需要我們編寫的。

宏定義和存儲設備狀態(tài)獲取函數(shù)

代碼清單: 24_2 disk_ioctl 函數(shù)

/*-----------------------------------------------------------------------*/
/* Get Drive Status                                                      */
/*-----------------------------------------------------------------------*/

DSTATUS disk_status (
   BYTE pdrv         /* Physical drive nmuber to identify the drive */
)
{
   DSTATUS stat;

   switch (pdrv) {
   case DEV_FLASH :
      QSPI_Flash_WaitForWriteEnd(); //等待Flash芯片內(nèi)部操作完成

      stat = RES_OK;
      return stat;

   }
   return STA_NOINIT;
}

存儲設備初始化函數(shù)

代碼清單: 24_3 disk_ioctl 函數(shù)

/*-----------------------------------------------------------------------*/
/* Inidialize a Drive                                                    */
/*-----------------------------------------------------------------------*/

DSTATUS disk_initialize (
   BYTE pdrv                         /* Physical drive nmuber to identify the drive */
)
{
   DSTATUS stat;

   switch (pdrv) {
   case DEV_FLASH :
      QSPI_Flash_Init();

      stat = RES_OK;
      return stat;

   }
   return STA_NOINIT;
}

存儲設備數(shù)據(jù)讀取函數(shù)

代碼清單: 24_4 disk_ioctl 函數(shù)

/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */
/*-----------------------------------------------------------------------*/

DRESULT disk_read (
   BYTE pdrv,                /* Physical drive nmuber to identify the drive */
   BYTE *buff,               /* Data buffer to store read data */
   LBA_t sector,     /* Start sector in LBA */
   UINT count                /* Number of sectors to read */
)
{
   DRESULT res;

   switch (pdrv) {
   case DEV_FLASH :
      // translate the arguments here

      QSPI_Flash_BufferRead(buff, sector<<12, count<<12); //1 sector == 4096 bytes

      res = RES_OK;
      return res;

   }

   return RES_PARERR;
}

存儲設備數(shù)據(jù)寫入函數(shù)

代碼清單: 24_5 disk_ioctl 函數(shù)

DRESULT disk_write (
   BYTE pdrv,                        /* Physical drive nmuber to identify the drive */
   const BYTE *buff, /* Data to be written */
   LBA_t sector,             /* Start sector in LBA */
   UINT count                        /* Number of sectors to write */
)
{
   DRESULT res;
   uint32_t write_addr;

   switch (pdrv) {
   case DEV_FLASH :
      write_addr = sector << 12;
      QSPI_Flash_SectorErase(write_addr);
      QSPI_Flash_BufferWrite(buff, write_addr, count<<12);

      res = RES_OK;
      return res;

   }

   return RES_PARERR;
}

IO控制函數(shù)

代碼清單: 24_6 disk_ioctl 函數(shù)

DRESULT disk_ioctl (
   BYTE pdrv,                /* Physical drive nmuber (0..) */
   BYTE cmd,         /* Control code */
   void *buff                /* Buffer to send/receive control data */
)
{
   DRESULT res;

   switch (pdrv) {
   case DEV_FLASH :
      switch (cmd) {
      case GET_SECTOR_COUNT:      /* 扇區(qū)數(shù)量:1024*4096/1024/1024 = 4(MB) */
            *(DWORD *)buff = 1024;
            break;
      case GET_SECTOR_SIZE:       /* 扇區(qū)大小  */
            *(WORD *)buff = 4096;
            break;
      case GET_BLOCK_SIZE:        /* 同時擦除扇區(qū)個數(shù) */
            *(DWORD *)buff = 1;
            break;
      }

      res = RES_OK;
      return res;

   }

   return RES_PARERR;
}

get_fattime函數(shù)

代碼清單: 24_7 disk_ioctl 函數(shù)

DWORD get_fattime(void) {
   /* 返回當前時間戳 */

   return (DWORD)(2022 - 80) << 25 |  /* Year */
         (DWORD)(1 + 1) << 21 |      /* Month */
         (DWORD)1 << 16 |            /* Mday */
         (DWORD)1 << 11 |            /* Hour */
         (DWORD)1 << 5 |             /* Min */
         (DWORD)1 >> 1;              /* Sec */
}

由于之前在配置文件關閉了 RTC 和時間戳功能,因此其實不需要實現(xiàn)這個返回當前時間戳函數(shù)。

由 FF_FS_NORTC 決定是否啟用,F(xiàn)F_FS_NORTC設置為1以禁用時間戳功能。

24.4.5.FatFs 基本 API 函數(shù)說明

更多關于 FatFs 接口函數(shù)的說明請看官方的說明:http://elm-chan.org/fsw/ff/00index_e.html

24.4.5.1.f_mount

f_mount 函數(shù)原型如下:

FRESULT f_mount (
FATFS*       fs,    /* [IN] Filesystem object */
const TCHAR* path,  /* [IN] Logical drive number */
BYTE         opt    /* [IN] Initialization option */
);

FatFs 需要每個邏輯驅動器(FAT 卷)的工作區(qū)域(文件系統(tǒng)對象)。 在執(zhí)行任何文件/目錄操作之前,需要使用邏輯驅動器的f_mount函數(shù)注冊文件系統(tǒng)對象。 完成此過程后,文件/目錄 API 函數(shù)已準備好工作。 某些卷管理功能(f_mkfs、f_fdisk和f_setcp)不需要文件系統(tǒng)對象。

f_mount函數(shù)將文件系統(tǒng)對象注冊/注銷到 FatFs 模塊,如下所示:

確定由 path 指定的邏輯驅動器。

清除并注銷卷的已注冊工作區(qū)(如果存在)。

如果 fs 不為 NULL,則清除新工作區(qū)并將其注冊到卷中。

如果指定了強制裝入,則對卷執(zhí)行卷裝入過程。

opt:安裝選項。0:現(xiàn)在不掛載(要在第一次訪問卷時掛載),1:強制掛載卷以檢查它是否準備好工作。

24.4.5.2.f_mkfs

f_mkfs函數(shù)原型如下:

FRESULT f_mkfs (
const TCHAR* path,   /* [IN] Logical drive number */
const MKFS_PARM* opt,/* [IN] Format options */
void* work,          /* [-]  Working buffer */
UINT len             /* [IN] Size of working buffer */
);

簇(cluster): 由于扇區(qū)的空間比較小且數(shù)目眾多,在尋址時比較困難, 所以操作系統(tǒng)就將多個的扇區(qū)組合在一起,形成一個更大的單位, 再對這個單位進行整體的操作。也可以理解為文件的磁盤空間分配單位。 當簇的大小為 32768 字節(jié)時,大小為 100 字節(jié)的文件將占用 32768 字節(jié)的磁盤空間。 隨著簇大小的增加,磁盤使用的空間效率會變得很低,但與此同時,讀/寫效率也會提高。 因此,簇的大小是空間效率和讀/寫效率之間的權衡。

opt:若為NULL,則啟用默認參數(shù)

f_mkfs opt 默認參數(shù)

static const MKFS_PARM defopt = {FM_ANY, 0, 0, 0, 0};        /* Default parameter */

由work來指向用于格式化過程的工作緩沖區(qū)的指針。

由len來確定工作緩沖區(qū)的大小(以字節(jié)為單位)。至少需要FF_MAX_SS。

提示

當 FF_FS_READONLY == 0 且 FF_USE_MKFS == 1 時可用。

24.4.5.3.f_setlabel

f_setlabel 函數(shù)原型如下:

FRESULT f_setlabel (
const TCHAR* label  /* [IN] Volume label to be set */
);

當字符串具有驅動器前綴時,卷標將設置為驅動器前綴指定的卷。 Unix 樣式的卷 ID 不能用于指定卷。 如果未指定驅動器號,則卷標將設置為默認驅動器。 如果給定卷標的長度為零,則將刪除卷上的卷標。卷標的格式如下所示:

在 FAT 卷上轉換 OEM 代碼頁時最多 11 個字節(jié)。 在 exFAT 卷中最多 11 個字符。 FAT 卷允許的字符數(shù)為:SFN 允許的字符不包括點。低寫字符向上轉換。 exFAT 卷允許的字符為:LFN 允許的字符包括點。將保留小寫字符。 空格可以嵌入卷標中的任何位置。尾隨空格在 FAT 音量處被截斷。

提示

當FF_FS_READONLY == 0 且FF_USE_LABEL == 1 時可用。

24.4.5.4.f_open

f_open 函數(shù)原型如下:

FRESULT f_open (
FIL* fp,           /* [OUT] Pointer to the file object structure */
const TCHAR* path, /* [IN] File name */
BYTE mode          /* [IN] Mode flags */
);

打開一個文件并創(chuàng)建一個文件對象。 完成對文件的訪問后應該使用f_close函數(shù)將其關閉。 如果在關機、移出介質(zhì)或重新裝入之前對文件進行了任何更改且未調(diào)用f_close函數(shù)將其關閉,則文件可能會 collapsed (損壞)。

可選mode選項:

wKgZO2m6P5eAA8miAAJRo8-RdEk792.png

提示

當FF_FS_READONLY == 1 時,只有FA_READ和FA_OPEN_EXISTING可用于模式標志。

24.4.5.5.f_close

f_close 函數(shù)原型如下:

FRESULT f_close (
FIL* fp     /* [IN] Pointer to the file object */
);

關閉打開的文件對象。如果文件已更改,則文件的緩存信息將寫回卷。 函數(shù)成功后,文件對象不再有效,可以丟棄。

請注意,如果文件對象處于只讀模式且未啟用FF_FS_LOCK, 則也可以在不執(zhí)行f_close函數(shù)的情況下丟棄該文件對象。 但是,不建議這樣做。

24.4.5.6.f_write

f_write 函數(shù)原型如下:

FRESULT f_write (
FIL* fp,          /* [IN] Pointer to the file object structure */
const void* buff, /* [IN] Pointer to the data to be written */
UINT btw,         /* [IN] Number of bytes to write */
UINT* bw          /* [OUT] Pointer to the variable to return number of bytes written */
);

該函數(shù)開始在讀/寫指針指向的文件偏移處將數(shù)據(jù)寫入文件。 讀/寫指針隨著寫入的字節(jié)數(shù)而前進。 功能成功后,應檢查 *bw 以檢測磁盤已滿。 如果 *bw < btw,則表示卷在寫入操作期間已滿。 該函數(shù)在卷已滿或接近滿時可能需要一段時間。

提示

FF_FS_READONLY == 0 時可用。

24.4.5.7.f_read

f_read 函數(shù)原型如下:

FRESULT f_read (
FIL* fp,     /* [IN] File object */
void* buff,  /* [OUT] Buffer to store read data */
UINT btr,    /* [IN] Number of bytes to read */
UINT* br     /* [OUT] Number of bytes read */
);

該函數(shù)開始在讀/寫指針指向的文件偏移處從文件中讀取數(shù)據(jù)。 讀/寫指針隨著讀取的字節(jié)數(shù)而前進。 函數(shù)成功后,應檢查 *br 以檢測文件的末尾。 如果 *br < btr,則表示在讀取操作期間讀/寫指針命中文件。

24.4.6.軟件設計

與FatFs文件系統(tǒng)使用相關的變量定義如下:

代碼清單: 24_8 hal_entry.c:全局變量

FATFS fs;           /* FatFs文件系統(tǒng)對象 */
FIL fnew;           /* 文件對象 */
UINT fnum;          /* 文件成功讀寫數(shù)量 */
FRESULT res_flash;  /* 文件操作結果 */
BYTE  fileReadBuffer[1024]; /* 讀緩沖區(qū) */
BYTE  fileWriteBuffer[] =   /* 寫緩沖區(qū) */
      "感謝您選用野火啟明瑞薩RA開發(fā)板 [FatFs讀寫測試文件.txt]";

BYTE work[FF_MAX_SS]; /* Work area (larger is better for processing time) */

FATFS是在ff.h文件定義的一個結構體類型,針對的對象是物理設備,包含了物理設備的物理編號、扇區(qū)大小等等信息, 一般我們都需要為每個物理設備定義一個FATFS變量。

FIL也是在ff.h文件定義的一個結構體類型,針對的對象是文件系統(tǒng)內(nèi)具體的文件,包含了文件很多基本屬性,比如文件大小、 路徑、當前讀寫地址等等。如果需要在同一時間打開多個文件進行讀寫,才需要定義多個FIL變量,不然一般定義一個FIL變量即可。

FRESULT是也在ff.h文件定義的一個枚舉類型,作為FatFs函數(shù)的返回值類型,主要管理FatFs運行中出現(xiàn)的錯誤。 總共有19種錯誤類型,包括物理設備讀寫錯誤、找不到文件、沒有掛載工作空間等等錯誤。這在實際編程中非常重要, 當有錯誤出現(xiàn)是我們要停止文件讀寫,通過返回值我們可以快速定位到錯誤發(fā)生的可能地點。如果運行沒有錯誤才返回FR_OK。

fnum是個32位無符號整形變量,用來記錄實際讀取或者寫入數(shù)據(jù)的數(shù)組。

fileReadBuffer和fileWriteBuffer分別對應讀取和寫入數(shù)據(jù)緩存區(qū),都是8位無符號整形數(shù)組。

hal_entry 入口函數(shù)

代碼清單: 24_9 hal_entry 入口函數(shù)

/* 用戶頭文件包含 */
#include "led/bsp_led.h"
#include "debug_uart/bsp_debug_uart.h"

//FatFs
#include "FatFs/ff15/ff.h"


FATFS fs;           /* FatFs文件系統(tǒng)對象 */
FIL fnew;           /* 文件對象 */
UINT fnum;          /* 文件成功讀寫數(shù)量 */
FRESULT res_flash;  /* 文件操作結果 */
BYTE  fileReadBuffer[1024]; /* 讀緩沖區(qū) */
BYTE  fileWriteBuffer[] =   /* 寫緩沖區(qū) */
      "感謝您選用野火啟明瑞薩RA開發(fā)板 [FatFs讀寫測試文件.txt]";

BYTE work[FF_MAX_SS]; /* Work area (larger is better for processing time) */


void hal_entry(void)
{
   /* TODO: add your own code here */

   LED_Init();         // LED 初始化
   Debug_UART4_Init(); // SCI4 UART 調(diào)試串口初始化

   printf("這是一個串行FLASH的FatFs使用演示例程\r\n");
   printf("打開串口助手查看打印的信息\r\n\r\n");

   /* 嘗試掛載外部FLASH FAT文件系統(tǒng) */
   res_flash = f_mount(&fs, "0:", 1);
   if (res_flash == FR_NO_FILESYSTEM)
   {
      printf(">>> FLASH還沒有文件系統(tǒng),即將進行格式化...\r\n");
      /* 格式化 */
      res_flash = f_mkfs("0:", NULL, work, sizeof(work));
      if (res_flash == FR_OK)
      {
            printf(">>> FLASH已成功格式化文件系統(tǒng)。\r\n");
            /* 格式化后,先取消掛載 */
            res_flash = f_mount(NULL,"0:",1);
            /* 重新掛載 */
            res_flash = f_mount(&fs,"0:",1);
      }
      else
      {
            printf(">>> 格式化失敗!!\r\n");
            while (1);
      }
   }
   else if (res_flash == FR_OK)
   {
      printf(">>> 文件系統(tǒng)掛載成功,可以進行讀寫測試。\r\n");
   }
   else
   {
      printf("!!外部Flash掛載文件系統(tǒng)失敗。(%d)\r\n", res_flash);
      printf("!!可能原因:Flash初始化不成功。\r\n");
      while (1);
   }


   /*----------------------- 文件系統(tǒng)測試:寫測試 -----------------------------*/
   printf("\r\n****** 即將進行文件寫入測試 ******\r\n");

   /* 打開文件,如果文件不存在則創(chuàng)建它 */
   res_flash = f_open(&fnew, "0:FatFs讀寫測試文件.txt", FA_CREATE_ALWAYS | FA_WRITE);
   if ( res_flash == FR_OK )
   {
      printf(">>> 打開/創(chuàng)建“FatFs讀寫測試文件.txt”文件成功,向文件寫入數(shù)據(jù)。\r\n");
      /* 將指定存儲區(qū)內(nèi)容寫入到文件內(nèi) */
      res_flash = f_write(&fnew, fileWriteBuffer, sizeof(fileWriteBuffer), &fnum);
      if (res_flash==FR_OK) {
            printf(">>> 文件寫入成功,寫入字節(jié)數(shù)據(jù):%d\r\n", fnum);
            printf(">>> 向文件寫入的數(shù)據(jù)為:%s\r\n", fileWriteBuffer);
      } else {
            printf("!!文件寫入失敗:(%d)\n",res_flash);
      }
      /* 不再讀寫,關閉文件 */
      f_close(&fnew);
   }
   else
   {
      printf("!!打開/創(chuàng)建文件失敗。\r\n");
   }


   /*----------------------- 文件系統(tǒng)測試:讀測試 -----------------------------*/
   printf("****** 即將進行文件讀取測試 ******\r\n");

   /* 打開文件,該文件前面已創(chuàng)建 */
   res_flash = f_open(&fnew, "0:FatFs讀寫測試文件.txt", FA_OPEN_EXISTING | FA_READ);
   if (res_flash == FR_OK)
   {
      printf(">>> 打開文件成功。\r\n");
      res_flash = f_read(&fnew, fileReadBuffer, sizeof(fileReadBuffer), &fnum);
      if (res_flash==FR_OK) {
            printf(">>> 文件讀取成功,讀到字節(jié)數(shù)據(jù):%d\r\n", fnum);
            printf(">>> 讀取得的文件數(shù)據(jù)為:%s\r\n", fileReadBuffer);
      } else {
            printf("!!文件讀取失敗:(%d)\n",res_flash);
      }
      /* 不再讀寫,關閉文件 */
      f_close(&fnew);
   }
   else
   {
      printf("!!打開文件失敗。\r\n");
   }

   /* 不再使用文件系統(tǒng),取消掛載文件系統(tǒng) */
   f_mount(NULL,"0:",1);

   printf("****** 測試結束 ******\r\n");
   while(1);


#if BSP_TZ_SECURE_BUILD
   /* Enter non-secure code */
   R_BSP_NonSecureEnter();
#endif
}

程序的開頭首先初始化調(diào)試串口,用來打印程序運行的一些調(diào)試信息。 此處的代碼是以啟明6M5板子的為例,另外兩塊板子的串口初始化函數(shù)名可能不同,讀者需要注意。

FatFs 使用的第一步工作就是使用 f_mount 函數(shù)掛載文件系統(tǒng)。 f_mount函數(shù)有三個形參,第一個參數(shù)是指向FATFS變量指針,如果賦值為NULL可以取消物理設備掛載。 第二個參數(shù)為邏輯設備編號,使用設備根路徑表示,與物理設備編號掛鉤, 在 diskio.h 中我們定義外部FLASH存儲器的物理編號為0,所以這里使用“0:”。 第三個參數(shù)可選0或1,1表示立即掛載,0表示不立即掛載,延遲掛載。 f_mount函數(shù)會返回一個 FRESULT 類型的值,指示掛載結果的情況。

如果 f_mount 函數(shù)返回值為 FR_NO_FILESYSTEM,說明外部FLASH存儲器還沒有FAT文件系統(tǒng)。 我們就必須對外部FLASH存儲器進行格式化處理,將里面的存儲空間以FAT文件系統(tǒng)的格式進行格式化。 使用 f_mkfs 函數(shù)可以實現(xiàn)格式化操作。 f_mkfs 函數(shù)有三個形參,第一個參數(shù)為邏輯設備編號; 第二個參數(shù)為格式化選項,選擇格式化的類型,比如:FAT16/FAT32/exFAT等,NULL表示使用默認選項進行格式化; 第三個參數(shù)指定工作緩存區(qū);第四個參數(shù)提供工作緩存區(qū)的大小。 格式化成功后需要先取消掛載原來設備,再重新掛載設備。

在設備正常掛載后,就可以進行文件讀寫操作了。使用文件之前,必須使用f_open函數(shù)打開文件,不再使用文件時必須使用f_close函數(shù)關閉文件, 這個跟電腦端操作文件步驟類似。f_open函數(shù)有三個形參,第一個參數(shù)為文件對象指針。第二參數(shù)為目標文件,包含絕對路徑的文件名稱和后綴名。 第三個參數(shù)為訪問文件模式選擇,可以是打開已經(jīng)存在的文件模式、讀模式、寫模式、新建模式、總是新建模式等的或運行結果。比如對于寫測試, 使用FA_CREATE_ALWAYS和FA_WRITE組合模式,就是總是新建文件并進行寫模式。

f_close函數(shù)用于不再對文件進行讀寫操作關閉文件,f_close函數(shù)只要一個形參,為文件對象指針。f_close函數(shù)運行可以確保緩沖區(qū)完全寫入到文件內(nèi)。

成功打開文件之后就可以使用f_write函數(shù)和f_read函數(shù)對文件進行寫操作和讀操作。這兩個函數(shù)用到的參數(shù)是一致的,只不過一個是數(shù)據(jù)寫入,一個是數(shù)據(jù)讀取。 f_write函數(shù)第一個形參為文件對象指針,使用與f_open函數(shù)一致即可。第二個參數(shù)為待寫入數(shù)據(jù)的首地址,對于f_read函數(shù)就是用來存放讀出數(shù)據(jù)的首地址。 第三個參數(shù)為寫入數(shù)據(jù)的字節(jié)數(shù),對于f_read函數(shù)就是欲讀取數(shù)據(jù)的字節(jié)數(shù)。第四個參數(shù)為32位無符號整形指針,這里使用fnum變量地址賦值給它, 在運行讀寫操作函數(shù)后,fnum變量指示成功讀取或者寫入的字節(jié)個數(shù)。之后 我們通過相應函數(shù)的返回值賦值到res_flash,后進行判斷當前程序是否運行成功我們點亮綠燈和藍燈,如果其中有一個失敗我們點亮紅燈。

最后,不再使用文件系統(tǒng)時,使用f_mount函數(shù)取消掛載。

24.4.7.實驗驗證

用USB線連接開發(fā)板“USB TO UART”接口跟電腦,在電腦端打開串口調(diào)試助手, 把編譯好的程序下載到開發(fā)板。在串口調(diào)試助手可看到FatFs測試的調(diào)試信息。

wKgZO2m6P7qANuRjAAGPfere4wY491.png

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • FlaSh
    +關注

    關注

    10

    文章

    1752

    瀏覽量

    155633
  • 瑞薩
    +關注

    關注

    37

    文章

    22491

    瀏覽量

    90952
  • 文件系統(tǒng)

    關注

    0

    文章

    304

    瀏覽量

    20996
  • FATFS
    +關注

    關注

    0

    文章

    46

    瀏覽量

    19553

原文標題:FatFs的官網(wǎng)源碼結構及已知問題以及解決方法或補丁——瑞薩RA系列FSP庫開發(fā)實戰(zhàn)指南(87)

文章出處:【微信號:瑞薩嵌入式小百科,微信公眾號:瑞薩嵌入式小百科】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    RA系列FSP開發(fā)實戰(zhàn)指南I2C讀寫EEPROM實驗

    使用官方提供的FPS進行編程,官方提供的FPS具有方便、快捷、簡潔的特性。
    的頭像 發(fā)表于 01-27 10:02 ?3492次閱讀
    <b class='flag-5'>瑞</b><b class='flag-5'>薩</b><b class='flag-5'>RA</b><b class='flag-5'>系列</b><b class='flag-5'>FSP</b><b class='flag-5'>庫</b><b class='flag-5'>開發(fā)</b><b class='flag-5'>實戰(zhàn)</b><b class='flag-5'>指南</b><b class='flag-5'>之</b>I2C讀寫EEPROM<b class='flag-5'>實驗</b>

    RA系列FSP開發(fā)實戰(zhàn)指南FatFs文件系統(tǒng)介紹

    即使讀者可能不了解文件系統(tǒng),讀者也一定對“文件”這個概念十分熟悉。數(shù)據(jù)在PC上是以文件的形式儲存在磁盤中的,這些數(shù)據(jù)的形式一般為ASCII 碼或二進制形式。
    的頭像 發(fā)表于 03-18 13:47 ?198次閱讀
    <b class='flag-5'>瑞</b><b class='flag-5'>薩</b><b class='flag-5'>RA</b><b class='flag-5'>系列</b><b class='flag-5'>FSP</b><b class='flag-5'>庫</b><b class='flag-5'>開發(fā)</b><b class='flag-5'>實戰(zhàn)</b><b class='flag-5'>指南</b><b class='flag-5'>之</b><b class='flag-5'>FatFs</b><b class='flag-5'>文件系統(tǒng)</b>介紹

    e2studio(1)----芯片搭建FSP環(huán)境

    視頻教學 樣品申請 請勿添加外鏈 e2studio軟件 e2studio是的集成開發(fā)環(huán)境,FSP 提供了眾多可提高效率的工具,用于開發(fā)
    發(fā)表于 09-30 15:28

    怎樣移植FATFS文件到工程文件

    FATFS移植是否成功八、說明&完整工程下載一、前言二、硬件及軟件準備1、硬件:STM32系列單片機2、軟件:Keil5、FATFS文件系統(tǒng)
    發(fā)表于 07-13 06:12

    介紹移植fatfs文件系統(tǒng)步驟

    就可以派上用場,fatfs是一小型的可裁剪免費文件系統(tǒng)移植起來比較方便,移植文件系統(tǒng)大大縮短開發(fā)
    發(fā)表于 11-23 07:19

    FATFS文件系統(tǒng)移植的相關資料推薦

    FATFS文件系統(tǒng)移植(FLASH)一、說明1、在移植文件系統(tǒng)前需先驗證
    發(fā)表于 01-11 06:57

    如何在spi_flash移植建立fatfs文件系統(tǒng)

    文章目錄基于stm32f103系列MCU,在spi_flash移植建立fatfs文件系統(tǒng)移植
    發(fā)表于 02-14 06:38

    RA4系列開發(fā)板體驗】開發(fā)環(huán)境搭建和新手點燈指南

    RA4系列開發(fā)板體驗】開發(fā)環(huán)境搭建和新手點燈指南
    發(fā)表于 11-24 22:54

    RA4系列開發(fā)板體驗】體驗過程

    拿到板子之后,做了幾個實驗過程,過程如下:1、在好奇心驅動下,逐步接觸;參照網(wǎng)上的實例,學習開發(fā)環(huán)境一、開箱驗貨二、搭建環(huán)境參考“ 【
    發(fā)表于 12-18 16:20

    【野火啟明6M5開發(fā)板體驗】開箱+認識開發(fā)板+資料

    按鍵檢測29. WiFi——模塊通訊板尺寸:3、資料:*附件:[野火EmbedFire]《RA系列FSP
    發(fā)表于 12-20 23:28

    FatFs文件系統(tǒng)使用

    STM系列FatFs文件系統(tǒng)使用文件,希望對大家有幫助。
    發(fā)表于 11-06 18:10 ?10次下載

    Fatfs文件系統(tǒng)移植

    Fatfs文件系統(tǒng)移植)一、文件系統(tǒng)介紹二、移植條件、說明1、FatFs模塊在可
    發(fā)表于 11-15 18:51 ?22次下載
    <b class='flag-5'>Fatfs</b>(<b class='flag-5'>文件系統(tǒng)</b>的<b class='flag-5'>移植</b>)

    文件系統(tǒng)FatFs文件系統(tǒng)在嵌入式芯片LPC18XX上的移植

    文件系統(tǒng)FatFs文件系統(tǒng)在嵌入式芯片LPC18XX上的移植
    發(fā)表于 12-04 10:51 ?12次下載
    【<b class='flag-5'>文件系統(tǒng)</b>】<b class='flag-5'>FatFs</b><b class='flag-5'>文件系統(tǒng)</b>在嵌入式芯片LPC18XX上的<b class='flag-5'>移植</b>

    手把手教你在flash移植fatfs文件系統(tǒng)(含實時操作系統(tǒng))

    文章目錄基于stm32f103系列MCU,在spi_flash移植建立fatfs文件系統(tǒng)移植
    發(fā)表于 12-09 12:51 ?30次下載
    手把手教你在<b class='flag-5'>flash</b>上<b class='flag-5'>移植</b><b class='flag-5'>fatfs</b><b class='flag-5'>文件系統(tǒng)</b>(含實時操作<b class='flag-5'>系統(tǒng)</b>)

    【有獎直播預報名】電子RA系列產(chǎn)品開發(fā)工具FSP4.0.0新特性介紹

    為使用電子RA系列ARM微控制器的嵌入式系統(tǒng)設計提供簡單易用且可擴展的高質(zhì)量軟件。 直播主題
    的頭像 發(fā)表于 11-22 12:20 ?1552次閱讀