Skip to content

Commit

Permalink
drivers/mtd_sdcard: add SDMMC support
Browse files Browse the repository at this point in the history
  • Loading branch information
gschorcht committed May 15, 2023
1 parent ffa388f commit 1c169e3
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 16 deletions.
12 changes: 12 additions & 0 deletions drivers/include/mtd_sdcard.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,14 @@

#include <stdint.h>

#if IS_USED(MODULE_SDCARD_SPI)
#include "sdcard_spi.h"
#elif IS_USED(MODULE_PERIPH_SDMMC)
#include "sdmmc/sdmmc.h"
#else
#error "No SD Card driver module selected"
#endif

#include "mtd.h"

#ifdef __cplusplus
Expand All @@ -39,8 +46,13 @@ extern "C"
*/
typedef struct {
mtd_dev_t base; /**< inherit from mtd_dev_t object */
#if IS_USED(MODULE_SDCARD_SPI)
sdcard_spi_t *sd_card; /**< sdcard_spi dev descriptor */
const sdcard_spi_params_t *params; /**< params for sdcard_spi init */
#elif IS_USED(MODULE_PERIPH_SDMMC)
uint8_t sd_card_idx; /**< sdmmc peripheral index */
sdmmc_dev_t *sd_card; /**< sdmmc dev descriptor */
#endif
} mtd_sdcard_t;

/**
Expand Down
4 changes: 3 additions & 1 deletion drivers/mtd/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ ifneq (,$(filter mtd_sdcard_default,$(USEMODULE)))
endif

ifneq (,$(filter mtd_sdcard,$(USEMODULE)))
USEMODULE += sdcard_spi
ifeq (,$(filter sdmmc,$(USEMODULE)))
USEMODULE += sdcard_spi
endif
endif
133 changes: 118 additions & 15 deletions drivers/mtd_sdcard/mtd_sdcard.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,33 @@
*
* @}
*/

#include <errno.h>
#include <inttypes.h>
#include <string.h>

#define ENABLE_DEBUG 0
#include "debug.h"
#include "kernel_defines.h"
#include "macros/utils.h"
#include "mtd.h"
#include "mtd_sdcard.h"

#if IS_USED(MODULE_SDCARD_SPI)
#include "sdcard_spi.h"
#include "sdcard_spi_internal.h"
#endif

#include <inttypes.h>
#include <errno.h>
#include <string.h>
#if IS_USED(MODULE_SDMMC)
#define SD_HC_BLOCK_SIZE SDMMC_SDHC_BLOCK_SIZE
#endif

static int mtd_sdcard_init(mtd_dev_t *dev)
{
DEBUG("mtd_sdcard_init\n");
mtd_sdcard_t *mtd_sd = (mtd_sdcard_t*)dev;

#if IS_USED(MODULE_SDCARD_SPI)
if ((mtd_sd->sd_card->init_done == true) ||
(sdcard_spi_init(mtd_sd->sd_card, mtd_sd->params) == 0)) {
/* erasing whole sectors is handled internally by the card so you can
Expand All @@ -47,13 +57,33 @@ static int mtd_sdcard_init(mtd_dev_t *dev)
dev->write_size = SD_HC_BLOCK_SIZE;
return 0;
}
#elif IS_USED(MODULE_SDMMC)
/* get the SDMMC device descriptor from SDMMC peripheral index */
mtd_sd->sd_card = sdmmc_get_dev(mtd_sd->sd_card_idx);

if ((mtd_sd->sd_card->init_done == true) ||
(sdmmc_card_init(mtd_sd->sd_card) == 0)) {
/* erasing whole sectors is handled internally by the card so you can
delete single blocks (i.e. pages) */
dev->pages_per_sector = 1;
dev->sector_count = (uint32_t)(sdmmc_get_capacity(mtd_sd->sd_card) /
SDMMC_SDHC_BLOCK_SIZE);

/* sdcard uses the fixed block size of SD-HC cards */
dev->page_size = SDMMC_SDHC_BLOCK_SIZE;
dev->write_size = SDMMC_SDHC_BLOCK_SIZE;
return 0;
}
#endif
return -EIO;
}

static int mtd_sdcard_read_page(mtd_dev_t *dev, void *buff, uint32_t page,
uint32_t offset, uint32_t size)
{
#if IS_USED(MODULE_SDCARD_SPI)
sd_rw_response_t err;
#endif
mtd_sdcard_t *mtd_sd = (mtd_sdcard_t*)dev;

DEBUG("mtd_sdcard_read_page: page:%" PRIu32 " offset:%" PRIu32 " size:%" PRIu32 "\n",
Expand All @@ -66,13 +96,19 @@ static int mtd_sdcard_read_page(mtd_dev_t *dev, void *buff, uint32_t page,
return -ENOTSUP;
}

#if IS_USED(MODULE_SDCARD_SPI)
sdcard_spi_read_blocks(mtd_sd->sd_card, page,
dev->work_area, SD_HC_BLOCK_SIZE,
1, &err);
if (err != SD_RW_OK) {
return -EIO;
}

#elif IS_USED(MODULE_SDMMC)
if (sdmmc_read_blocks(mtd_sd->sd_card, page, SDMMC_SDHC_BLOCK_SIZE,
1, dev->work_area, NULL)) {
return -EIO;
}
#endif
size = MIN(size, SD_HC_BLOCK_SIZE - offset);
DEBUG("mtd_sdcard_read_page: read %" PRIu32 " bytes at offset %" PRIu32 "\n",
size, offset);
Expand All @@ -83,19 +119,31 @@ static int mtd_sdcard_read_page(mtd_dev_t *dev, void *buff, uint32_t page,
#endif
}

#if IS_USED(MODULE_SDCARD_SPI)
sdcard_spi_read_blocks(mtd_sd->sd_card, page,
buff, SD_HC_BLOCK_SIZE,
size / SD_HC_BLOCK_SIZE, &err);
if (err != SD_RW_OK) {
DEBUG("mtd_sdcard_read_page: error %d\n", err);
return -EIO;
}
#elif IS_USED(MODULE_SDMMC)
int err = sdmmc_read_blocks(mtd_sd->sd_card, page, SDMMC_SDHC_BLOCK_SIZE,
size / SDMMC_SDHC_BLOCK_SIZE, buff, NULL);
if (err) {
DEBUG("mtd_sdcard_read_page: error %d\n", err);
return -EIO;
}
#endif
return size;
}

static int mtd_sdcard_write_page(mtd_dev_t *dev, const void *buff, uint32_t page,
uint32_t offset, uint32_t size)
{
#if IS_USED(MODULE_SDCARD_SPI)
sd_rw_response_t err;
#endif
mtd_sdcard_t *mtd_sd = (mtd_sdcard_t*)dev;

DEBUG("mtd_sdcard_write_page: page:%" PRIu32 " offset:%" PRIu32 " size:%" PRIu32 "\n",
Expand All @@ -108,24 +156,39 @@ static int mtd_sdcard_write_page(mtd_dev_t *dev, const void *buff, uint32_t page
return -ENOTSUP;
}

#if IS_USED(MODULE_SDCARD_SPI)
sdcard_spi_read_blocks(mtd_sd->sd_card, page,
dev->work_area, SD_HC_BLOCK_SIZE,
1, &err);
if (err != SD_RW_OK) {
return -EIO;
}

#elif IS_USED(MODULE_SDMMC)
if (sdmmc_read_blocks(mtd_sd->sd_card, page, SDMMC_SDHC_BLOCK_SIZE,
1, dev->work_area, NULL)) {
return -EIO;
}
#endif
size = MIN(size, SD_HC_BLOCK_SIZE - offset);
DEBUG("mtd_sdcard_write_page: write %" PRIu32 " bytes at offset %" PRIu32 "\n",
size, offset);
memcpy((uint8_t *)dev->work_area + offset, buff, size);
#if IS_USED(MODULE_SDCARD_SPI)
sdcard_spi_write_blocks(mtd_sd->sd_card, page,
dev->work_area, SD_HC_BLOCK_SIZE,
1, &err);
#elif IS_USED(MODULE_SDMMC)
if (sdmmc_write_blocks(mtd_sd->sd_card, page, SDMMC_SDHC_BLOCK_SIZE,
1, dev->work_area, NULL)) {
return -EIO;
}
#endif
#else
return -ENOTSUP;
#endif
} else {
}
#if IS_USED(MODULE_SDCARD_SPI)
else {
sdcard_spi_write_blocks(mtd_sd->sd_card, page,
buff, SD_HC_BLOCK_SIZE,
size / SD_HC_BLOCK_SIZE, &err);
Expand All @@ -135,6 +198,16 @@ static int mtd_sdcard_write_page(mtd_dev_t *dev, const void *buff, uint32_t page
DEBUG("mtd_sdcard_write_page: error %d\n", err);
return -EIO;
}
#elif IS_USED(MODULE_SDMMC)
else {
int err = sdmmc_write_blocks(mtd_sd->sd_card, page, SDMMC_SDHC_BLOCK_SIZE,
size / SDMMC_SDHC_BLOCK_SIZE, buff, NULL);
if (err) {
DEBUG("mtd_sdcard_write_page: error %d\n", err);
return -EIO;
}
}
#endif
return size;
}

Expand All @@ -152,6 +225,7 @@ static int mtd_sdcard_erase_sector(mtd_dev_t *dev, uint32_t sector, uint32_t cou
}
memset(dev->work_area, 0, SD_HC_BLOCK_SIZE);
while (count) {
#if IS_USED(MODULE_SDCARD_SPI)
sd_rw_response_t err;
sdcard_spi_write_blocks(mtd_sd->sd_card, sector,
dev->work_area, SD_HC_BLOCK_SIZE,
Expand All @@ -160,16 +234,29 @@ static int mtd_sdcard_erase_sector(mtd_dev_t *dev, uint32_t sector, uint32_t cou
DEBUG("mtd_sdcard_erase_sector: error %d\n", err);
return -EIO;
}
#elif IS_USED(MODULE_SDMMC)
if (sdmmc_write_blocks(mtd_sd->sd_card, sector, SDMMC_SDHC_BLOCK_SIZE,
1, dev->work_area, NULL)) {
return -EIO;
}
#endif
--count;
++sector;
}
#else
(void)dev;
(void)sector;
(void)count;
#if IS_USED(MODULE_SDMMC)
mtd_sdcard_t *mtd_sd = (mtd_sdcard_t*)dev;
if (IS_ACTIVE(CONFIG_MTD_SDCARD_ERASE)) {
return sdmmc_erase_blocks(mtd_sd->sd_card, sector, count);
}
#else
if (IS_ACTIVE(CONFIG_MTD_SDCARD_ERASE)) {
return -ENOTSUP;
}
#endif
#endif
return 0;
}
Expand Down Expand Up @@ -223,31 +310,47 @@ const mtd_desc_t mtd_sdcard_driver = {
};

#if IS_USED(MODULE_MTD_SDCARD_DEFAULT)
#include "sdcard_spi_params.h"
#include "vfs_default.h"

#define SDCARD_NUMOF ARRAY_SIZE(sdcard_spi_params)

#ifndef CONFIG_SDCARD_GENERIC_MTD_OFFSET
#define CONFIG_SDCARD_GENERIC_MTD_OFFSET 0
#endif

#if IS_USED(MODULE_SDCARD_SPI)
#include "sdcard_spi_params.h"

#define SDCARD_NUMOF ARRAY_SIZE(sdcard_spi_params)

/* this is provided by the sdcard_spi driver see drivers/sdcard_spi/sdcard_spi.c */
extern sdcard_spi_t sdcard_spi_devs[SDCARD_NUMOF];

#define MTD_SDCARD_DEV(n, m) \
mtd_sdcard_t mtd_sdcard_dev ## n = { \
mtd_sdcard_t mtd_sdcard_dev ##n = { \
.base = { \
.driver = &mtd_sdcard_driver, \
}, \
.sd_card = &sdcard_spi_devs[n], \
.params = &sdcard_spi_params[n] \
}; \
\
mtd_dev_t CONCAT(*mtd, m) = (mtd_dev_t *)&mtd_sdcard_dev ## n
mtd_dev_t CONCAT(*mtd, m) = (mtd_dev_t *)&mtd_sdcard_dev ##n

#define MTD_SDCARD_DEV_FS(n, m, filesystem) \
VFS_AUTO_MOUNT(filesystem, VFS_MTD(mtd_sdcard_dev ## n), VFS_DEFAULT_SD(n), m)
#elif IS_USED(MODULE_SDMMC)

/* this is provided by the sdcard_spi driver see drivers/sdcard_spi/sdcard_spi.c */
extern sdcard_spi_t sdcard_spi_devs[SDCARD_NUMOF];
#define MTD_SDCARD_DEV(n, m) \
mtd_sdcard_t mtd_sdcard_dev ##n = { \
.base = { \
.driver = &mtd_sdcard_driver, \
}, \
.sd_card_idx = n, \
}; \
\
mtd_dev_t CONCAT(*mtd, m) = (mtd_dev_t *)&mtd_sdcard_dev ##n

#endif /* IS_USED(MODULE_SDMMC) */

#define MTD_SDCARD_DEV_FS(n, m, filesystem) \
VFS_AUTO_MOUNT(filesystem, VFS_MTD(mtd_sdcard_dev ##n), VFS_DEFAULT_SD(n), m)

MTD_SDCARD_DEV(0, CONFIG_SDCARD_GENERIC_MTD_OFFSET);
#ifdef MODULE_FATFS_VFS
Expand Down

0 comments on commit 1c169e3

Please sign in to comment.