]> granicus.if.org Git - esp-idf/commitdiff
fatfs: add pluggable diskio layer, sdmmc implementation
authorIvan Grokhotkov <ivan@espressif.com>
Thu, 29 Dec 2016 09:33:38 +0000 (17:33 +0800)
committerIvan Grokhotkov <igrokhotkov@gmail.com>
Sun, 8 Jan 2017 20:51:24 +0000 (04:51 +0800)
components/fatfs/src/diskio.c
components/fatfs/src/diskio.h
components/fatfs/src/ffconf.h
components/fatfs/src/option/syscall.c

index 25f5e53bc032bd3fcdacd3c53582e63e73ae8dcc..b00e9d2ca516c1ec1914508d4da854480b375049 100644 (file)
 /* 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
index 03e8b7c560badc2265fff3c14e82d817f3f26ba4..921ef9836a3360dd2387dfda7f0b01eeec50c9ab 100644 (file)
@@ -10,7 +10,8 @@ extern "C" {
 #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
@@ -29,12 +30,31 @@ typedef enum {
 /* 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
index c43321f626caa48b180ae0db8b4f68dcd6a078ad..b3a1bf574738e8bcc7909cd581551910635e1971 100644 (file)
@@ -39,7 +39,7 @@
 /  f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */\r
 \r
 \r
-#define        _USE_MKFS               0\r
+#define        _USE_MKFS               1\r
 /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */\r
 \r
 \r
@@ -69,7 +69,7 @@
 / Locale and Namespace Configurations\r
 /---------------------------------------------------------------------------*/\r
 \r
-#define _CODE_PAGE     932\r
+#define _CODE_PAGE     1\r
 /* This option specifies the OEM code page to be used on the target system.\r
 /  Incorrect setting of the code page can cause a file open failure.\r
 /\r
 / Drive/Volume Configurations\r
 /---------------------------------------------------------------------------*/\r
 \r
-#define _VOLUMES       1\r
+#define _VOLUMES       2\r
 /* Number of volumes (logical drives) to be used. */\r
 \r
 \r
 /  the drive ID strings are: A-Z and 0-9. */\r
 \r
 \r
-#define        _MULTI_PARTITION        0\r
+#define        _MULTI_PARTITION        1\r
 /* This option switches support of multi-partition on a physical drive.\r
 /  By default (0), each logical drive number is bound to the same physical drive\r
 /  number and only an FAT volume found on the physical drive will be mounted.\r
index c9d219b797027dab0c1ad1721a62f1084a18f9aa..14140c5a732a4ae73c1bd7cb9c5cb2620f146fd9 100644 (file)
@@ -9,7 +9,7 @@
 \r
 #if _FS_REENTRANT\r
 /*------------------------------------------------------------------------*/\r
-/* Create a Synchronization Object\r
+/* Create a Synchronization Object                                        */\r
 /*------------------------------------------------------------------------*/\r
 /* This function is called in f_mount() function to create a new\r
 /  synchronization object, such as semaphore and mutex. When a 0 is returned,\r