/* storage control modules to the FatFs module with a defined API. */\r
/*-----------------------------------------------------------------------*/\r
\r
+#include <string.h>\r
#include "diskio.h" /* FatFs lower layer API */\r
-\r
-/* Definitions of physical drive number for each drive */\r
-#define DEV_RAM 0 /* Example: Map Ramdisk to physical drive 0 */\r
-#define DEV_MMC 1 /* Example: Map MMC/SD card to physical drive 1 */\r
-#define DEV_USB 2 /* Example: Map USB MSD to physical drive 2 */\r
-\r
-\r
-/*-----------------------------------------------------------------------*/\r
-/* Get Drive Status */\r
-/*-----------------------------------------------------------------------*/\r
-\r
-DSTATUS disk_status (\r
- BYTE pdrv /* Physical drive nmuber to identify the drive */\r
-)\r
+#include "ffconf.h"\r
+#include "ff.h"\r
+#include "sdmmc_cmd.h"\r
+#include "esp_log.h"\r
+#include <time.h>\r
+#include <sys/time.h>\r
+\r
+static const char* TAG = "ff_diskio";\r
+static ff_diskio_impl_t s_impls[_VOLUMES] = { { 0 } };\r
+static sdmmc_card_t* s_cards[_VOLUMES] = { NULL };\r
+\r
+PARTITION VolToPart[] = {\r
+ {0, 1}, /* Logical drive 0 ==> Physical drive 0, 1st partition */\r
+ {1, 0} /* Logical drive 1 ==> Physical drive 1, auto detection */\r
+};\r
+\r
+void ff_diskio_register(BYTE pdrv, const ff_diskio_impl_t* discio_impl)\r
{\r
- DSTATUS stat;\r
- int result;\r
-\r
- switch (pdrv) {\r
- case DEV_RAM :\r
- result = RAM_disk_status();\r
-\r
- // translate the reslut code here\r
-\r
- return stat;\r
-\r
- case DEV_MMC :\r
- result = MMC_disk_status();\r
-\r
- // translate the reslut code here\r
-\r
- return stat;\r
-\r
- case DEV_USB :\r
- result = USB_disk_status();\r
-\r
- // translate the reslut code here\r
-\r
- return stat;\r
- }\r
- return STA_NOINIT;\r
+ assert(pdrv < _VOLUMES);\r
+ memcpy(&s_impls[pdrv], discio_impl, sizeof(ff_diskio_impl_t));\r
}\r
\r
-\r
-\r
-/*-----------------------------------------------------------------------*/\r
-/* Inidialize a Drive */\r
-/*-----------------------------------------------------------------------*/\r
-\r
-DSTATUS disk_initialize (\r
- BYTE pdrv /* Physical drive nmuber to identify the drive */\r
-)\r
+DSTATUS ff_disk_initialize (BYTE pdrv)\r
{\r
- DSTATUS stat;\r
- int result;\r
-\r
- switch (pdrv) {\r
- case DEV_RAM :\r
- result = RAM_disk_initialize();\r
-\r
- // translate the reslut code here\r
-\r
- return stat;\r
-\r
- case DEV_MMC :\r
- result = MMC_disk_initialize();\r
-\r
- // translate the reslut code here\r
-\r
- return stat;\r
-\r
- case DEV_USB :\r
- result = USB_disk_initialize();\r
-\r
- // translate the reslut code here\r
-\r
- return stat;\r
- }\r
- return STA_NOINIT;\r
+ return s_impls[pdrv].init(pdrv);\r
}\r
-\r
-\r
-\r
-/*-----------------------------------------------------------------------*/\r
-/* Read Sector(s) */\r
-/*-----------------------------------------------------------------------*/\r
-\r
-DRESULT disk_read (\r
- BYTE pdrv, /* Physical drive nmuber to identify the drive */\r
- BYTE *buff, /* Data buffer to store read data */\r
- DWORD sector, /* Start sector in LBA */\r
- UINT count /* Number of sectors to read */\r
-)\r
+DSTATUS ff_disk_status (BYTE pdrv)\r
{\r
- DRESULT res;\r
- int result;\r
-\r
- switch (pdrv) {\r
- case DEV_RAM :\r
- // translate the arguments here\r
-\r
- result = RAM_disk_read(buff, sector, count);\r
-\r
- // translate the reslut code here\r
-\r
- return res;\r
-\r
- case DEV_MMC :\r
- // translate the arguments here\r
-\r
- result = MMC_disk_read(buff, sector, count);\r
-\r
- // translate the reslut code here\r
-\r
- return res;\r
-\r
- case DEV_USB :\r
- // translate the arguments here\r
-\r
- result = USB_disk_read(buff, sector, count);\r
-\r
- // translate the reslut code here\r
-\r
- return res;\r
- }\r
-\r
- return RES_PARERR;\r
+ return s_impls[pdrv].status(pdrv);\r
}\r
-\r
-\r
-\r
-/*-----------------------------------------------------------------------*/\r
-/* Write Sector(s) */\r
-/*-----------------------------------------------------------------------*/\r
-\r
-DRESULT disk_write (\r
- BYTE pdrv, /* Physical drive nmuber to identify the drive */\r
- const BYTE *buff, /* Data to be written */\r
- DWORD sector, /* Start sector in LBA */\r
- UINT count /* Number of sectors to write */\r
-)\r
+DRESULT ff_disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count)\r
{\r
- DRESULT res;\r
- int result;\r
-\r
- switch (pdrv) {\r
- case DEV_RAM :\r
- // translate the arguments here\r
-\r
- result = RAM_disk_write(buff, sector, count);\r
-\r
- // translate the reslut code here\r
-\r
- return res;\r
-\r
- case DEV_MMC :\r
- // translate the arguments here\r
-\r
- result = MMC_disk_write(buff, sector, count);\r
-\r
- // translate the reslut code here\r
-\r
- return res;\r
-\r
- case DEV_USB :\r
- // translate the arguments here\r
-\r
- result = USB_disk_write(buff, sector, count);\r
-\r
- // translate the reslut code here\r
-\r
- return res;\r
- }\r
-\r
- return RES_PARERR;\r
+ return s_impls[pdrv].read(pdrv, buff, sector, count);\r
}\r
-\r
-\r
-\r
-/*-----------------------------------------------------------------------*/\r
-/* Miscellaneous Functions */\r
-/*-----------------------------------------------------------------------*/\r
-\r
-DRESULT disk_ioctl (\r
- BYTE pdrv, /* Physical drive nmuber (0..) */\r
- BYTE cmd, /* Control code */\r
- void *buff /* Buffer to send/receive control data */\r
-)\r
+DRESULT ff_disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count)\r
{\r
- DRESULT res;\r
- int result;\r
-\r
- switch (pdrv) {\r
- case DEV_RAM :\r
-\r
- // Process of the command for the RAM drive\r
-\r
- return res;\r
+ return s_impls[pdrv].write(pdrv, buff, sector, count);\r
+}\r
+DRESULT ff_disk_ioctl (BYTE pdrv, BYTE cmd, void* buff)\r
+{\r
+ return s_impls[pdrv].ioctl(pdrv, cmd, buff);\r
+}\r
\r
- case DEV_MMC :\r
+DWORD get_fattime(void)\r
+{\r
+ time_t t = time(NULL);\r
+ struct tm *tmr = gmtime(&t);\r
+ return ((DWORD)(tmr->tm_year - 80) << 25)\r
+ | ((DWORD)(tmr->tm_mon + 1) << 21)\r
+ | ((DWORD)tmr->tm_mday << 16)\r
+ | (WORD)(tmr->tm_hour << 11)\r
+ | (WORD)(tmr->tm_min << 5)\r
+ | (WORD)(tmr->tm_sec >> 1);\r
+}\r
\r
- // Process of the command for the MMC/SD card\r
+DSTATUS ff_sdmmc_initialize (BYTE pdrv)\r
+{\r
+ return 0;\r
+}\r
\r
- return res;\r
+DSTATUS ff_sdmmc_status (BYTE pdrv)\r
+{\r
+ return 0;\r
+}\r
\r
- case DEV_USB :\r
+DRESULT ff_sdmmc_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count)\r
+{\r
+ sdmmc_card_t* card = s_cards[pdrv];\r
+ assert(card);\r
+ esp_err_t err = sdmmc_read_blocks(card, buff, sector, count);\r
+ if (err != ESP_OK) {\r
+ ESP_LOGE(TAG, "sdmmc_read_blocks failed (%d)", err);\r
+ return RES_ERROR;\r
+ }\r
+ return RES_OK;\r
+}\r
\r
- // Process of the command the USB drive\r
+DRESULT ff_sdmmc_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count)\r
+{\r
+ sdmmc_card_t* card = s_cards[pdrv];\r
+ assert(card);\r
+ esp_err_t err = sdmmc_write_blocks(card, buff, sector, count);\r
+ if (err != ESP_OK) {\r
+ ESP_LOGE(TAG, "sdmmc_write_blocks failed (%d)", err);\r
+ return RES_ERROR;\r
+ }\r
+ return RES_OK;\r
+}\r
\r
- return res;\r
- }\r
+DRESULT ff_sdmmc_ioctl (BYTE pdrv, BYTE cmd, void* buff)\r
+{\r
+ sdmmc_card_t* card = s_cards[pdrv];\r
+ assert(card);\r
+ switch(cmd) {\r
+ case CTRL_SYNC:\r
+ return RES_OK;\r
+ case GET_SECTOR_COUNT:\r
+ *((uint32_t*) buff) = card->csd.capacity;\r
+ return RES_OK;\r
+ case GET_SECTOR_SIZE:\r
+ *((uint32_t*) buff) = card->csd.sector_size;\r
+ return RES_OK;\r
+ case GET_BLOCK_SIZE:\r
+ return RES_ERROR;\r
+ }\r
+ return RES_ERROR;\r
+}\r
\r
- return RES_PARERR;\r
+void ff_diskio_register_sdmmc(BYTE pdrv, sdmmc_card_t* card)\r
+{\r
+ static const ff_diskio_impl_t sdmmc_impl = {\r
+ .init = &ff_sdmmc_initialize,\r
+ .status = &ff_sdmmc_status,\r
+ .read = &ff_sdmmc_read,\r
+ .write = &ff_sdmmc_write,\r
+ .ioctl = &ff_sdmmc_ioctl\r
+ };\r
+ s_cards[pdrv] = card;\r
+ ff_diskio_register(pdrv, &sdmmc_impl);\r
}\r
\r
#endif\r
\r
#include "integer.h"\r
-\r
+#include "sdmmc_cmd.h"\r
+#include "driver/sdmmc_host.h"\r
\r
/* Status of Disk Functions */\r
typedef BYTE DSTATUS;\r
/* Prototypes for disk control functions */\r
\r
\r
+/* Redefine names of disk IO functions to prevent name collisions */\r
+#define disk_initialize ff_disk_initialize\r
+#define disk_status ff_disk_status\r
+#define disk_read ff_disk_read\r
+#define disk_write ff_disk_write\r
+#define disk_ioctl ff_disk_ioctl\r
+\r
+\r
DSTATUS disk_initialize (BYTE pdrv);\r
DSTATUS disk_status (BYTE pdrv);\r
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);\r
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);\r
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);\r
\r
+typedef struct {\r
+ DSTATUS (*init) (BYTE pdrv);\r
+ DSTATUS (*status) (BYTE pdrv);\r
+ DRESULT (*read) (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);\r
+ DRESULT (*write) (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);\r
+ DRESULT (*ioctl) (BYTE pdrv, BYTE cmd, void* buff);\r
+} ff_diskio_impl_t;\r
+\r
+void ff_diskio_register(BYTE pdrv, const ff_diskio_impl_t* discio_impl);\r
+\r
+void ff_diskio_register_sdmmc(BYTE pdrv, sdmmc_card_t* card);\r
\r
/* Disk Status Bits (DSTATUS) */\r
\r