stm32cube+fatfs+spi_flash(W25Q128)

在大型的存储器中,没有文件系统是万万不可行的,你不可能每次要打开一个文件都要从头到尾扫描一遍存储器,几兆的小存储器还好,几G甚至几T的存储器就根本没办法这么做了。而且有了文件系统也可以方便的管理使用各类文件。

这一次使用Cubemx生成FatFs的初始化代码,然后做最后的移植工作。本人使用的是stm32f767的野火的板子。

介绍一下FafFs

系统架构

FatFs是一种中间层,可以屏蔽硬件的差异,移植起来非常方便

移植需要注意的地方

你需要提供FatFs需要的底层I/O函数,需要的函数如下表,但是并不是全部函数都需要,你只需要提供必需的disk_status disk_initialize disk_read 和你需要的就可以。

开始移植

配置Cubemx

因为我准备的是W25Q128上的FatFs,CubeMX上面没有,所以要选择user-defined

接下来是在Configuration里面配置FatFs,因为需要读取的文件是中文的,所以要配置为中文,然后为以后可能还有别的存储器预留空位,所以配置VOLUMES为3

还有就是在project setting里面把stack设置的大点

此外就是W25Q128的基本配置,这些就不提供了,网上有,可以参考微雪课堂里的配置。

接下来就是生成代码了

补完底层I/O函数

打开user_disko.c这个文件,可以看到CubeMX自动生成的函数原型。由于我需要读写磁盘,所以我需要补全这些所有的函数USER_initialize USER_status USER_read USER_write USER_ioctl

遇到问题和解决问题

f_mount返回FR_DISK_ERR

这个问题困扰了我好几个小时,我从f_mount->get_ldnumber用printf找了差不多1个小时的BUG,发现找不到问题,突然间发现我f_mount还调用了一个函数find_volume,而且就算这里出现了问题,就换方向一路追踪find_volume->check_fs->move_window->disk_read,发现是disk_read返回的错误,看到这我就傻眼了,觉得不可能啊,因为我之前读取写入flash都是没有问题的。

第二天脑袋比较清醒了,首先先测试初始化是否成功,在读取成功flash id后确定了初始化成功。

然后再来看看disk_read,它使用的是我提供的一个全局的disk io驱动来读取disk,结构体类型如下

typedef struct

{

 uint8_t                 is_initialized[_VOLUMES];

 const Diskio_drvTypeDef *drv[_VOLUMES];

 uint8_t                 lun[_VOLUMES];

 volatile uint8_t        nbr;

}Disk_drvTypeDef;

所以我回到了userdiskio.c查看我的USERread函数

DRESULT USER_read (

   BYTE pdrv,      /* Physical drive nmuber to identify the drive */

   BYTE *buff,     /* Data buffer to store read data */

   DWORD sector,   /* Sector address in LBA */

   UINT count      /* Number of sectors to read */

)

{

 /* USER CODE BEGIN READ */

 FLASH_DEBUG_FUNC();

 DRESULT res = RES_ERROR;

   if ((Stat & STA_NOINIT))

   {

       res = RES_NOTRDY;

   }

 else

 {

   sector+=1536;//扇区偏移,外部Flash文件系统空间放在外部Flash后面6M空间

   res = BSP_QSPI_Read(buff, sector <<12, count<<12);

 }

   return res;  

 /* USER CODE END READ */

}

我在USER_read的else括号中加了一个printf,结果发现调用f_mount时,居然没有进入这个else语句,然后我开始怀疑这个Stat有问题,所以我把if的条件去掉了,直接执行sector+=1536;res = BSP_QSPI_Read(buff, sector <<12, count<<12);这条语句,发现FatFs挂载成功。

很激动,原来问题在于Stat的状态没有更新,因为Stat一开始定义的时候是定义为STA_NOINIT

/* Disk status */

static volatile DSTATUS Stat = STA_NOINIT;

接下来就是查找disk的状态没有更新的原因。回到一开始找到返回错误信息的函数find_volume,它的执行过程相当于get_ldnumber->disk_initialize->check_fs...一开始就是到了check_fs这一步的时候报错,停止程序的,我们可以发现,这个过程并没有调用到用户定义的USER_status或FatFs定义的disk_status来检查disk的状态更新。

所以我在初始化中加入了检查disk的状态的代码

DSTATUS USER_initialize (

   BYTE pdrv           /* Physical drive nmuber to identify the drive */

)

{

 /* USER CODE BEGIN INIT */

 Stat = USER_status(pdrv);

 return BSP_QSPI_Init(); /* Flash的初始化 */

 /* USER CODE END INIT */

}

效果很好,disk的状态更新成功,f_mount挂载正常。

f_open返回FR_INVALID_NAME

好不容易挂载成功了,但是读写还是失败,第一反应是可能在编码上出错了,因为我的工程没有包括cc936.c这个文件,而野火官方的工程却包括了,我怀疑是不是这一点导致无法读取中文,从而FR_INVALID_NAME。

但是我现在还不知道FatFs是怎么调用cc936.c这个文件的,只能先从f_open跟踪进去看看。

f_open->follow_path,打LOG发现是follow_path中的create_name返回的FR_INVALID_NAME

进入create_name找到返回FR_INVALID_NAME的语句

...

mem_set(sfn, ' ', 11);

...

for (;;;) {

   ...

   if (c == '.' || i >= ni) {        /* End of body or over size? */

           if (ni == 11 || c != '.') return FR_INVALID_NAME;   /* Over size or invalid dot */

           i = 8; ni = 11;             /* Goto extension */

           continue;

   }

   ...

}

由于对于文件名一开始只分配了11个空间,但是我的文件名却超过了11个空间,所以导致了这个问题,在我将我的文件名减少后,问题解决。

文件名长度才11有点短,但是可以通过修改支持长文件名来支持。

在支持长文件名后,读写长文件名没有问题了

可以改进的地方

本工程没有加入RTC的支持,所以没有去实现get_fattime,因此不支持多磁盘,想支持多磁盘需要实现get_fattime

本工程已上传github

https://github.com/greedyhao/stm32

———— / END / ————

 

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,需要明确的是,STM32和W25Q64是完全不同的产品,它们分别是微控制器和闪存存储器。而FATFS是一个用于嵌入式系统的文件系统。因此,题目中的"STM32 W25Q64 FATFS速度慢"可能涉及到两个方面的问题,即STM32的操作速度与W25Q64芯片的读写速度,以及FATFS文件系统的读写性能。以下我将就这两个方面进行回答。 首先,STM32的速度问题可能与控制器的硬件和软件设计有关。可能是使用了低速的系统时钟频率或者是编写的代码存在效率上的问题。解决这个问题的方法是重新评估系统的时钟配置,以获得更高的处理速度,并且可以通过优化代码来提高程序的执行效率。 其次,W25Q64芯片的读写速度取决于其本身的性能和连接方式。要确保读写速度最大化,首先要确保正确选择了合适的SPI总线时钟,并进行合适的SPI通信设置。其次,在读写数据时需要考虑到W25Q64芯片的数据传输速率以及是否使用了缓存等功能。最后,检查硬件电路的设计与布线是否符合要求,并根据需要进行优化。 最后,FATFS文件系统的读写性能可能与文件系统的配置有关。在初始化FATFS时,需要选择合适的参数来优化文件系统的性能。例如,可以选择合适的簇大小和对齐方式,以减少磁盘片段和提高读写速度。此外,可以根据实际需求进行文件缓存的大小调整,以提高磁盘访问效率。 总结而言,如果STM32的速度慢、W25Q64芯片的读写速度慢或者FATFS的读写性能慢,需要综合考虑硬件和软件层面的因素,并根据具体问题进行适当的优化和调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值