乐于分享
好东西不私藏

基本函数及说明和实验验证——瑞萨RA系列FSP库开发实战指南(90)

基本函数及说明和实验验证——瑞萨RA系列FSP库开发实战指南(90)

24.4.5.3

f_setlabel

f_setlabel函数原型如下:

左右滑动查看完整内容

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

当字符串具有驱动器前缀时,卷标将设置为驱动器前缀指定的卷。Unix样式的卷ID不能用于指定卷。如果未指定驱动器号,则卷标将设置为默认驱动器。如果给定卷标的长度为零,则将删除卷上的卷标。

卷标的格式如下所示:

在FAT卷上转换OEM代码页时最多11个字节。在exFAT卷中最多11个字符。FAT卷允许的字符数为:SFN允许的字符不包括点。低写字符向上转换。exFAT卷允许的字符为:LFN允许的字符包括点。将保留小写字符。空格可以嵌入卷标中的任何位置。尾随空格在FAT音量处被截断。

当FF_FS_READONLY==0且FF_USE_LABEL==1时可用。

24.4.5.4

f_open

f_open函数原型如下:

左右滑动查看完整内容

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

打开一个文件并创建一个文件对象。完成对文件的访问后应该使用f_close函数将其关闭。如果在关机、移出介质或重新装入之前对文件进行了任何更改且未调用f_close函数将其关闭,则文件可能会collapsed(损坏)。

可选mode选项:

当FF_FS_READONLY==1时,只有FA_READ和FA_OPEN_EXISTING可用于模式标志。

24.4.5.5

f_close

f_close函数原型如下:

左右滑动查看完整内容

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

关闭打开的文件对象。如果文件已更改,则文件的缓存信息将写回卷。函数成功后,文件对象不再有效,可以丢弃。

请注意,如果文件对象处于只读模式且未启用FF_FS_LOCK,则也可以在不执行f_close函数的情况下丢弃该文件对象。但是,不建议这样做。

24.4.5.6

f_write

f_write函数原型如下:

左右滑动查看完整内容

FRESULT f_write(FIL* fp, /* [IN] Pointer to the file object structure */constvoid* 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 */);

该函数开始在读/写指针指向的文件偏移处将数据写入文件。读/写指针随着写入的字节数而前进。功能成功后,应检查*bw以检测磁盘已满。如果*bw<btw,则表示卷在写入操作期间已满。该函数在卷已满或接近满时可能需要一段时间。

FF_FS_READONLY==0时可用。

24.4.5.7

f_read

f_read函数原型如下:

左右滑动查看完整内容

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 */);

该函数开始在读/写指针指向的文件偏移处从文件中读取数据。读/写指针随着读取的字节数而前进。函数成功后,应检查*br以检测文件的末尾。如果*br<btr,则表示在读取操作期间读/写指针命中文件。

24.4.6

软件设计

与FatFs文件系统使用相关的变量定义如下:

列表11:

代码清单:24_8 hal_entry.c:全局变量

左右滑动查看完整内容

FATFS fs; /* FatFs 文件系统对象*/FIL fnew; /* 文件对象*/UINT fnum; /* 文件成功读写数量*/FRESULT res_flash; /* 文件操作结果*/BYTE fileReadBuffer[1024]; /* 读缓冲区*/BYTE fileWriteBuffer[] = /* 写缓冲区*/"感谢您选用野火启明瑞萨RA 开发板[FatFs 读写测试文件.txt]";

存储设备初始化函数

列表12:代码清单:24_3 disk_ioctl函数

左右滑动查看完整内容

FATFS fs; /* FatFs 文件系统对象*/FIL fnew; /* 文件对象*/UINT fnum; /* 文件成功读写数量*/FRESULT res_flash; /* 文件操作结果*/BYTE fileReadBuffer[1024]; /* 读缓冲区*/BYTE fileWriteBuffer[] = /* 写缓冲区*/"感谢您选用瑞萨RA开发板[FatFs 读写测试文件.txt]";BYTE work[FF_MAX_SS]; /* Work area (larger is better for processing time) */
  • FATFS是在ff.h文件定义的一个结构体类型,针对的对象是物理设备,包含了物理设备的物理编号、扇区大小等等信息,一般我们都需要为每个物理设备定义一个FATFS变量。

  • FIL也是在ff.h文件定义的一个结构体类型,针对的对象是文件系统内具体的文件,包含了文件很多基本属性,比如文件大小、路径、当前读写地址等等。如果需要在同一时间打开多个文件进行读写,才需要定义多个FIL变量,不然一般定义一个FIL变量即可。

  • FRESULT是也在ff.h文件定义的一个枚举类型,作为FatFs函数的返回值类型,主要管理FatFs运行中出现的错误。总共有19种错误类型,包括物理设备读写错误、找不到文件、没有挂载工作空间等等错误。这在实际编程中非常重要,当有错误出现时我们要停止文件读写,通过返回值我们可以快速定位到错误发生的可能地点。如果运行没有错误才返回FR_OK。

  • fnum是个32位无符号整形变量,用来记录实际读取或者写入数据的数组。

  • fileReadBuffer和fileWriteBuffer分别对应读取和写入数据缓存区,都是8位无符号整数数组。

hal_entry入口函数

列表12:代码清单:24_9 hal_entry入口函数

左右滑动查看完整内容

/* 用户头文件包含*/#include"led/bsp_led.h"#include"debug_uart/bsp_debug_uart.h"//FatFs#include"FatFs/ff15/ff.h"FATFS fs; /* FatFs 文件系统对象*/FIL fnew; /* 文件对象*/UINT fnum; /* 文件成功读写数量*/FRESULT res_flash; /* 文件操作结果*/BYTE fileReadBuffer[1024]; /* 读缓冲区*/BYTE fileWriteBuffer[] = /* 写缓冲区*/"感谢您选用瑞萨RA开发板[FatFs 读写测试文件.txt]";BYTE work[FF_MAX_SS]; /* Work area (larger is better for processing time) */voidhal_entry(void){/* TODO: add your own code here */LED_Init(); // LED 初始化Debug_UART4_Init(); // SCI4 UART 调试串口初始化printf("这是一个串行FLASH 的FatFs 使用演示例程\r\n");printf("打开串口助手查看打印的信息\r\n\r\n");/* 尝试挂载外部FLASH FAT 文件系统*/res_flash = f_mount(&fs, "0:"1);if (res_flash == FR_NO_FILESYSTEM){printf(">>> FLASH 还没有文件系统,即将进行格式化...\r\n");/* 格式化*/res_flash = f_mkfs("0:"NULL, work, sizeof(work));if (res_flash == FR_OK){printf(">>> FLASH 已成功格式化文件系统。\r\n");/* 格式化后,先取消挂载*/res_flash = f_mount(NULL,"0:",1);/* 重新挂载*/res_flash = f_mount(&fs,"0:",1);}else{printf(">>> 格式化失败!!\r\n");while (1);}}elseif (res_flash == FR_OK){printf(">>> 文件系统挂载成功,可以进行读写测试。\r\n");}else{printf("!!外部Flash 挂载文件系统失败。(%d)\r\n", res_flash);printf("!!可能原因:Flash 初始化不成功。\r\n");while (1);}/*----------------------- 文件系统测试:写测试-----------------------------,→*/printf("\r\n****** 即将进行文件写入测试******\r\n");/* 打开文件,如果文件不存在则创建它*/res_flash = f_open(&fnew, "0:FatFs 读写测试文件.txt"FA_CREATE_ALWAYS |,FA_WRITE);if ( res_flash == FR_OK ){printf(">>> 打开/创建“FatFs 读写测试文件.txt”文件成功,向文件写入数据。\r\n,→");/* 将指定存储区内容写入到文件内*/res_flash = f_write(&fnew, fileWriteBuffer, sizeof(fileWriteBuffer), &if (res_flash==FR_OK) {printf(">>> 文件写入成功,写入字节数据:%d\r\n", fnum);printf(">>> 向文件写入的数据为:%s\r\n", fileWriteBuffer);else {printf("!!文件写入失败:(%d)\n",res_flash);}/* 不再读写,关闭文件*/f_close(&fnew);}else{printf("!!打开/创建文件失败。\r\n");}/*----------------------- 文件系统测试:读测试-----------------------------,→*/printf("****** 即将进行文件读取测试******\r\n");/* 打开文件,该文件前面已创建*/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(">>> 文件读取成功,读到字节数据:%d\r\n", fnum);printf(">>> 读取得的文件数据为:%s\r\n", fileReadBuffer);else {printf("!!文件读取失败:(%d)\n",res_flash);}/* 不再读写,关闭文件*/f_close(&fnew);}else{printf("!!打开文件失败。\r\n");}/* 不再使用文件系统,取消挂载文件系统*/f_mount(NULL,"0:",1);printf("****** 测试结束******\r\n");while(1);#if BSP_TZ_SECURE_BUILD/* Enter non-secure code */R_BSP_NonSecureEnter();#endif}

程序的开头首先初始化调试串口,用来打印程序运行的一些调试信息。此处的代码是以启明6M5开发板的为例,另外两块板子的串口初始化函数名可能不同,读者需要注意。

FatFs使用的第一步工作就是使用f_mount函数挂载文件系统。f_mount函数有三个形参:

  • 第一个参数是指向FATFS变量指针,如果赋值为NULL可以取消物理设备挂载。

  • 第二个参数为逻辑设备编号,使用设备根路径表示,与物理设备编号挂钩,在diskio.h中我们定义外部FLASH存储器的物理编号为0,所以这里使用“0:”。

  • 第三个参数可选0或1,1表示立即挂载,0表示不立即挂载,延迟挂载。f_mount函数会返回一个FRESULT类型的值,指示挂载结果的情况。

如果f_mount函数返回值为FR_NO_FILESYSTEM,说明外部FLASH存储器还没有FAT文件系统。我们就必须对外部FLASH存储器进行格式化处理,将里面的存储空间以FAT文件系统的格式进行格式化。使用f_mkfs函数可以实现格式化操作。f_mkfs函数有三个形参:

  • 第一个参数为逻辑设备编号;

  • 第二个参数为格式化选项,选择格式化的类型,比如:FAT16/FAT32/exFAT等,NULL表示使用默认选项进行格式化;

  • 第三个参数指定工作缓存区;

  • 第四个参数提供工作缓存区的大小。

格式化成功后需要先取消挂载原来设备,再重新挂载设备。

在设备正常挂载后,就可以进行文件读写操作了。使用文件之前,必须使用f_open函数打开文件,不再使用文件时必须使用f_close函数关闭文件,这个跟电脑端操作文件步骤类似。f_open函数有三个形参:

  • 第一个参数为文件对象指针。

  • 第二参数为目标文件,包含绝对路径的文件名称和后缀名。

  • 第三个参数为访问文件模式选择,可以是打开已经存在的文件模式、读模式、写模式、新建模式、总是新建模式等的或运行结果。比如对于写测试,使用FA_CREATE_ALWAYS和FA_WRITE组合模式,就是总是新建文件并进行写模式。

f_close函数用于不再对文件进行读写操作关闭文件,f_close函数只要一个形参,为文件对象指针。f_close函数运行可以确保缓冲区完全写入到文件内。

成功打开文件之后就可以使用f_write函数和f_read函数对文件进行写操作和读操作。这两个函数用到的参数是一致的,只不过一个是数据写入,一个是数据读取。

  • f_write函数第一个形参为文件对象指针,使用与f_open函数一致即可。

  • 第二个参数为待写入数据的首地址,对于f_read函数就是用来存放读出数据的首地址。

  • 第三个参数为写入数据的字节数,对于f_read函数就是欲读取数据的字节数。

  • 第四个参数为32位无符号整形指针,这里使用fnum变量地址赋值给它,在运行读写操作函数后,fnum变量指示成功读取或者写入的字节个数。之后我们通过相应函数的返回值赋值到res_flash,后进行判断当前程序是否运行成功我们点亮绿灯和蓝灯,如果其中有一个失败我们点亮红灯。

最后,不再使用文件系统时,使用f_mount函数取消挂载。

24.4.7

实验验证

用USB线连接开发板“USB TO UART”接口跟电脑,在电脑端打开串口调试助手,把编译好的程序下载到开发板。在串口调试助手可看到FatFs测试的调试信息。

需要技术支持?

如您在使用瑞萨MCU/MPU产品中有任何问题,可识别下方二维码或复制网址到浏览器中打开,进入瑞萨MCU/MPU官方技术论坛寻找答案或获取在线技术支持。

https://bbs.21ic.com/renesas

未完待续

推荐阅读

FatFs的官网源码结构及已知问题以及解决方法或补丁——瑞萨RA系列FSP库开发实战指南(87)

FatFs路径名格式说明——瑞萨RA系列FSP库开发实战指南(88)

FatFs文件系统与存储设备的连接函数及基本API函数说明——瑞萨RA系列FSP库开发实战指南(89)