From e5baef38100a7ebd1ce0508330bc7bb98541beb9 Mon Sep 17 00:00:00 2001
From: MichelRottleuthner <michel.rottleuthner@haw-hamburg.de>
Date: Wed, 9 Aug 2017 11:30:41 +0200
Subject: [PATCH] Merge pull request #7324 from MichelRottleuthner/sdcard_mtd

sdcard_spi: integrate to mtd interface
---
 drivers/Makefile.dep            |   5 ++
 drivers/include/mtd_sdcard.h    |  67 ++++++++++++++++++
 drivers/include/sdcard_spi.h    |   2 +-
 drivers/mtd_sdcard/Makefile     |   3 +
 drivers/mtd_sdcard/mtd_sdcard.c | 121 ++++++++++++++++++++++++++++++++
 drivers/sdcard_spi/sdcard_spi.c |  12 ++--
 6 files changed, 203 insertions(+), 7 deletions(-)
 create mode 100644 drivers/include/mtd_sdcard.h
 create mode 100644 drivers/mtd_sdcard/Makefile
 create mode 100644 drivers/mtd_sdcard/mtd_sdcard.c

diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep
index 801ea6bf7b..ecf77e0ffd 100644
--- a/drivers/Makefile.dep
+++ b/drivers/Makefile.dep
@@ -159,6 +159,11 @@ ifneq (,$(filter mpu9150,$(USEMODULE)))
     USEMODULE += xtimer
 endif
 
+ifneq (,$(filter mtd_sdcard,$(USEMODULE)))
+  USEMODULE += mtd
+  USEMODULE += sdcard_spi
+endif
+
 ifneq (,$(filter nrfmin,$(USEMODULE)))
     FEATURES_REQUIRED += radio_nrfmin
     FEATURES_REQUIRED += periph_cpuid
diff --git a/drivers/include/mtd_sdcard.h b/drivers/include/mtd_sdcard.h
new file mode 100644
index 0000000000..6b6388bd0c
--- /dev/null
+++ b/drivers/include/mtd_sdcard.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 HAW-Hamburg
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @defgroup    drivers_mtd_sdcard mtd wrapper for sdcard_spi
+ * @ingroup     drivers_storage
+ * @brief       Driver for SD-cards using mtd interface
+ *
+ * @{
+ *
+ * @file
+ * @brief       Interface definition for mtd_sdcard driver
+ *
+ * @author      Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
+ */
+
+#ifndef MTD_SDCARD_H
+#define MTD_SDCARD_H
+
+#include <stdint.h>
+
+#include "sdcard_spi.h"
+#include "mtd.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @brief Device descriptor for mtd_sdcard device
+ *
+ * This is an extension of the @c mtd_dev_t struct
+ */
+typedef struct {
+    mtd_dev_t base;                    /**< inherit from mtd_dev_t object */
+    sdcard_spi_t *sd_card;             /**< sdcard_spi dev descriptor */
+    const sdcard_spi_params_t *params; /**< params for sdcard_spi init */
+} mtd_sdcard_t;
+
+
+/**
+ * @brief sdcards handle sector erase internally so it's possible to directly
+ *        write to the card without erasing the sector first.
+ *        Attention: an erase call will therefore NOT touch the content,
+ *                   so disable this feature to ensure overriding the data.
+ */
+#ifndef MTD_SDCARD_SKIP_ERASE
+#define MTD_SDCARD_SKIP_ERASE (1)
+#endif
+
+/**
+ * @brief sdcard device operations table for mtd
+ */
+extern const mtd_desc_t mtd_sdcard_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MTD_SDCARD_H */
+/** @} */
diff --git a/drivers/include/sdcard_spi.h b/drivers/include/sdcard_spi.h
index c2ed3d3dde..bdafa4eeca 100644
--- a/drivers/include/sdcard_spi.h
+++ b/drivers/include/sdcard_spi.h
@@ -252,7 +252,7 @@ int sdcard_spi_read_blocks(sdcard_spi_t *card, int blockaddr, char *data, int bl
  *
  * @return                number of sucessfully written blocks (0 if no block was written).
  */
-int sdcard_spi_write_blocks(sdcard_spi_t *card, int blockaddr, char *data, int blocksize,
+int sdcard_spi_write_blocks(sdcard_spi_t *card, int blockaddr, const char *data, int blocksize,
                             int nblocks, sd_rw_response_t *state);
 
 /**
diff --git a/drivers/mtd_sdcard/Makefile b/drivers/mtd_sdcard/Makefile
new file mode 100644
index 0000000000..6b99904df0
--- /dev/null
+++ b/drivers/mtd_sdcard/Makefile
@@ -0,0 +1,3 @@
+MODULE = mtd_sdcard
+
+include $(RIOTBASE)/Makefile.base
diff --git a/drivers/mtd_sdcard/mtd_sdcard.c b/drivers/mtd_sdcard/mtd_sdcard.c
new file mode 100644
index 0000000000..80423e9124
--- /dev/null
+++ b/drivers/mtd_sdcard/mtd_sdcard.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2017 HAW-Hamburg
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ *
+ */
+
+/**
+ * @ingroup     drivers_mtd_sdcard
+ * @{
+ *
+ * @file
+ * @brief       Driver for using sdcard_spi via mtd interface
+ *
+ * @author      Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
+ *
+ * @}
+ */
+#define ENABLE_DEBUG (0)
+#include "debug.h"
+#include "mtd.h"
+#include "mtd_sdcard.h"
+#include "sdcard_spi.h"
+#include "sdcard_spi_internal.h"
+
+#include <stdint.h>
+#include <errno.h>
+
+static int mtd_sdcard_init(mtd_dev_t *mtd);
+static int mtd_sdcard_read(mtd_dev_t *mtd, void *dest, uint32_t addr,
+                           uint32_t size);
+static int mtd_sdcard_write(mtd_dev_t *mtd, const void *src, uint32_t addr,
+                            uint32_t size);
+static int mtd_sdcard_erase(mtd_dev_t *mtd, uint32_t addr, uint32_t size);
+static int mtd_sdcard_power(mtd_dev_t *mtd, enum mtd_power_state power);
+
+const mtd_desc_t mtd_sdcard_driver = {
+    .init = mtd_sdcard_init,
+    .read = mtd_sdcard_read,
+    .write = mtd_sdcard_write,
+    .erase = mtd_sdcard_erase,
+    .power = mtd_sdcard_power,
+};
+
+static int mtd_sdcard_init(mtd_dev_t *dev)
+{
+    DEBUG("mtd_sdcard_init\n");
+    mtd_sdcard_t *mtd_sd = (mtd_sdcard_t*)dev;
+    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
+           delete single blocks (i.e. pages) */
+        dev->pages_per_sector = 1;
+        dev->sector_count     = sdcard_spi_get_sector_count(mtd_sd->sd_card);
+
+        /* sdcard_spi always uses the fixed block size of SD-HC cards */
+        dev->page_size        = SD_HC_BLOCK_SIZE;
+        return 0;
+    }
+    return -EIO;
+}
+
+static int mtd_sdcard_read(mtd_dev_t *dev, void *buff, uint32_t addr,
+                           uint32_t size)
+{
+    DEBUG("mtd_sdcard_read: addr:%lu size:%lu\n", addr, size);
+    mtd_sdcard_t *mtd_sd = (mtd_sdcard_t*)dev;
+    sd_rw_response_t err;
+    int res = sdcard_spi_read_blocks(mtd_sd->sd_card, addr / SD_HC_BLOCK_SIZE,
+                                     buff, SD_HC_BLOCK_SIZE,
+                                     size / SD_HC_BLOCK_SIZE, &err);
+
+    if (err == SD_RW_OK) {
+        return res * SD_HC_BLOCK_SIZE;
+    }
+    return -EIO;
+}
+
+static int mtd_sdcard_write(mtd_dev_t *dev, const void *buff, uint32_t addr,
+                            uint32_t size)
+{
+    DEBUG("mtd_sdcard_write: addr:%lu size:%lu\n", addr, size);
+    mtd_sdcard_t *mtd_sd = (mtd_sdcard_t*)dev;
+    sd_rw_response_t err;
+    int res = sdcard_spi_write_blocks(mtd_sd->sd_card, addr / SD_HC_BLOCK_SIZE,
+                                      buff, SD_HC_BLOCK_SIZE,
+                                      size / SD_HC_BLOCK_SIZE, &err);
+
+    if (err == SD_RW_OK) {
+        return res * SD_HC_BLOCK_SIZE;
+    }
+    return -EIO;
+}
+
+static int mtd_sdcard_erase(mtd_dev_t *dev,
+                            uint32_t addr,
+                            uint32_t size)
+{
+    DEBUG("mtd_sdcard_erase: addr:%lu size:%lu\n", addr, size);
+    (void)dev;
+    (void)addr;
+    (void)size;
+
+#if MTD_SDCARD_SKIP_ERASE == 1
+    return 0;
+#else
+    return -ENOTSUP; /* explicit erase currently not supported */
+#endif
+}
+
+static int mtd_sdcard_power(mtd_dev_t *dev, enum mtd_power_state power)
+{
+    (void)dev;
+    (void)power;
+
+    /* TODO: implement power down of sdcard in sdcard_spi
+    (make use of sdcard_spi_params_t.power pin) */
+    return -ENOTSUP; /* currently not supported */
+}
diff --git a/drivers/sdcard_spi/sdcard_spi.c b/drivers/sdcard_spi/sdcard_spi.c
index 7eabda4daf..82a6084583 100644
--- a/drivers/sdcard_spi/sdcard_spi.c
+++ b/drivers/sdcard_spi/sdcard_spi.c
@@ -40,7 +40,7 @@ static sd_init_fsm_state_t _init_sd_fsm_step(sdcard_spi_t *card, sd_init_fsm_sta
 static sd_rw_response_t _read_cid(sdcard_spi_t *card);
 static sd_rw_response_t _read_csd(sdcard_spi_t *card);
 static sd_rw_response_t _read_data_packet(sdcard_spi_t *card, char token, char *data, int size);
-static sd_rw_response_t _write_data_packet(sdcard_spi_t *card, char token, char *data, int size);
+static sd_rw_response_t _write_data_packet(sdcard_spi_t *card, char token, const char *data, int size);
 
 /* CRC-7 (polynomial: x^7 + x^3 + 1) LSB of CRC-7 in a 8-bit variable is always 1*/
 static char _crc_7(const char *data, int n);
@@ -49,7 +49,7 @@ static char _crc_7(const char *data, int n);
 static uint16_t _crc_16(const char *data, size_t n);
 
 /* use this transfer method instead of _transfer_bytes to force the use of 0xFF as dummy bytes */
-static inline int _transfer_bytes(sdcard_spi_t *card, char *out, char *in, unsigned int length);
+static inline int _transfer_bytes(sdcard_spi_t *card, const char *out, char *in, unsigned int length);
 
 /* uses bitbanging for spi communication which allows to enable pull-up on the miso pin for
 greater card compatibility on platforms that don't have a hw pull up installed */
@@ -576,7 +576,7 @@ static inline int _hw_spi_rxtx_byte(sdcard_spi_t *card, char out, char *in){
     return 1;
 }
 
-static inline int _transfer_bytes(sdcard_spi_t *card, char *out, char *in, unsigned int length){
+static inline int _transfer_bytes(sdcard_spi_t *card, const char *out, char *in, unsigned int length){
     int trans_ret;
     unsigned trans_bytes = 0;
     char in_temp;
@@ -703,7 +703,7 @@ int sdcard_spi_read_blocks(sdcard_spi_t *card, int blockaddr, char *data, int bl
     }
 }
 
-static sd_rw_response_t _write_data_packet(sdcard_spi_t *card, char token, char *data, int size)
+static sd_rw_response_t _write_data_packet(sdcard_spi_t *card, char token, const char *data, int size)
 {
 
     spi_transfer_byte(card->params.spi_dev, GPIO_UNDEF, true, token);
@@ -758,7 +758,7 @@ static sd_rw_response_t _write_data_packet(sdcard_spi_t *card, char token, char
     }
 }
 
-static inline int _write_blocks(sdcard_spi_t *card, char cmd_idx, int bladdr, char *data, int blsz,
+static inline int _write_blocks(sdcard_spi_t *card, char cmd_idx, int bladdr, const char *data, int blsz,
                                 int nbl, sd_rw_response_t *state)
 {
     _select_card_spi(card);
@@ -823,7 +823,7 @@ static inline int _write_blocks(sdcard_spi_t *card, char cmd_idx, int bladdr, ch
     }
 }
 
-int sdcard_spi_write_blocks(sdcard_spi_t *card, int blockaddr, char *data, int blocksize,
+int sdcard_spi_write_blocks(sdcard_spi_t *card, int blockaddr, const char *data, int blocksize,
                             int nblocks, sd_rw_response_t *state)
 {
     if (nblocks > 1) {
-- 
GitLab