You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/12/13 19:35:37 UTC

[04/12] incubator-mynewt-core git commit: Add mmc read support - WIP

Add mmc read support - WIP


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/fed3a394
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/fed3a394
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/fed3a394

Branch: refs/heads/develop
Commit: fed3a394ca4bed73a94386bdc0b410ad082d5145
Parents: 163843f
Author: Fabio Utzig <ut...@utzig.org>
Authored: Thu Dec 1 23:54:56 2016 -0200
Committer: Fabio Utzig <ut...@utzig.org>
Committed: Thu Dec 8 22:00:32 2016 -0200

----------------------------------------------------------------------
 hw/drivers/mmc/include/mmc/mmc.h |  12 ++-
 hw/drivers/mmc/src/mmc.c         | 168 ++++++++++++++++++++++++++--------
 2 files changed, 142 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/fed3a394/hw/drivers/mmc/include/mmc/mmc.h
----------------------------------------------------------------------
diff --git a/hw/drivers/mmc/include/mmc/mmc.h b/hw/drivers/mmc/include/mmc/mmc.h
index 1a03edb..9c805ec 100644
--- a/hw/drivers/mmc/include/mmc/mmc.h
+++ b/hw/drivers/mmc/include/mmc/mmc.h
@@ -30,8 +30,10 @@ extern "C" {
  * MMC driver errors.
  */
 #define MMC_OK              (0)
-#define MMC_CARD_ERROR      (1)  /* Is there a card installed? */
-#define MMC_TIMEOUT         (2)
+#define MMC_CARD_ERROR      (-1)  /* Is there a card installed? */
+#define MMC_READ_ERROR      (-2)
+#define MMC_WRITE_ERROR     (-3)
+#define MMC_TIMEOUT         (-4)
 
 /**
  * Initialize the MMC driver
@@ -45,6 +47,12 @@ extern "C" {
 int
 mmc_init(int spi_num, void *spi_cfg, int ss_pin);
 
+int
+mmc_read(uint32_t addr, void *buf, size_t len);
+
+int
+mmc_write(uint32_t addr, void *buf, size_t len);
+
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/fed3a394/hw/drivers/mmc/src/mmc.c
----------------------------------------------------------------------
diff --git a/hw/drivers/mmc/src/mmc.c b/hw/drivers/mmc/src/mmc.c
index 6aefce4..be7f54c 100644
--- a/hw/drivers/mmc/src/mmc.c
+++ b/hw/drivers/mmc/src/mmc.c
@@ -24,10 +24,13 @@
 
 #include <stdio.h>
 
+#define MIN(n, m) (((n) < (m)) ? (n) : (m))
+
 /* Current used MMC commands */
 #define CMD0                (0)            /* GO_IDLE_STATE */
 #define CMD1                (1)            /* SEND_OP_COND (MMC) */
 #define CMD8                (8)            /* SEND_IF_COND */
+#define CMD12               (12)           /* STOP_TRANSMISSION */
 #define CMD16               (16)           /* SET_BLOCKLEN */
 #define CMD17               (17)           /* READ_SINGLE_BLOCK */
 #define CMD18               (18)           /* READ_MULTIPLE_BLOCK */
@@ -53,6 +56,10 @@
 #define R_ADDR_ERROR        (0x20)
 #define R_PARAM_ERROR       (0x40)
 
+#define BLOCK_LEN           (512)
+
+static uint8_t g_block_buf[BLOCK_LEN];
+
 static struct hal_spi_settings mmc_settings = {
     .data_order = HAL_SPI_MSB_FIRST,
     .data_mode  = HAL_SPI_MODE0,
@@ -89,31 +96,32 @@ ocr_from_r3(uint8_t *response)
 {
     uint32_t ocr;
 
-    ocr  = (uint32_t) response[4];
-    ocr |= (uint32_t) response[3] <<  8;
-    ocr |= (uint32_t) response[2] << 16;
-    ocr |= (uint32_t) response[1] << 24;
+    ocr  = (uint32_t) response[3];
+    ocr |= (uint32_t) response[2] <<  8;
+    ocr |= (uint32_t) response[1] << 16;
+    ocr |= (uint32_t) response[0] << 24;
 
-    return ocr;
-}
+#if 0
+    printf("Card supports: ");
+    if (ocr & (1 << 15)) {
+        printf("2.7-2.8 ");
+    }
+#endif
 
-static uint8_t
-status_from_r1(uint8_t *response)
-{
-    return response[0];
+    return ocr;
 }
 
 static uint8_t
 voltage_from_r7(uint8_t *response)
 {
-    return response[3] & 0xF;
+    return response[2] & 0xF;
 }
 
 static uint8_t
 send_mmc_cmd(uint8_t cmd, uint32_t payload)
 {
     int n;
-    uint8_t response[5];
+    uint8_t response[4];
     uint8_t status;
     uint8_t type;
 
@@ -122,8 +130,6 @@ send_mmc_cmd(uint8_t cmd, uint32_t payload)
         send_mmc_cmd(CMD55, 0);
     }
 
-    hal_gpio_write(g_ss_pin, 0);
-
     /* 4.7.2: Command Format */
     hal_spi_tx_val(g_spi_num, 0x40 | (cmd & ~0x80));
 
@@ -139,35 +145,36 @@ send_mmc_cmd(uint8_t cmd, uint32_t payload)
      *   NOTE: CRC can be turned on with CMD59 (CRC_ON_OFF).
      */
     if (cmd == CMD0) {
-        hal_spi_tx_val(g_spi_num, 0x95);
+        status = hal_spi_tx_val(g_spi_num, 0x95);
     } else if (cmd == CMD8) {
-        hal_spi_tx_val(g_spi_num, 0x87);
+        status = hal_spi_tx_val(g_spi_num, 0x87);
     } else {
         /* Any value is OK */
-        hal_spi_tx_val(g_spi_num, 0x01);
+        status = hal_spi_tx_val(g_spi_num, 0x01);
     }
 
     printf("=======================\n");
     printf("sending cmd %d\n", cmd & ~0x80);
 
-    status = 0xff;
     n = 10;
     do {
-        response[0] = (uint8_t) hal_spi_tx_val(g_spi_num, 0xff);
-    } while ((response[0] & 0x80) && --n);
+        status = hal_spi_tx_val(g_spi_num, 0xff);
+    } while ((status & 0x80) && --n);
 
     if (n) {
         type = response_type_by_cmd(cmd);
-        status = status_from_r1(response);
         printf("status=0x%x\n", status);
         if (!(type == R1 || status & R_ILLEGAL_COMMAND || status & R_CRC_ERROR)) {
             /* Read remaining data for this command */
-            for (n = 0; n < 4; n++) {
-                response[n+1] = (uint8_t) hal_spi_tx_val(g_spi_num, 0xff);
+            for (n = 0; n < sizeof(response); n++) {
+                response[n] = (uint8_t) hal_spi_tx_val(g_spi_num, 0xff);
             }
 
-            printf("response=[%0x][%0x][%0x][%0x]\n",
-                    response[1], response[2], response[3], response[4]);
+            printf("response=");
+            for (n = 0; n < sizeof(response); n++) {
+                printf("[%02x]", response[n]);
+            }
+            printf(" \n");
 
             switch (type) {
                 case R3:
@@ -179,12 +186,12 @@ send_mmc_cmd(uint8_t cmd, uint32_t payload)
                     break;
             }
         }
+    } else {
+        printf("status=%x, n=%d\n", status, n);
     }
 
     printf("\n");
 
-    hal_gpio_write(g_ss_pin, 1);
-
     return status;
 }
 
@@ -208,6 +215,7 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
     int i;
     uint8_t status;
     uint32_t ocr;
+    os_time_t wait_to;
 
     g_ss_pin = ss_pin;
     g_spi_num = spi_num;
@@ -238,20 +246,19 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
     /* give 10ms for VDD rampup */
     os_time_delay(OS_TICKS_PER_SEC / 100);
 
-    /* send the required >= 74 clock cycles */
     hal_gpio_write(g_ss_pin, 0);
 
+    /* send the required >= 74 clock cycles */
     for (i = 0; i < 74; i++) {
         hal_spi_tx_val(0, 0xff);
     }
 
-    hal_gpio_write(g_ss_pin, 1);
-
     /* put card in idle state */
     status = send_mmc_cmd(CMD0, 0);
 
     if (status != R_IDLE) {
         /* No card inserted or bad card! */
+        hal_gpio_write(g_ss_pin, 1);
         return mmc_error_by_status(status);
     }
 
@@ -272,21 +279,37 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
         if (ocr & R_ILLEGAL_COMMAND) {
 
         }
+
+        /* TODO: set blocklen */
+
     } else {
         /* Ver2.00 or later SD Memory Card */
 
         /* TODO:
          * 1) check CMD8 response pattern and voltage range.
-         * 2) send ACMD41 while in R_IDLE up to 1s.
+         * 2) DONE: send ACMD41 while in R_IDLE up to 1s.
          * 3) send CMD58, check CCS in response.
          */
 
-        status = send_mmc_cmd(ACMD41, 0);
+#define TIME_TO_WAIT (3 * OS_TICKS_PER_SEC)
+
+        wait_to = os_time_get() + TIME_TO_WAIT;
+        status = send_mmc_cmd(ACMD41, 0x40000000);
+
+        while (status & R_IDLE) {
+            if (os_time_get() > wait_to) {
+                break;
+            }
+            os_time_delay(OS_TICKS_PER_SEC / 10);
+            status = send_mmc_cmd(ACMD41, 0);
+        }
 
-        /* CCS = OCR[30] */
+        /* TODO: check CCS = OCR[30] */
         status = send_mmc_cmd(CMD58, 0);
     }
 
+    hal_gpio_write(g_ss_pin, 1);
+
     return rc;
 }
 
@@ -294,18 +317,91 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
  * @return 0 on success, non-zero on failure
  */
 int
-mmc_read(void *buf, size_t len)
+mmc_read(uint32_t addr, void *buf, size_t len)
 {
+    uint8_t cmd;
+    uint8_t res;
+    uint32_t n;
+    size_t block_len;
+    size_t block_count;
+    os_time_t timeout;
+    size_t block_addr;
+    size_t offset;
+    size_t index;
+    size_t amount;
+
     hal_gpio_write(g_ss_pin, 0);
+
+    block_len = (len + BLOCK_LEN - 1) & ~(BLOCK_LEN - 1);
+    block_count = block_len / BLOCK_LEN;
+    block_addr = addr / BLOCK_LEN;
+    offset = addr - (block_addr * BLOCK_LEN);
+
+    printf("block_addr=%d, offset=%d\n", block_addr, offset);
+    printf("block_len=%d, block_count=%d\n", block_len, block_count);
+
+    cmd = (block_count == 1) ? CMD17 : CMD18;
+    res = send_mmc_cmd(cmd, block_addr);
+    /* TODO: should be 0 */
+    printf("res=0x%x\n", res);
+
+    /* 7.3.3 Control tokens */
+
+    /* wait up to 1s (should be 200ms???) for control token */
+    timeout = os_time_get() + OS_TICKS_PER_SEC;
+    do {
+        res = hal_spi_tx_val(g_spi_num, 0xff);
+        if (res != 0xFF) {
+            break;
+        }
+        os_time_delay(OS_TICKS_PER_SEC / 20);
+    } while (os_time_get() < timeout);
+
+    printf("res=0x%x\n", res);
+    if (res == 0xFE) {
+        index = 0;
+        while (block_count--) {
+            /**
+             * FIXME: on last run doesn't need to transfer all BLOCK_LEN bytes!
+             */
+
+            for (n = 0; n < BLOCK_LEN; n++) {
+                g_block_buf[n] = hal_spi_tx_val(g_spi_num, 0xff);
+            }
+
+            /* consume CRC-16 */
+            hal_spi_tx_val(g_spi_num, 0xff);
+            hal_spi_tx_val(g_spi_num, 0xff);
+
+            amount = MIN(BLOCK_LEN - offset, len);
+
+            printf("copying %d bytes to index %d\n", amount, index);
+            memcpy(((uint8_t *)buf + index), &g_block_buf[offset], amount);
+
+            offset = 0;
+            len -= amount;
+            index += amount;
+        }
+
+        if (cmd == CMD18) {
+            send_mmc_cmd(CMD12, 0);
+        }
+
+        hal_gpio_write(g_ss_pin, 1);
+
+        return MMC_OK;
+    }
+
     hal_gpio_write(g_ss_pin, 1);
-    return 0;
+
+    return MMC_CARD_ERROR;
 }
 
 /**
  * @return 0 on success, non-zero on failure
  */
 int
-mmc_write(void *buf, size_t len)
+mmc_write(uint32_t addr, void *buf, size_t len)
 {
     return 0;
 }