cembeddedstm32spifatfs

Deinitialising FatFS and mounting another SD card


I've been trying to mount an SD card, write some data to some files, then dismount the SD card. Mount a separate one and write to more files (This is done via a multiplexer and two separate but identical SD card modules). I am using an STM32F3 and an SPI interface, I can mount and write to files without issue but I am struggling to properly deinitialise all of FatFs variables between SD cards.

I am taking the following steps

Using f_close to close all open files. Dismounting the drive by mounting a NULL drive f_mount(0, "", 0);. I then call FATFS_UnLinkDriver. My main issue appears to be that after all these steps disk.is_initilized still returns 1.

DSTATUS disk_initialize (
    BYTE pdrv               /* Physical drive nmuber to identify the drive */
)
{
  DSTATUS stat = RES_OK;
  
  if(disk.is_initialized[pdrv] == 0)
  { 
    disk.is_initialized[pdrv] = 1;
    stat = disk.drv[pdrv]->disk_initialize(disk.lun[pdrv]);
  }
  return stat;
}

Therefore the SPI initilising code I am using is not called for the second SD card. I can get around this by manually calling the SPI initialise but I would like to know if I am missing any steps in deinitialising. Ideally I would like to return all of FatFS stack to the default state, as if the microcontroller were power cycled between SD card swaps.


Solution

  • The media access interface where disk_initialise() is defined did not envisage perhaps you physically changing the hardware interface. disk.is_initialized[pdrv] is there only to block unnecessary reinitialization of the hardware, and is a one way switch.

    You can force reinitialisation simply by resetting disk.is_initialized[pdrv] to 0:

    DSTATUS disk_deinitialize (
        BYTE pdrv               /* Physical drive number to identify the drive */
    )
    {
      disk.is_initialized[pdrv] = 0 ;
      return RES_OK ;
    }
    

    Thereafter a call to disk_initialize() will perform the initialisation.

    Or you could have a re-initialise function:

    DSTATUS disk_reinitialize (
        BYTE pdrv               /* Physical drive number to identify the drive */
    )
    {
      disk.is_initialized[pdrv] = 0 ;
      return disk_initialize( pdrv ) ;
    }