移植方法参见我的另一篇博客:《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,之后由
    • 输入参数FAT+SFD,并在输入参数中强制pau为1,倒是不会置为FAT12格式,但是格式化返回FR_MKFS_ABORTED错误。查找错误原因,发现问题来自
  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虚焊。焊好后恢复正常。

stm32--FatFs调试过程(SPIFlash)的更多相关文章

  1. STM32的操作过程,寄存器配置与调试过程(转载)

    很多学习stm32的,为什么学习stm32他也不知道,我们所知道的就是各个论坛讨论stm32的很多,而我们很多人之所以学习stm32是很多的淘宝卖家做了大量的图片文字宣传,于是我们经不住诱惑就买了板子 ...

  2. 关于火狐浏览器在开发调试过程中,出现javascript:void(0)的状态

    关于火狐浏览器在开发调试过程中,出现javascript:void(0)的状态 由于火狐浏览器没有安装 Adobe Flash Player 19 NPAPI这个插件 安装好了之后就可以直接运行了

  3. S3C6410裸奔之旅——RVDS2.2编译、仿真、调试过程 LED流水灯---转的

    S3C6410裸奔之旅——RVDS2.2编译.仿真.调试过程 LED流水灯 (2012-10-13 23:56:30) 转载▼ 标签: s3c6410裸奔 ok6410 rvds2.2 rvds2.2 ...

  4. MYSQL存储过程调试过程

     mysql不像oracle有plsqldevelper工具用来调试存储过程,所以有几种简单的方式追踪执行过程: 1.用一张临时表,记录调试过程: 2.直接在存储过程中,增加select xxx,在控 ...

  5. Android APP 调试过程中遇到的问题。

    调试过过程中APP安装完启动后有的时候会异常退出,报这个错误.有的时候可以直接启动.查找不到原因.网上说把commit方法替换成commitAllowingStateLoss() 也无效. Andro ...

  6. 调试过程中发现按f5无法走进jdk源码

    debug 模式 ,在fis=new FileInputStream(file); 行打断点 调试过程中发现按f5无法走进jdk源码 package com.lzl.spring.test; impo ...

  7. 0xe7f001f0!?NDK调试过程,无故抛出SIGSEGV。

    arm调试过程,如果抛一个SIGSEGV,地址在 0xe7f001f0 附近,原因居然是因为我在调试.当我使用n指令跳到下一行代码时,往往变成了continue指令一样地执行.还不确定地抛出SIGSE ...

  8. VS·调试过程中某个操作导致调试突然退出之解决方案

    阅文时长 | 0.11分钟 字数统计 | 232字符 主要内容 | 1.引言&背景 2.声明与参考资料 『VS·调试过程中某个操作导致调试突然退出之解决方案』 编写人 | SCscHero 编 ...

  9. stm32调试过程中如何判断是程序问题还是硬件问题?

    可以用软件仿真,如果软件仿真时寄存器什么的都正确,而硬件在线仿真时不对,则说明是板子硬件的问题

随机推荐

  1. POJ 1986 Distance Queries 【输入YY && LCA(Tarjan离线)】

    任意门:http://poj.org/problem?id=1986 Distance Queries Time Limit: 2000MS   Memory Limit: 30000K Total ...

  2. 2018.12.1 web项目中解决乱码问题的一个工具类

    <!-- 配置一个过滤器 编码格式的过滤器 --> <filter> <filter-name>encodeFilter</filter-name> & ...

  3. PSROIAlign的代码实现

    https://github.com/afantideng/R-FCN-PSROIAlign

  4. Angularjs实例2

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  5. 菜鸟崛起 DB Chapter 1 数据库概述

    1. 数据库的概述 在目前阶段,如果要存储和管理数据,则离不开数据库.当数据存储到数据库后,就会通过数据库管理系统对这些数据进行组织和管理.数据库由一批数据构成有序的集合,这些数据被存放在结构化的数据 ...

  6. 2018-03-21 11:34:44 java脚本批量转换java utf-8 bom源码文件为utf-8编码文件

    package com.springbootdubbo; import java.io.*;import java.util.ArrayList;import java.util.List; /** ...

  7. Nacicat for Oracle 绿色版 亲测可用

    参考: http://blog.csdn.net/u013107634/article/details/52741591 https://blog.csdn.net/zhengyikuangge/ar ...

  8. iOS:常用属性、方法

    前言:一段时间没接触,很容易就忘记以前的知识.专写一篇,供几个月没接触,拿起却忘记了. 0.宏定义.系统相关 0-1).宏定义.规范 变量: //全局变量通常用小写g来提示 int gNumb=0; ...

  9. ETO的公开赛T5《猎杀蓝色空间号》题解

    这道题别看题面这么长,其实题意很简单 就是让你求从起点开始的最长合法区间 合法的要求有两个:兜圈子和直飞 且这两个条件相互独立 (也就是说兜圈子的末尾不会对下面可能出现的直飞造成影响) 举个例子: 1 ...

  10. 小a的强迫症(组合数学)

    问题描述: 小a是一名强迫症患者,现在他要给一群带颜色的珠子排成一列,现在有N种颜色,其中第i种颜色的柱子有num(i)个.要求排列中第i种颜色珠子的最后一个珠子,一定要排在第i+1种颜色的最后一个珠 ...