Build a low level driver for SD card, then the glue logic for FatFs and USB MSD is pretty much the same as Flash memory case posed before. In case of SD card, sector size is 512 in most of the cases. Thus the memory requirement is much relaxed. You can even allocate a file buffer bigger than the sector size.
FatFs site has a dedicated page for MMC/SDC, on which you can find fairly detailed explanation about how to interface MMC/SDC via SPI bus. Implementation should be straightforward until you encounter with cheap SD cards that do not behave very well.
In such cases, you either have to protect your code with redundancy or just stick with quality devices. If you choose SanDisk or Kingston brand, you will be safe. ADATA on the other hand, frequently generates timeout error at first try.
Most of the SD card sockets have a pin to detect the presence of the card. This pin is usually connected to GND pin or some other pin. You can use this to generate interrupt whenever a card is inserted or removed.
When inserted, run FATFS_LinkDriver() and call f_mount. When removed, you need to call FATFS_UnLinkDriver() to clear the disk state.
596 // card is removed 597 if(HAL_GPIO_ReadPin(SDC_EX_GPIO_Port, SDC_EX_Pin)) 598 { 599 // reset SDCard state 600 SDCard_SetStatus(SDCARD_NODISK); 601 // decomission fatfs 602 FATFS_UnLinkDriver(USERPath); 603 DbgPrintf("\r\nSD card removed"); 604 } 605 // card is inserted 606 else 607 { 608 DbgPrintf("\r\nSD card inserted"); 609 // initialize fatfs 610 retUSER = FATFS_LinkDriver(&USER_Driver, USERPath); 611 // mount volume 612 if((fr = f_mount(&USERFatFS, "/", 1)) == FR_OK) 613 { 614 DbgPrintf("\r\nVolume mounted"); 615 } 616 else 617 { 618 DbgPrintf("\r\nFailed to mount volume:%d", fr); 619 } 620 }
This hot-plugging does not work however for USB MSD interface. You have to insert the card before you plug the device to the USB port of the host system. And do not remove the card during USB operation.

