从STM32Cube库向标准外设库移植FatFs文件系统 前言 在很多应用中,文件系统被用来在存储介质上进行存储和管理文件数据。FatFs 作为面向小型嵌入式系统的一种通用FAT 文件系统,被广泛使用。在STM32Cube 库中,Middleware 是包含有FatFs 文件系统的,而且有相关的例程。但是在标准外设库并没有相关的例程,这使得在使用标准外设库在开发项目中使用文件系统的话,需要自己再移植代码。其实,从STM32Cube 库向标准外设库移植FatFs 文件系统很方便,简单实用。下面我们以STM32F4 系列为例,来介绍一下SD 卡的移植。 STM32CubeF4库中的FatFs 大家都知道,进行FatFs 移植主要就是在diskio.c 中添加底层驱动代码。在STM32CubeF4 库中,可以在\STM32Cube_FW_F4_V1.11.0\Middlewares\Third_Party\FatFs\src 找到FatFs R0.11 的代码,细心的工程师会发现,里边的文件与从FatFs 下载的FatFs R0.11 不太一样,多了ff_gen_drv.c 和ff_gen_drv.h 两个文件,并且多了一个包含多种存储介质驱动的driver 文件夹。这是因为ST 的工程师在FatFs 的代码中,已经为大家添加了各种存储介质的驱动代码,以方便大家使用,并使用ff_gen_drv.c 来进行管理。所以,STM32CubeF4 的FatFs 中间件模块架构如下: 从架构图可知,在STM32CubeF4 解决方案中,已经添加额外的接口层,可以动态地添加/删除FatFs 模块的物理介质。如需以底层磁盘 I/O 驱动来连接 FatFs 模块,用户可以使用 FATFS_LinkDriver()和 FATFS_UnLinkDriver() 动态地添加或者删除磁盘 I/O 驱动;应用程序可能需要知道当前连接的磁盘 I/O 驱动数量,这一点可通过 FATFS_GetAttachedDriversNbr() API 来实现。这让我们在管理物理介质更为方便。这三个函数就位于ff_gen_drv.c 中。以SD 卡为例,原本的“diskio.c”分化为“diskio.c + ff_gen_drv.c + \drivers\sd_diskio.c”三个文件,虽然文件增加了,但是条理更加清晰。具体的介绍可以参考用户手册UM1721《在STM32Cube 上开发FatFs 相关应用》,这里不作详述。看完UM1721,接下来可以开始动手实现了。 一 实现环境 开发板: STM32439I-EVAL (MCU: STM32F439NIH6) 开发环境: STM32Cube_FW_F4_V1.11.0 STM32F4xx_DSP_StdPeriph_Lib_V1.6.1 IDE: IAR Embedded Workbench for ARM v7.50.1.10273 二 实现步骤 1.在标准外设库上建立项目文件,确保SD卡可正常工作 1) 在\STM32F4xx_DSP_StdPeriph_Lib_V1.6.1\Project 下复制STM32F4xx_StdPeriph_Templates 并将文件夹更名为FatFs_uSD 2) 将\STM32F4xx_DSP_StdPeriph_Lib_V1.6.1\Project\STM32F4xx_StdPeriph_Examples\SDIO\SDIO_uSDCard 下的文件复制到FatFs_uSD 替换掉原有文件 3) 打开EWARM 下面的项目文件,在项目文件中添加\Utilities\STM32_EVAL\STM324x9I_EVAL 文件组,并加入stm324x9i_eval.c、stm324x9i_eval_ioe16.c、stm324x9i_eval_sdio_sd.c,如图: 4) 在main.h 中将include 中的代码加入STM324x9I 的信息,更新为 5) 编译,成功。下载运行,可见LED1、LED2 和LED3 点亮,证明SD 卡读写正常。此步骤的目的在于首先要确保SDIO 读写SD 卡是正常的。 2.移植FatFs代码 1) 将\STM32Cube_FW_F4_V1.11.0\Middlewares\Third_Party\下的FatFs 文件夹复制到\STM32F4xx_DSP_StdPeriph_Lib_V1.6.1\Libraries 2) 打开之前的项目,在项目中添加FatFs 文件组,加入\drivers\sd_diskio.c、diskio.c、ff.c 和ff_gen_drv.c,如图: 3) 打开Project Options,在C/C++ Compiler 的Preprocessor 页面添加FatFs 使用的头文件的地址:$PROJ_DIR$\..\..\..\Libraries\FatFs\src 和$PROJ_DIR$\..\..\..\Libraries\FatFs\src\drivers,如下: 4) 复制\STM32Cube_FW_F4_V1.11.0\Projects\STM324x9I_EVAL\Applications\FatFs\FatFs_uSD\Inc 下的ffconf.h 到\STM32F4xx_DSP_StdPeriph_Lib_V1.6.1\Project\Fatfs_uSDcard 5) 修改ffconf.h,删掉第15 行的“#include "stm32f4xx_hal.h"”,将第18 行的“#include "stm324x9i_eval_sd.h"”改为“#include "stm324x9i_eval_sdio_sd.h"” 6) 修改sd_diskio.c,这是整个移植最关键的地方。 a. DSTATUS SD_initialize(BYTE lun) STM32CubeF4 中的BSP_SD_Init()对应于标准外设库的SD_Init(),MSD_OK 对应于SD_OK。此函数修改为: b. DSTATUS SD_status(BYTE lun) STM32CubeF4 中的BSP_SD_GetStatus ()对应于标准外设库的SD_GetStatus() ()。此函数修改为: c. DRESULT SD_read(BYTE lun, BYTE *buff, DWORD sector, UINT count) 在STM32CubeF4 中,BSP_SD_ReadBlocks()函数调用HAL_SD_ReadBlocks(),而HAL_SD_ReadBlocks()已经针对读取单个Block 和多个Block 进行了处理。而在标准外设库中没有这样的函数,单个Block 的读取使用SD_ReadBlock()函数,多个Block 的读取使用SD_ReadMultiBlocks()函数。所以,这个函数需要修改为: d. DRESULT SD_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count) SD_write()的修改和SD_read()一样,需要分别对单个Block 和多个Block 进行处理。函数修改为: e. DRESULT SD_ioctl(BYTE lun, BYTE cmd, void *buff) STM32CubeF4 中的BSP_SD_GetCardInfo()对应于标准外设库的SD_GetCardInfo()。此函数修改为: 至此,编译可通过,FatFs 的移植已算完成。接下来,是修改测试代码。 7) 修改main.c。参考\STM32Cube_FW_F4_V1.11.0\Projects\STM324x9I_EVAL\Applications\FatFs\FatFs_uSD\Src\main.c,修改此文件,如下: 还需要在main.h 中加入: 此主函数实现功能为:创建STM32STD.TXT 文件,并向其写入“STM32 with FatFs demo @ std lib” 8) 编译,成功。 3.测试 1) 连接STM32439I-EVAL 到PC 2) 打开工程,下载代码并运行,LED1 点亮,代表运行通过。 3) 将SD 卡从STM32439I-EVAL 取出,放入PC 进行读取,可见: 4) 打开STM32STD.TXT,可见: 5) 测试结果:成功。 结论 此文档介绍从STM32CubeF4 中将FatFs 文件系统移植到标准外设库的实现过程。另外,对于时间接口函数,有需要的读者可自行进行移植。 文档下载 更多实战经验 |