移植方法参见我的另一篇博客:《stm32--FatFs移植(SPIFlash)》。

本文仅记录在初次移植完成后,遇到的问题,和解决的过程。

调试记录:

  1. 问题1:f_open返回3,即磁盘没有准备好。

    • 原因:这是因为逻辑驱动器是按默认(0)初始化的,而在宏定义中把SPIFlash定义为了1。将SPIFlash定义为0即可。
  2. 问题2:开机是否格式化?如果不格式化,SPIFlash无法创建创建文件系统;又不可能每次开机都格式化。
    • 处理:f_getfree检测FAT卷空间,如果返回是FR_NO_FILESYSTEM,说明没有格式化过,进行格式化。
  3. 问题3:格式化失败(返回FR_DISK_ERR)【此时的BLOCK_SIZE参数是错误的】
    • 原因:diskio.c中底层写入函数入口判断错误,入口判断参数是否正常时 if(sector > SEC_MAX || sector + count > SEC_MAX) return RES_PARERR; 出错,第二个判断条件应为sector + count - 1而非sector + count。
  4. 问题4:只能格式化为FAT12格式。
    • 调试过程:仿真跟踪f_mkfs源代码:
    • 如果输入参数为FAT,函数中会减去63个扇区用于存放分区表,此时就只剩4033个扇区了;之后由这段代码,sz_vol为4033,pau为1,得出n_clst为4033<4085(MAX_FAT12),于是设为FAT12格式
    • 如果输入参数为FAT+SFD,sz_vol值为4096,之后由这段代码,pau为2,再执行1中代码,n_clst为2048,依然是FAT12格式
    • 输入参数FAT+SFD,并在输入参数中强制pau为1,倒是不会置为FAT12格式,但是格式化返回FR_MKFS_ABORTED错误。查找错误原因,发现问题来自这段代码。sz_blk由disk指令Get_Block_Size得到,这里我把这个值设为了4096(一个扇区),这样最后得到的n_clst为0,小于MAX_FAT12,返回错误代码。实际上这个值是以扇区为单位,应设为1。
  5. 问题5:不正确的格式化。【此时对FAT文件系统结构的理解是错误的】
    • sz_fat只有3,于是后面格式化只格式化了3个扇区。可是sz_fat和n_clst是互斥的:如果sz_fat很大就意味着n_clst很小,无法格式化为FAT16;如果n_clst格式化为FAT16那就意味着sz_fat是小于10的数。
    • 此时尝试创建文件,“果然”可以创建成功、但无法正确保存:每次重启后能载入文件系统,但获取不到之前创建的文件。
    • 于是开始走向错误的尝试路径:尝试减小单个扇区的定义大小、单次擦除多个扇区。
    • 尝试将单个扇区自定义为1k,block定义为4扇区,修改disk_read函数、disk_wirte函数、disk_ioctl函数,以及格式化函数f_mkfs的输入参数。
      1. 结果:不可行。实际操作中会有写入单个扇区的情况(分区:1系统保留区-x数据区-y页表区),如此,在写入第一个数据扇区的时候,会执行一次erase函数,擦除刚刚写入的系统保留区。类似的情况也会出现在其他地方。
      2. 修改为仅在初始扇区为4的倍数时,允许擦除。如此不会擦除正确写入的数据,但有可能无法成功修改某些单个小扇区。
      3. 修改为,在写入扇区时,如果判断到初始扇区不为4的倍数或结束扇区不为4的倍数,先将4k真实扇区数据读出,再擦除真实扇区,然后将读出的数据写入需写入扇区前的部分,最后将需写入的数据写入。
      4. 依旧不可行,格式化能返回ok,但重启后出现无文件系统的错误,说明文件系统写入还是有问题。
  6. 解决问题5中文件无法正确保存的问题
    • 通过USB程序,将模块连到电脑上格式化。

      1. 用8k/扇区格式化,能格式化成功。但将格式化好的模块下载fatfs程序时,fatfs读取出现问题,因为fatfs最大支持的单扇区大小为4096字节。
      2. 用我的电脑4k/扇区格式化,一直格式化失败,串口打印出log发现写入都没有问题,写入后的读取却读不到有效内容。
      3. 在程序里面加上一段打印打码,执行对0扇区的写入后,打印写入到0扇区的内容,从而判断到底是什么导致了格式化失败。结果,加上这段代码后,格式化成功。
      4. 判断为需要在写入0扇区后延时一段时间再读取才能成功。加入延时函数后,格式化没有问题了。
    • 将格式化好的模块下载fatfs程序后,读取无问题,获取剩余空间大小也没有问题。但是,在f_open创建文件、f_write进行写入操作、f_close关闭文件后,下次用f_open打开这个文件(OPEN_EXISTING选项)时,依然返回找不到文件的错误。
    • 经过各种调试,发现在disk_write函数中,每次进出打断点,这样进行的f_write和f_close操作,能成功保存文件、修改页表,下次f_open能够读到这个文件。
    • 判断是延时问题,尝试在disk_write出口处加上100ms延时,问题解决。实验发现,延时最短到15ms的时候,可以正常保存文件。最终将延时设为20ms。
  7. 解决格式化失败的问题:
    • 既然无法保存的问题出自写入后的延时,那么之前的格式化之后文件无法保存的问题是否也出自这里?
    • 之前的判断认为是fatfs将页表存在末4个扇区内,所以导致文件无法保存的原因是只格式化了前面的数个扇区,没有成功格式化。现在认为这个判断是错误的。
    • 因为经过调试发现,前几个扇区都是用于存储fatfs相关内容的。之前以为是数据区的sz_fat,目前看来应该是fat文件页表;之前认为是文件页表的sz_dir,实际上是fat目录表。
    • 也就是说,fat16文件系统的结构是这样的:(参见https://blog.csdn.net/sikuon/article/details/75222224)
      1. rsv:系统保留区(0扇区的DBR,可能存在的分区表,以及其他保留扇区),位于第0--x扇区。
      2. fat:文件页表区(有时会有FAT2作为FAT的备份),位于x+1--y扇区。
      3. dir:文件目录表区,位于y+1--z扇区
      4. data:数据区,位于z+1--末扇区
    • 那么,昨天遇到的情况,格式化只格了前几个扇区,是正确的操作。如此说来,GET_BLOCK_SIZE的功能的确如我所理解的那样,是扇区数量。block_size就是一次性擦除的扇区数量。
    • 如此,格式化的参数有两种选择:
      1. 根据昨天的经验,用f_mkfs("", FM_FAT, 0, work_buffer, FF_MAX_SS);这样的参数格式化,只能格式化为FAT12(或许应该再试试,因为最初用这种参数格式化时,用的BLOCK_SIZE是4096--与此无关,只要不是SFD格式,都会-63扇区作为起始扇区)。
      2. 根据昨天的经验,用f_mkfs("", FM_FAT+FM_SFD, 4096, work_buffer, FF_MAX_SS);这样的参数,能成功格式化为FAT16,但这是软盘格式,电脑上不一定可用。
      3. 最终试验发现第一种会格式化为FAT12,第二种可行。
  8. 在最开始遇到的一个问题,后来在另一个用到Fatfs的板子上又遇到了:
    1. 现象:开机f_getfree函数返回FR_NO_FILESYSTEM,进入格式化;f_mkfs函数返回FR_OK,格式化成功;下一步f_open函数又返回FR_NO_FILESYSTEM错误。
    2. 原因:SPIFlash虚焊。焊好后恢复正常。

转载于:https://www.cnblogs.com/cage666/p/9206853.html

stm32--FatFs调试过程(SPIFlash)相关推荐

  1. STM32调试过程中出现的问题1:

    STM32调试过程中出现的问题1: -\HARDWARE\KEY\key.c(47): error: #29: expected an expression if(key_up&&(K ...

  2. PLC、STM32单片机、PC端485modbus通信调试过程

    设备明细: PLC:埃森ARS-010-32PLC,软件AR Logic Editor. 单片机:STM32F103RCT6,软件keil. 测试软件:modbus串口调试软件.modbus poll ...

  3. Proteus仿真stm32和51单片机,串口通信调试过程记录

    前言 本文所用Proteus版本为8.10,主要内容为在Proteus中仿真stm32和51单片机进行串口通信,记录了仿真过程中遇到的问题和解决办法.        这里要注意的是,在Proteus中 ...

  4. STM32(Cortex-M3)启动过程+IAR中xcl及icf文件详解

    一:STM32(Cortex-M3)启动过程(入口地址) ARM7和ARM9启动时从绝对地址0X00000000开始执行复位中断程序,即固定了复位后的起始地址,但中断向量表的位置是可变的. Corte ...

  5. stm32时钟初始化过程浅析

    stm32时钟初始化过程浅析 (大致梳理了一下32启动过程中时钟的初始化过程) 加载main函数之前(启动代码中LDR R0, =__main之前),HCLK总线时钟默认上电是上一次断电前配置的频率 ...

  6. 学习 stm32 FATFS 系统文件函数使用和学习查看说明以及常用函数例程

    学习 stm32 FATFS 文件的日常操作,本次通过SDIO模式进行存储卡的设备连接,进行数据的读取操作.之前介绍过一起SD卡的读取操作, stm32 SD(SDSC)卡的学习与SPI 模式应用(卡 ...

  7. STM32电路板调试Could not power up debug port

    前段时间调试一块STM32的实验板,下载程序始终提示:Could not power up debug port: Control/Status register reads 000000F0. 网上 ...

  8. STM32——USMART调试组件实验-M4

    什么是USMART? USMART是为STM32开发平台开发的一种类似Linux的shell的调试工具.具体工作过程是通过串口发送命令给单片机,然后单片机收到命令之后调用单片机里面对应的相关函数并执行 ...

  9. STM32的调试方式、更新程序、仿真以及补救措施

    STM32的调试方式.更新程序.仿真以及补救措施 1. STM32的调试方式选择 STM32支持JTAG和SWD两种调试方式,且默认状态下这两种调试功能都是开启的. 由此我们可以知道: 如果要使用JT ...

最新文章

  1. 如何从功能测试转化自动化测试?
  2. 苹果的浏览器safari无法识别 2016-1-1这样的日期,会返回Invalid Date
  3. 某都计算机考研计算机组成原理,东北大学2000年考研真题-计算机组成原理
  4. struts深入原理之RequestProcessor与xml
  5. Ansible管理节点过多导致的超时问题解决方法
  6. CSS定位网页中的元素
  7. 唐骏:幸福与财富无关
  8. 吴恩达机器学习笔记(二) —— Logistic回归
  9. 深度解析容器化技术在广发证券交易系统的应用【转】
  10. 惠斯通电桥信号调理芯片_变频器通电后无反应,如何检查维修?
  11. python软件下载3版本-Python软件下载-Python最新版 v3.7.3 - 动力软件园
  12. Python+selenium+eclipse执行web自动化(四)控件处理
  13. pagerTabStrip例子
  14. android usb pos机,USB支持安卓系统NFC刷卡器|RFID刷卡机ACR122U
  15. 计算机软件工程自考,自考软件工程试题及答案2021年10月
  16. matlab 读取odb,求教用C++方式读取abaqus的odb数据中的问题!!!
  17. 觅知blibli专业版弹幕播放器开源无加密JSON解析版-后台功能一键管理-开源版22-8-24
  18. mt6573的DSI 接口
  19. 近端梯度法(Proximal Gradient Method, PG)
  20. Gateway杂谈:线上引流和灰度发布

热门文章

  1. Photon服务器引擎入门
  2. python基础之模块之os模块
  3. Oracle DataGuard数据备份方案详解
  4. C#在线打开编辑保存Excel文件[pageoffice]
  5. @Controller 不能访问到
  6. 如何从Alfresco中提取Language Pack
  7. Linq to Oracle 使用教程(七)将数据库的存储过程映射到方法
  8. linux tcp cork,Socket选项系列之TCP_CORK(转)
  9. IDEA启动hadoop报Could not locate executable null\bin\winutils.exe in the Hadoop binaries.错误的解决办法
  10. deephash项目代码使用指北