Search code examples
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 ) ;
    }