FatFS – Cannot format drive, FR_MKFS_ABORTED

  c++, embedded, fatfs, stm32, stm32f4

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. I have successfully created the basic i/o for the w25 over SPI, being able to write and read sectors at a time.

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.

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. However, f_mkfs() keeps returning FR_MKFS_ABORTED. (FF_MAX_SS is set to 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);

Upon investigating my ff.c, it seems that the code is halting on line 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 = (sz_vol - sz_rsv - sz_fat * n_fats - sz_dir) / pau;

Here is what the debugger reads the variables going in as:

enter image description here

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. 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. The minimum erasable block size is 32kb. If you would need more info on the flash chip I am using, page 5 of this pdf outlines all of the specs.

This is what my USER_ioctl() looks like:

    BYTE pdrv,      /* Physical drive nmuber (0..) */
    BYTE cmd,       /* Control code */
    void *buff      /* Buffer to send/receive control data */
    UINT* result = (UINT*)buff;

    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;

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.

Source: Windows Questions C++