FatFS - 无法格式化驱动器,FR_MKFS_ABORTED

问题描述

我是嵌入式开发的新手,我的任务是在 SPI 闪存上实现文件系统。我在 STM32CubeIDE 上使用 w25qxx 芯片和 STM32F4xx。我已经成功地通过 SPI 为 w25 创建了基本的 I/O,能够一次写入和读取扇区。

在我的 user_diskio.c 中,我已经实现了所有需要的 I/O 方法,并验证了它们是否正确链接和被调用

在我的 main.cpp 中,我使用 f_mkfs() 格式化驱动器,然后获取可用空间,最后打开和关闭文件。但是,f_mkfs() 不断返回 FR_MKFS_ABORTED。 (FF_MAX_SS 设置为 16384)

  fresult = FR_NO_FILESYstem;
  if (fresult == FR_NO_FILESYstem)
  {
      BYTE work[FF_MAX_SS]; // Formats the drive if it has yet to be formatted
      fresult = f_mkfs("0:",FM_ANY,work,sizeof work);
  }

  f_getfree("",&fre_clust,&pfs);

  total = (uint32_t)((pfs->n_fatent - 2) * pfs->csize * 0.5);
  free_space = (uint32_t)(fre_clust * pfs->csize * 0.5);

  fresult = f_open(&fil,"file67.txt",FA_OPEN_ALWAYS | FA_READ | FA_WRITE);
  f_puts("This data is from the FILE1.txt. And it was written using ...f_puts... ",&fil);
  fresult = f_close(&fil);

  fresult = f_open(&fil,FA_READ);
  f_gets(buffer,f_size(&fil),&fil);
  f_close(&fil);

在调查我的 ff.c 后,代码似乎在第 5617 行停止:

if (fmt == FS_FAT12 && n_clst > MAX_FAT12) return FR_MKFS_ABORTED; /* Too many clusters for FAT12 */

n_clst 是在一些条件逻辑之前的几行计算出来的,在第 5594 行:

n_clst = (sz_vol - sz_rsv - sz_fat * n_fats - sz_dir) / pau;

调试器读取的变量如下:

enter image description here

这导致 n_clst 被设置为 4294935040,因为它是无符号的,但如果变量有符号,计算的实际结果将是 -32256。可以想象,这似乎不是一个准确的计算。

我使用的设备有 16M 位 (2MB) 的存储空间,组织在 512 个大小为 4kb 的扇区中。最小可擦除块大小为 32kb。如果您需要有关我使用的闪存芯片的更多信息,page 5 of this pdf outlines all of the specs.

这就是我的 USER_ioctl() 的样子:

DRESULT USER_ioctl (
    BYTE pdrv,/* Physical drive nmuber (0..) */
    BYTE cmd,/* Control code */
    void *buff      /* Buffer to send/receive control data */
)
{
  /* USER CODE BEGIN IOCTL */
    UINT* result = (UINT*)buff;
    HAL_GPIO_WritePin(GPIOE,GPIO_PIN_11,GPIO_PIN_SET);

    switch (cmd) {
        case GET_SECTOR_COUNT:
            result[0] = 512; // Sector and block sizes of
            return RES_OK;
        case GET_SECTOR_SIZE:
            result[0] = 4096;
            return RES_OK;
        case GET_BLOCK_SIZE:
            result[0] = 32768;
            return RES_OK;

    }
    return RES_ERROR;
  /* USER CODE END IOCTL */
}

我尝试过将参数设置为 f_mkfs(),将 FM_ANY 换成 FM_FAT、FM_fat32 和 FM_EXFAT(以及在我的 ffconf.h 中启用 exFat。我还尝试对 au 使用多个值而不是认值。有关我正在使用的 f_mkfs() 方法的更深入文档,check here,此方法有一些变体。

解决方法

这里:

fresult = f_mkfs("0:",FM_ANY,work,sizeof work);

第二个参数无效。对于默认选项,它应该是指向 MKFS_PARM 结构的指针或 NULL,如 http://elm-chan.org/fsw/ff/doc/mkfs.html 所述。

你应该有类似的东西:

MKFS_PARM fmt_opt = {FM_ANY,0};
fresult = f_mkfs("0:",&fmt_opt,sizeof work);

除了您的媒体(SPI 闪存)不太可能使用默认选项 - 文件系统无法像 SD 卡那样从媒体获取格式化参数。您必须提供必要的格式信息。

鉴于您的擦除块大小,我猜:

 MKFS_PARM fmt_opt = {FM_ANY,32768,0};

但要明确的是,我从未使用过带有 SPI 闪存的 ELM FatFS(STM32Cube 集成了它)——可能还有其他问题。我也不使用 STM32CubeMX - 我认为该版本可能有不同的界面,但我建议使用来自 ELM 的最新代码,而不是 ST 可能的僵化版本。

另一个考虑因素是,由于磨损均衡问题,FatFs 不是特别适合您的媒体。此外,ELM FatFs 没有日志记录或检查/修复功能,因此不是电源故障安全的。这对于无法轻松备份或修复的不可移动媒体尤为重要。

您可以考虑专门为 SPI NOR 闪存设计的文件系统,例如 SPIFFS,或电源故障安全 LittleFS。以下是 STM32 中的 LittleFS 示例:https://uimeter.com/2018-04-12-Try-LittleFS-on-STM32-and-SPI-Flash/

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...