简体   繁体   English

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

[英]FatFS - Cannot format drive, FR_MKFS_ABORTED

I am new to embedded development and have been tasked with implementing a file system on SPI flash memory. I am using a w25qxx chip and an STM32F4xx on STM32CubeIDE.我是嵌入式开发的新手,负责在 SPI flash memory 上实现文件系统。我在 STM32CubeIDE 上使用 w25qxx 芯片和 STM32F4xx。 I have successfully created the basic i/o for the w25 over SPI, being able to write and read sectors at a time.我已经通过 SPI 成功地为 w25 创建了基本的 i/o,能够一次写入和读取扇区。

In my user_diskio.c I have implemented all of the needed i/o methods and have verified that they are properly linked and being called.在我的user_diskio.c中,我已经实现了所有需要的 i/o 方法,并验证了它们是否正确链接和被调用。

in my main.cpp I go to format the drive using f_mkfs() , then get the free space, and finally open and close a file.在我的main.cpp I go 中使用f_mkfs()格式化驱动器,然后获取可用空间,最后打开和关闭文件。 However, f_mkfs() keeps returning FR_MKFS_ABORTED .但是, f_mkfs()不断返回FR_MKFS_ABORTED (FF_MAX_SS is set to 16384) (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, 0, 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, "file67.txt", FA_READ);
  f_gets(buffer, f_size(&fil), &fil);
  f_close(&fil);

Upon investigating my ff.c , it seems that the code is halting on line 5617:在调查我的ff.c后,代码似乎在第 5617 行停止:

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

n_clst is calculated a few lines up before some conditional logic, on line 5594: n_clst在第 5594 行的某些条件逻辑之前计算几行:

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

Here is what the debugger reads the variables going in as:以下是调试器读取变量的内容:

在此处输入图像描述

This results in n_clst being set to 4294935040 , as it is unsigned, though the actual result of doing the calculations would be -32256 if the variable was signed.这导致n_clst被设置为4294935040 ,因为它是无符号的,但如果变量已签名,则计算的实际结果将是-32256 As you can imagine, this does not seem to be an accurate calculation.可以想象,这似乎不是一个准确的计算。

The device I am using has 16M-bit (2MB) of storage organized in 512 sectors of 4kb in size.我使用的设备具有 16M 位 (2MB) 的存储空间,分为 512 个 4kb 大小的扇区。 The minimum erasable block size is 32kb.最小可擦除块大小为 32kb。 If you would need more info on the flash chip I am using, page 5 of this pdf outlines all of the specs.如果您需要有关我正在使用的 flash 芯片的更多信息, 此 pdf 的第 5 页概述了所有规格。

This is what my USER_ioctl() looks like:这就是我的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 */
}

I have tried monkeying around with the parameters to f_mkfs() , swapping FM_ANY out for FM_FAT, FM_FAT32, and FM_EXFAT (along with enabling exFat in my ffconf.h . I have also tried using several values for au rather than the default. For a deeper documentation on the f_mkfs() method I am using, check here , there are a few variations of this method floating around out there.我尝试过使用f_mkfs()的参数,将 FM_ANY 换成 FM_FAT、FM_FAT32 和 FM_EXFAT(同时在我的ffconf.h中启用 exFat。我还尝试使用 au 的多个值而不是默认值。对于一个有关我正在使用的f_mkfs()方法的更深入的文档, 请在此处查看,此方法有一些变体。

Here:这里:

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

The second argument is not valid.第二个参数无效。 It should be a pointer to a MKFS_PARM structure or NULL for default options, as described at http://elm-chan.org/fsw/ff/doc/mkfs.html .它应该是指向MKFS_PARM结构或 NULL 的默认选项的指针,如http://elm-chan.org/fsw/ff/doc/mkfs.ZFC35FDC70D52FC69D269883A中所述。

You should have something like:你应该有类似的东西:

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

except that it is unlikely for your media (SPI flash) that the default option are appropriate - the filesystem cannot obtain formatting parameters from the media as it would for SD card for example.除了您的媒体(SPI 闪存)不太可能使用默认选项 - 文件系统无法像 SD 卡那样从媒体获取格式化参数。 You have to provide the necessary formatting information.您必须提供必要的格式信息。

Given your erase block size I would guess:鉴于您的擦除块大小,我猜:

 MKFS_PARM fmt_opt = {FM_ANY, 0, 32768, 0, 0};

but to be clear I have never used the ELM FatFS (which STM32Cube incorporates) with SPI flash - there may be additional issues.但要明确的是,我从未将 ELM FatFS(STM32Cube 包含)与 SPI flash 一起使用 - 可能还有其他问题。 I also do not use STM32CubeMX - it is possible I suppose that the version has a different interface, but I would recommend using the latest code from ELM rather than ST's possibly fossilised version.我也不使用 STM32CubeMX - 我可能认为该版本具有不同的接口,但我建议使用 ELM 的最新代码,而不是 ST 可能的僵化版本。

Another consideration is that FatFs is not particularly suitable for your media due to wear-levelling issues.另一个考虑因素是,由于磨损均衡问题,FatFs 并不是特别适合您的媒体。 Also ELM FatFs has not journalling or check/repair function, so is not power fail safe.此外,ELM FatFs 没有日志记录或检查/修复 function,因此不是电源故障安全。 That is particularly important for non-removable media that you cannot easily back-up or repair.这对于您无法轻松备份或修复的不可移动媒体尤其重要。

You might consider a file system specifically designed for SPI NOR flash such as SPIFFS , or the power-fail safe LittleFS .您可能会考虑专门为 SPI NOR flash 设计的文件系统,例如SPIFFS或电源故障安全LittleFS Here is an example of LittleFS in STM32: https://uimeter.com/2018-04-12-Try-LittleFS-on-STM32-and-SPI-Flash/这是STM32中LittleFS的一个例子: https://umeter.com/2018-04-12-Try-LittleFS-on-STM32-and-SPI-Flash/

I don't believe the answer is correct.我不相信答案是正确的。 OP is using the right arguments for the version of FatFS OP is using. OP 正在为 OP 正在使用的 FatFS 版本使用正确的参数。

The suggested answer uses a different version with different arguments.建议的答案使用具有不同参数的不同版本。

Switching to LittleFS may be the right answer in the end, but does not answer the original question.切换到 LittleFS 可能是最终的正确答案,但并不能回答最初的问题。

I have run into the same problem, will post something once I figure it out.我遇到了同样的问题,一旦我弄明白了就会发布一些东西。

I suspect it is on the line that OP mentions where n_clist is computed.我怀疑是在 OP 提到计算 n_clist 的地方。 It seems to me that the value sz_fat is in bytes while all other values are in sectors.在我看来,值 sz_fat 以字节为单位,而所有其他值以扇区为单位。 At least that is what my cursory examination says.至少我的粗略检查是这么说的。

Ok, I think the real problem was that the IOCTL call GET_BLOCK_SIZE to get the block size was returning the sector size instead of the number of sectors in the block.好的,我认为真正的问题是 IOCTL 调用 GET_BLOCK_SIZE 来获取块大小返回的是扇区大小而不是块中的扇区数。 Which is usually 1 for SPI Flash.对于 SPI Flash 通常为 1。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM