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:34 UTC

[01/12] incubator-mynewt-core git commit: Misc fixes + fix multi-block read

Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/develop 1caa49235 -> d19cb51b0


Misc fixes + fix multi-block read


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/17e7f9c1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/17e7f9c1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/17e7f9c1

Branch: refs/heads/develop
Commit: 17e7f9c1b11b7825ad7546063c2daee3ec542b88
Parents: 2d89fc4
Author: Fabio Utzig <ut...@utzig.org>
Authored: Thu Dec 8 21:55:01 2016 -0200
Committer: Fabio Utzig <ut...@utzig.org>
Committed: Thu Dec 8 22:00:32 2016 -0200

----------------------------------------------------------------------
 hw/drivers/mmc/src/mmc.c | 114 +++++++++++++++++++++---------------------
 1 file changed, 58 insertions(+), 56 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/17e7f9c1/hw/drivers/mmc/src/mmc.c
----------------------------------------------------------------------
diff --git a/hw/drivers/mmc/src/mmc.c b/hw/drivers/mmc/src/mmc.c
index 8b30929..f0fe71d 100644
--- a/hw/drivers/mmc/src/mmc.c
+++ b/hw/drivers/mmc/src/mmc.c
@@ -71,7 +71,7 @@ static struct hal_spi_settings mmc_settings = {
     .word_size  = HAL_SPI_WORD_SIZE_8BIT,
 };
 
-/* FIXME: this limits usage to single MMC spi device */
+/* FIXME: currently limited to single MMC spi device */
 static struct mmc_cfg {
     int                      spi_num;
     int                      ss_pin;
@@ -84,6 +84,8 @@ mmc_error_by_status(uint8_t status)
 {
     if (status == 0) {
         return MMC_OK;
+    } else if (status == 0xff) {
+        return MMC_CARD_ERROR;
     } else if (status & R_IDLE) {
         return MMC_TIMEOUT;
     } else if (status & R_ERASE_RESET) {
@@ -156,11 +158,6 @@ send_mmc_cmd(struct mmc_cfg *mmc, uint8_t cmd, uint32_t payload)
     for (n = 255; n > 0; n--) {
         status = hal_spi_tx_val(mmc->spi_num, 0xff);
         if ((status & 0x80) == 0) break;
-        //os_time_delay(OS_TICKS_PER_SEC / 1000);
-    }
-
-    if (n == 0) {
-        return status;
     }
 
     return status;
@@ -223,7 +220,6 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
     os_time_delay(OS_TICKS_PER_SEC / 100);
 
     hal_gpio_write(mmc->ss_pin, 0);
-    hal_spi_tx_val(mmc->spi_num, 0xff);
 
     /* send the required >= 74 clock cycles */
     for (i = 0; i < 74; i++) {
@@ -246,29 +242,18 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
      *       will answer this with R_ILLEGAL_COMMAND.
      */
     status = send_mmc_cmd(mmc, CMD8, 0x1AA);
-    for (i = 0; i < 4; i++) {
-        cmd_resp[i] = (uint8_t) hal_spi_tx_val(mmc->spi_num, 0xff);
-    }
-
-    if (status & R_ILLEGAL_COMMAND) {
-        /* Ver1.x SD Memory Card or Not SD Memory Card */
-
-        ocr = send_mmc_cmd(mmc, CMD58, 0);
-
-        /* TODO: check if voltage range is ok! */
-
-        if (ocr & R_ILLEGAL_COMMAND) {
-
-        }
-
-        /* TODO: set blocklen */
-
-    } else {
+    if (status != 0xff && !(status & R_ILLEGAL_COMMAND)) {
 
         /**
          * Ver2.00 or later SD Memory Card
          */
 
+        /* Read the contents of R7 */
+        for (i = 0; i < 4; i++) {
+            cmd_resp[i] = (uint8_t) hal_spi_tx_val(mmc->spi_num, 0xff);
+        }
+
+        /* Did the card return the same pattern? */
         if (cmd_resp[3] != 0xAA) {
             rc = MMC_RESPONSE_ERROR;
             goto out;
@@ -323,6 +308,24 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
     }
 #endif
 
+    } else if (status != 0xff && status & R_ILLEGAL_COMMAND) {
+
+        /**
+         * Ver1.x SD Memory Card or Not SD Memory Card
+         */
+
+        ocr = send_mmc_cmd(mmc, CMD58, 0);
+
+        /* TODO: check if voltage range is ok! */
+
+        if (ocr & R_ILLEGAL_COMMAND) {
+
+        }
+
+        /* TODO: set blocklen */
+
+    } else {
+        rc = mmc_error_by_status(status);
     }
 
 out:
@@ -338,6 +341,7 @@ mmc_read(uint8_t mmc_id, uint32_t addr, void *buf, size_t len)
 {
     uint8_t cmd;
     uint8_t res;
+    int rc;
     uint32_t n;
     size_t block_len;
     size_t block_count;
@@ -353,6 +357,8 @@ mmc_read(uint8_t mmc_id, uint32_t addr, void *buf, size_t len)
         return (MMC_DEVICE_ERROR);
     }
 
+    rc = MMC_OK;
+
     block_len = (len + BLOCK_LEN - 1) & ~(BLOCK_LEN - 1);
     block_count = block_len / BLOCK_LEN;
     block_addr = addr / BLOCK_LEN;
@@ -365,9 +371,9 @@ mmc_read(uint8_t mmc_id, uint32_t addr, void *buf, size_t len)
 
     cmd = (block_count == 1) ? CMD17 : CMD18;
     res = send_mmc_cmd(mmc, cmd, block_addr);
-    if (res != MMC_OK) {
-        hal_gpio_write(mmc->ss_pin, 1);
-        return (MMC_CARD_ERROR);
+    if (res) {
+        rc = mmc_error_by_status(res);
+        goto out;
     }
 
     /**
@@ -384,43 +390,39 @@ mmc_read(uint8_t mmc_id, uint32_t addr, void *buf, size_t len)
     /**
      * 7.3.3.2 Start Block Tokens and Stop Tran Token
      */
-    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(mmc->spi_num, 0xff);
-            }
-
-            /* FIXME: consume CRC-16, but should check */
-            hal_spi_tx_val(mmc->spi_num, 0xff);
-            hal_spi_tx_val(mmc->spi_num, 0xff);
+    if (res != 0xFE) {
+        rc = MMC_TIMEOUT;
+        goto out;
+    }
 
-            amount = MIN(BLOCK_LEN - offset, len);
+    index = 0;
+    while (block_count--) {
+        for (n = 0; n < BLOCK_LEN; n++) {
+            g_block_buf[n] = hal_spi_tx_val(mmc->spi_num, 0xff);
+        }
 
-            //printf("copying %d bytes to index %d\n", amount, index);
-            memcpy(((uint8_t *)buf + index), &g_block_buf[offset], amount);
+        /* TODO: CRC-16 not used here but would be cool to have */
+        hal_spi_tx_val(mmc->spi_num, 0xff);
+        hal_spi_tx_val(mmc->spi_num, 0xff);
 
-            offset = 0;
-            len -= amount;
-            index += amount;
-        }
+        amount = MIN(BLOCK_LEN - offset, len);
 
-        if (cmd == CMD18) {
-            send_mmc_cmd(mmc, CMD12, 0);  /* FIXME */
-        }
+        memcpy(((uint8_t *)buf + index), &g_block_buf[offset], amount);
 
-        hal_gpio_write(mmc->ss_pin, 1);
+        offset = 0;
+        len -= amount;
+        index += amount;
+    }
 
-        return MMC_OK;
+    if (cmd == CMD18) {
+        send_mmc_cmd(mmc, CMD12, 0);
+        /* FIXME: sending extra cycle to wait for stop, need to loop here? */
+        hal_spi_tx_val(mmc->spi_num, 0xff);
     }
 
+out:
     hal_gpio_write(mmc->ss_pin, 1);
-
-    return MMC_CARD_ERROR;
+    return (rc);
 }
 
 /**


[06/12] incubator-mynewt-core git commit: Add write support - WIP

Posted by cc...@apache.org.
Add write 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/f4aaf683
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/f4aaf683
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/f4aaf683

Branch: refs/heads/develop
Commit: f4aaf6837f7cbf002a1d9fc7a119e706c138bdf8
Parents: fed3a39
Author: Fabio Utzig <ut...@utzig.org>
Authored: Mon Dec 5 15:15:14 2016 -0200
Committer: Fabio Utzig <ut...@utzig.org>
Committed: Thu Dec 8 22:00:32 2016 -0200

----------------------------------------------------------------------
 hw/drivers/mmc/include/mmc/mmc.h |  20 +++
 hw/drivers/mmc/src/mmc.c         | 234 +++++++++++++++++++++++++++-------
 2 files changed, 205 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f4aaf683/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 9c805ec..add9b9b 100644
--- a/hw/drivers/mmc/include/mmc/mmc.h
+++ b/hw/drivers/mmc/include/mmc/mmc.h
@@ -34,6 +34,8 @@ extern "C" {
 #define MMC_READ_ERROR      (-2)
 #define MMC_WRITE_ERROR     (-3)
 #define MMC_TIMEOUT         (-4)
+#define MMC_PARAM           (-5)
+#define MMC_CRC_ERROR       (-6)
 
 /**
  * Initialize the MMC driver
@@ -47,9 +49,27 @@ extern "C" {
 int
 mmc_init(int spi_num, void *spi_cfg, int ss_pin);
 
+/**
+ * Read data from MMC
+ *
+ * @param addr
+ * @param buf
+ * @param len
+ *
+ * @return 0 on success, non-zero on failure
+ */
 int
 mmc_read(uint32_t addr, void *buf, size_t len);
 
+/**
+ * Write data to the MMC
+ *
+ * @param addr
+ * @param buf
+ * @param len
+ *
+ * @return 0 on success, non-zero on failure
+ */
 int
 mmc_write(uint32_t addr, void *buf, size_t len);
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f4aaf683/hw/drivers/mmc/src/mmc.c
----------------------------------------------------------------------
diff --git a/hw/drivers/mmc/src/mmc.c b/hw/drivers/mmc/src/mmc.c
index be7f54c..92acc45 100644
--- a/hw/drivers/mmc/src/mmc.c
+++ b/hw/drivers/mmc/src/mmc.c
@@ -26,7 +26,7 @@
 
 #define MIN(n, m) (((n) < (m)) ? (n) : (m))
 
-/* Current used MMC commands */
+/* Currently used MMC commands */
 #define CMD0                (0)            /* GO_IDLE_STATE */
 #define CMD1                (1)            /* SEND_OP_COND (MMC) */
 #define CMD8                (8)            /* SEND_IF_COND */
@@ -68,6 +68,7 @@ static struct hal_spi_settings mmc_settings = {
     .word_size  = HAL_SPI_WORD_SIZE_8BIT,
 };
 
+/* FIXME: this limits usage to single MMC spi device */
 static int g_spi_num = -1;
 static int g_ss_pin = -1;
 
@@ -78,6 +79,18 @@ static int g_ss_pin = -1;
 static int
 mmc_error_by_status(uint8_t status)
 {
+    if (status == 0xff) {
+        return MMC_CARD_ERROR;
+    } else if (status & R_IDLE) {
+        return MMC_TIMEOUT;
+    } else if (status & R_ERASE_RESET) {
+    } else if (status & R_ILLEGAL_COMMAND) {
+    } else if (status & R_CRC_ERROR) {
+    } else if (status & R_ERASE_ERROR) {
+    } else if (status & R_ADDR_ERROR) {
+    } else if (status & R_PARAM_ERROR) {
+    }
+
     return MMC_OK;
 }
 
@@ -145,52 +158,57 @@ send_mmc_cmd(uint8_t cmd, uint32_t payload)
      *   NOTE: CRC can be turned on with CMD59 (CRC_ON_OFF).
      */
     if (cmd == CMD0) {
-        status = hal_spi_tx_val(g_spi_num, 0x95);
+        hal_spi_tx_val(g_spi_num, 0x95);
     } else if (cmd == CMD8) {
-        status = hal_spi_tx_val(g_spi_num, 0x87);
+        hal_spi_tx_val(g_spi_num, 0x87);
     } else {
-        /* Any value is OK */
-        status = hal_spi_tx_val(g_spi_num, 0x01);
+        /* Any CRC value is OK here */
+        hal_spi_tx_val(g_spi_num, 0x01);
     }
 
-    printf("=======================\n");
-    printf("sending cmd %d\n", cmd & ~0x80);
+    //printf("==> sending cmd %d\n", cmd & ~0x80);
 
     n = 10;
     do {
         status = hal_spi_tx_val(g_spi_num, 0xff);
     } while ((status & 0x80) && --n);
 
-    if (n) {
-        type = response_type_by_cmd(cmd);
-        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 < sizeof(response); n++) {
-                response[n] = (uint8_t) hal_spi_tx_val(g_spi_num, 0xff);
-            }
+    if (!n) {
+        return status;
+    }
 
-            printf("response=");
-            for (n = 0; n < sizeof(response); n++) {
-                printf("[%02x]", response[n]);
-            }
-            printf(" \n");
-
-            switch (type) {
-                case R3:
-                    /* NOTE: ocr is defined in section 5.1 */
-                    printf("ocr=0x%08lx\n", ocr_from_r3(response));
-                    break;
-                case R7:
-                    printf("voltage=0x%x\n", voltage_from_r7(response));
-                    break;
-            }
+    type = response_type_by_cmd(cmd);
+
+    /* FIXME:
+     *       R1 and R1b don't have extra payload
+     *       R2 has extra status byte
+     *       R3 has 4 extra bytes for OCR
+     *       R7 has 4 extra bytes with pattern, voltage, etc
+     */
+    if (!(type == R1 || status & R_ILLEGAL_COMMAND || status & R_CRC_ERROR)) {
+        /* Read remaining data for this command */
+        for (n = 0; n < sizeof(response); n++) {
+            response[n] = (uint8_t) hal_spi_tx_val(g_spi_num, 0xff);
         }
-    } else {
-        printf("status=%x, n=%d\n", status, n);
-    }
 
-    printf("\n");
+#if 0
+        printf("response=");
+        for (n = 0; n < sizeof(response); n++) {
+            printf("[%02x]", response[n]);
+        }
+        printf(" \n");
+#endif
+
+        switch (type) {
+            case R3:
+                /* NOTE: ocr is defined in section 5.1 */
+                printf("ocr=0x%08lx\n", ocr_from_r3(response));
+                break;
+            case R7:
+                printf("voltage=0x%x\n", voltage_from_r7(response));
+                break;
+        }
+    }
 
     return status;
 }
@@ -294,7 +312,7 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
 #define TIME_TO_WAIT (3 * OS_TICKS_PER_SEC)
 
         wait_to = os_time_get() + TIME_TO_WAIT;
-        status = send_mmc_cmd(ACMD41, 0x40000000);
+        status = send_mmc_cmd(ACMD41, 0x40000000); /* FIXME */
 
         while (status & R_IDLE) {
             if (os_time_get() > wait_to) {
@@ -337,27 +355,30 @@ mmc_read(uint32_t addr, void *buf, size_t 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);
+    //printf("block_addr=%d, offset=%d\n", block_addr, offset);
+    //printf("len=%d, block_len=%d, block_count=%d\n", len, 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 */
+    if (res != MMC_OK) {
+        hal_gpio_write(g_ss_pin, 1);
+        return MMC_CARD_ERROR;
+    }
 
-    /* wait up to 1s (should be 200ms???) for control token */
-    timeout = os_time_get() + OS_TICKS_PER_SEC;
+    /**
+     * 7.3.3 Control tokens
+     *   Wait up to 200ms for control token.
+     */
+    timeout = os_time_get() + OS_TICKS_PER_SEC / 5;
     do {
         res = hal_spi_tx_val(g_spi_num, 0xff);
-        if (res != 0xFF) {
-            break;
-        }
+        if (res != 0xFF) break;
         os_time_delay(OS_TICKS_PER_SEC / 20);
     } while (os_time_get() < timeout);
 
-    printf("res=0x%x\n", res);
+    /**
+     * 7.3.3.2 Start Block Tokens and Stop Tran Token
+     */
     if (res == 0xFE) {
         index = 0;
         while (block_count--) {
@@ -369,7 +390,7 @@ mmc_read(uint32_t addr, void *buf, size_t len)
                 g_block_buf[n] = hal_spi_tx_val(g_spi_num, 0xff);
             }
 
-            /* consume CRC-16 */
+            /* FIXME: consume CRC-16, but should check */
             hal_spi_tx_val(g_spi_num, 0xff);
             hal_spi_tx_val(g_spi_num, 0xff);
 
@@ -403,5 +424,120 @@ mmc_read(uint32_t addr, void *buf, size_t len)
 int
 mmc_write(uint32_t addr, void *buf, size_t len)
 {
-    return 0;
+    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;
+
+    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);
+
+    if (offset) {
+        res = send_mmc_cmd(CMD17, block_addr);
+        if (res != MMC_OK) {
+            hal_gpio_write(g_ss_pin, 1);
+            return MMC_CARD_ERROR;
+        }
+
+        timeout = os_time_get() + OS_TICKS_PER_SEC / 5;
+        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);
+
+        if (res != 0xFE) {
+            hal_gpio_write(g_ss_pin, 1);
+            return MMC_CARD_ERROR;
+        }
+
+        for (n = 0; n < BLOCK_LEN; n++) {
+            g_block_buf[n] = hal_spi_tx_val(g_spi_num, 0xff);
+        }
+
+        hal_spi_tx_val(g_spi_num, 0xff);
+        hal_spi_tx_val(g_spi_num, 0xff);
+    }
+
+    /* now start write */
+
+    cmd = (block_count == 1) ? CMD24 : CMD25;
+    res = send_mmc_cmd(cmd, block_addr);
+    if (res != MMC_OK) {
+        hal_gpio_write(g_ss_pin, 1);
+        return MMC_CARD_ERROR;
+    }
+
+    /**
+     * 7.3.3 Control tokens
+     *   Wait up to 500ms for control token.
+     */
+    timeout = os_time_get() + OS_TICKS_PER_SEC / 2;
+    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);
+
+    if (res == 0xFF) {
+        hal_gpio_write(g_ss_pin, 1);
+        return MMC_CARD_ERROR;
+    }
+
+    index = 0;
+    do {
+        /* FIXME: must wait for ready here? */
+
+        /**
+         * 7.3.3.2 Start Block Tokens and Stop Tran Token
+         */
+        if (cmd == CMD24) {
+            hal_spi_tx_val(g_spi_num, 0xFE);
+        } else {
+            hal_spi_tx_val(g_spi_num, 0xFC);
+        }
+
+        amount = MIN(BLOCK_LEN - offset, len);
+        memcpy(&g_block_buf[offset], ((uint8_t *)buf + index), amount);
+
+        for (n = 0; n < BLOCK_LEN; n++) {
+            hal_spi_tx_val(g_spi_num, g_block_buf[n]);
+        }
+
+        /* CRC */
+        hal_spi_tx_val(g_spi_num, 0xff);
+        hal_spi_tx_val(g_spi_num, 0xff);
+
+        /**
+         * 7.3.3.1 Data Response Token
+         */
+        res = hal_spi_tx_val(g_spi_num, 0xff);
+        if ((res & 0x1f) != 0x05) {
+            break;
+        }
+
+        offset = 0;
+        len -= amount;
+        index += amount;
+
+    } while (len);
+
+    hal_gpio_write(g_ss_pin, 1);
+
+    res &= 0x1f;
+    if (res == 0x0b) {
+        return MMC_CRC_ERROR;
+    } else if (res == 0x0d) {
+        return MMC_WRITE_ERROR;
+    }
+
+    return MMC_OK;
 }


[05/12] incubator-mynewt-core git commit: Initial bare support for multiple MMC

Posted by cc...@apache.org.
Initial bare support for multiple MMC


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/b4040d76
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/b4040d76
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/b4040d76

Branch: refs/heads/develop
Commit: b4040d76bf058777c6d0e150d5183fa9a7fed65e
Parents: 70bbb74
Author: Fabio Utzig <ut...@utzig.org>
Authored: Tue Dec 6 21:48:53 2016 -0200
Committer: Fabio Utzig <ut...@utzig.org>
Committed: Thu Dec 8 22:00:32 2016 -0200

----------------------------------------------------------------------
 hw/drivers/mmc/include/mmc/mmc.h |  13 ++-
 hw/drivers/mmc/src/mmc.c         | 187 +++++++++++++++++++---------------
 2 files changed, 115 insertions(+), 85 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b4040d76/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 c9b03af..2f434ef 100644
--- a/hw/drivers/mmc/include/mmc/mmc.h
+++ b/hw/drivers/mmc/include/mmc/mmc.h
@@ -34,15 +34,16 @@ extern "C" {
 #define MMC_READ_ERROR      (-2)
 #define MMC_WRITE_ERROR     (-3)
 #define MMC_TIMEOUT         (-4)
-#define MMC_PARAM           (-5)
+#define MMC_PARAM_ERROR     (-5)
 #define MMC_CRC_ERROR       (-6)
+#define MMC_DEVICE_ERROR    (-7)
 
 /**
  * Initialize the MMC driver
  *
  * @param spi_num Number of the SPI channel to be used by MMC
  * @param spi_cfg Low-level device specific SPI configuration
- * @param ss_pin Number of SS pin if SW controlled, -1 otherwise
+ * @param ss_pin GPIO number of the SS pin
  *
  * @return 0 on success, non-zero on failure
  */
@@ -52,6 +53,7 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin);
 /**
  * Read data from MMC
  *
+ * @param mmc_id
  * @param addr
  * @param buf
  * @param len
@@ -59,11 +61,12 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin);
  * @return 0 on success, non-zero on failure
  */
 int
-mmc_read(uint32_t addr, void *buf, size_t len);
+mmc_read(uint8_t mmc_id, uint32_t addr, void *buf, size_t len);
 
 /**
  * Write data to the MMC
  *
+ * @param mmc_id
  * @param addr
  * @param buf
  * @param len
@@ -71,10 +74,10 @@ mmc_read(uint32_t addr, void *buf, size_t len);
  * @return 0 on success, non-zero on failure
  */
 int
-mmc_write(uint32_t addr, const void *buf, size_t len);
+mmc_write(uint8_t mmc_id, uint32_t addr, const void *buf, size_t len);
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* __ADC_H__ */
+#endif /* __MMC_H__ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b4040d76/hw/drivers/mmc/src/mmc.c
----------------------------------------------------------------------
diff --git a/hw/drivers/mmc/src/mmc.c b/hw/drivers/mmc/src/mmc.c
index d6e4a0d..199b201 100644
--- a/hw/drivers/mmc/src/mmc.c
+++ b/hw/drivers/mmc/src/mmc.c
@@ -64,17 +64,18 @@ static struct hal_spi_settings mmc_settings = {
     .data_order = HAL_SPI_MSB_FIRST,
     .data_mode  = HAL_SPI_MODE0,
     /* XXX: MMC initialization accepts clocks in the range 100-400KHz */
+    /* TODO: switch to high-speed aka 25MHz after initialization. */
     .baudrate   = 100,
     .word_size  = HAL_SPI_WORD_SIZE_8BIT,
 };
 
 /* FIXME: this limits usage to single MMC spi device */
-static int g_spi_num = -1;
-static int g_ss_pin = -1;
-
-/**
- * TODO: switch to high-speed SPI after initialization.
- */
+static struct mmc_cfg {
+    int                      spi_num;
+    int                      ss_pin;
+    void                     *spi_cfg;
+    struct hal_spi_settings  *settings;
+} g_mmc_cfg;
 
 static int
 mmc_error_by_status(uint8_t status)
@@ -132,26 +133,38 @@ voltage_from_r7(uint8_t *response)
 }
 */
 
+static struct mmc_cfg *
+mmc_cfg_dev(uint8_t id)
+{
+    if (id != 0) {
+        return NULL;
+    }
+
+    return &g_mmc_cfg;
+}
+
 static uint8_t
-send_mmc_cmd(uint8_t cmd, uint32_t payload)
+send_mmc_cmd(struct mmc_cfg *mmc, uint8_t cmd, uint32_t payload)
 {
     int n;
     uint8_t response[4];
     uint8_t status;
     uint8_t type;
+    uint8_t crc;
 
     if (cmd & 0x80) {
         /* TODO: refactor recursion? */
-        send_mmc_cmd(CMD55, 0);
+        /* TODO: error checking */
+        send_mmc_cmd(mmc, CMD55, 0);
     }
 
     /* 4.7.2: Command Format */
-    hal_spi_tx_val(g_spi_num, 0x40 | (cmd & ~0x80));
+    hal_spi_tx_val(mmc->spi_num, 0x40 | (cmd & ~0x80));
 
-    hal_spi_tx_val(g_spi_num, payload >> 24 & 0xff);
-    hal_spi_tx_val(g_spi_num, payload >> 16 & 0xff);
-    hal_spi_tx_val(g_spi_num, payload >>  8 & 0xff);
-    hal_spi_tx_val(g_spi_num, payload       & 0xff);
+    hal_spi_tx_val(mmc->spi_num, payload >> 24 & 0xff);
+    hal_spi_tx_val(mmc->spi_num, payload >> 16 & 0xff);
+    hal_spi_tx_val(mmc->spi_num, payload >>  8 & 0xff);
+    hal_spi_tx_val(mmc->spi_num, payload       & 0xff);
 
     /**
      * 7.2.2 Bus Transfer Protection
@@ -159,19 +172,21 @@ send_mmc_cmd(uint8_t cmd, uint32_t payload)
      *   require a valid CRC.
      *   NOTE: CRC can be turned on with CMD59 (CRC_ON_OFF).
      */
-    if (cmd == CMD0) {
-        hal_spi_tx_val(g_spi_num, 0x95);
-    } else if (cmd == CMD8) {
-        hal_spi_tx_val(g_spi_num, 0x87);
-    } else {
-        /* Any CRC value is OK here */
-        hal_spi_tx_val(g_spi_num, 0x01);
+    crc = 0x01;
+    switch (cmd) {
+        case CMD0:
+            crc = 0x95;
+            break;
+        case CMD8:
+            crc = 0x87;
+            break;
     }
+    hal_spi_tx_val(mmc->spi_num, crc);
 
     //printf("==> sending cmd %d\n", cmd & ~0x80);
 
     for (n = 255; n > 0; n--) {
-        status = hal_spi_tx_val(g_spi_num, 0xff);
+        status = hal_spi_tx_val(mmc->spi_num, 0xff);
         if ((status & 0x80) == 0) break;
         //os_time_delay(OS_TICKS_PER_SEC / 1000);
     }
@@ -191,7 +206,7 @@ send_mmc_cmd(uint8_t cmd, uint32_t payload)
     if (!(type == R1 || status & R_ILLEGAL_COMMAND || status & R_CRC_ERROR)) {
         /* Read remaining data for this command */
         for (n = 0; n < sizeof(response); n++) {
-            response[n] = (uint8_t) hal_spi_tx_val(g_spi_num, 0xff);
+            response[n] = (uint8_t) hal_spi_tx_val(mmc->spi_num, 0xff);
         }
 
         switch (type) {
@@ -218,6 +233,7 @@ send_mmc_cmd(uint8_t cmd, uint32_t payload)
  * @param spi_num Number of the SPI channel to be used by MMC
  * @param spi_cfg Low-level device specific SPI configuration
  * @param ss_pin Number of SS pin if SW controlled, -1 otherwise
+ * @param mmc_spi_cfg 
  *
  * @return 0 on success, non-zero on failure
  */
@@ -230,25 +246,25 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
     uint32_t ocr;
     os_time_t wait_to;
 
-    g_ss_pin = ss_pin;
-    g_spi_num = spi_num;
+    g_mmc_cfg.spi_num = spi_num;
+    g_mmc_cfg.ss_pin = ss_pin;
+    g_mmc_cfg.spi_cfg = spi_cfg;
+    g_mmc_cfg.settings = &mmc_settings;
 
-    if (g_ss_pin != -1) {
-        hal_gpio_init_out(g_ss_pin, 1);
-    }
+    hal_gpio_init_out(g_mmc_cfg.ss_pin, 1);
 
-    rc = hal_spi_init(g_spi_num, spi_cfg, HAL_SPI_TYPE_MASTER);
+    rc = hal_spi_init(g_mmc_cfg.spi_num, g_mmc_cfg.spi_cfg, HAL_SPI_TYPE_MASTER);
     if (rc) {
         return (rc);
     }
 
-    rc = hal_spi_config(g_spi_num, &mmc_settings);
+    rc = hal_spi_config(g_mmc_cfg.spi_num, g_mmc_cfg.settings);
     if (rc) {
         return (rc);
     }
 
-    hal_spi_set_txrx_cb(0, NULL, NULL);
-    hal_spi_enable(0);
+    hal_spi_set_txrx_cb(g_mmc_cfg.spi_num, NULL, NULL);
+    hal_spi_enable(g_mmc_cfg.spi_num);
 
     /**
      * NOTE: The state machine below follows:
@@ -259,20 +275,20 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
     /* give 10ms for VDD rampup */
     os_time_delay(OS_TICKS_PER_SEC / 100);
 
-    hal_gpio_write(g_ss_pin, 0);
-    hal_spi_tx_val(0, 0xff);
+    hal_gpio_write(g_mmc_cfg.ss_pin, 0);
+    hal_spi_tx_val(g_mmc_cfg.spi_num, 0xff);
 
     /* send the required >= 74 clock cycles */
     for (i = 0; i < 74; i++) {
-        hal_spi_tx_val(0, 0xff);
+        hal_spi_tx_val(g_mmc_cfg.spi_num, 0xff);
     }
 
     /* put card in idle state */
-    status = send_mmc_cmd(CMD0, 0);
+    status = send_mmc_cmd(&g_mmc_cfg, CMD0, 0);
 
     if (status != R_IDLE) {
         /* No card inserted or bad card! */
-        hal_gpio_write(g_ss_pin, 1);
+        hal_gpio_write(g_mmc_cfg.ss_pin, 1);
         return mmc_error_by_status(status);
     }
 
@@ -282,11 +298,11 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
      * NOTE: cards that are not compliant with "Physical Spec Version 2.00"
      *       will answer this with R_ILLEGAL_COMMAND.
      */
-    status = send_mmc_cmd(CMD8, 0x1AA);
+    status = send_mmc_cmd(&g_mmc_cfg, CMD8, 0x1AA);
     if (status & R_ILLEGAL_COMMAND) {
         /* Ver1.x SD Memory Card or Not SD Memory Card */
 
-        ocr = send_mmc_cmd(CMD58, 0);
+        ocr = send_mmc_cmd(&g_mmc_cfg, CMD58, 0);
 
         /* TODO: check if voltage range is ok! */
 
@@ -308,23 +324,23 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
 #define TIME_TO_WAIT (3 * OS_TICKS_PER_SEC)
 
         wait_to = os_time_get() + TIME_TO_WAIT;
-        status = send_mmc_cmd(ACMD41, 0x40000000); /* FIXME */
+        status = send_mmc_cmd(&g_mmc_cfg, ACMD41, 0x40000000); /* FIXME */
 
         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);
+            status = send_mmc_cmd(&g_mmc_cfg, ACMD41, 0);
         }
         //printf("ACMD41 status=%x\n", status);
 
         /* TODO: check CCS = OCR[30] */
-        status = send_mmc_cmd(CMD58, 0);
+        status = send_mmc_cmd(&g_mmc_cfg, CMD58, 0);
         //printf("CMD58 status=%x\n", status);
     }
 
-    hal_gpio_write(g_ss_pin, 1);
+    hal_gpio_write(g_mmc_cfg.ss_pin, 1);
 
     return rc;
 }
@@ -333,7 +349,7 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
  * @return 0 on success, non-zero on failure
  */
 int
-mmc_read(uint32_t addr, void *buf, size_t len)
+mmc_read(uint8_t mmc_id, uint32_t addr, void *buf, size_t len)
 {
     uint8_t cmd;
     uint8_t res;
@@ -345,8 +361,12 @@ mmc_read(uint32_t addr, void *buf, size_t len)
     size_t offset;
     size_t index;
     size_t amount;
+    struct mmc_cfg *mmc;
 
-    hal_gpio_write(g_ss_pin, 0);
+    mmc = mmc_cfg_dev(mmc_id);
+    if (mmc == NULL) {
+        return (MMC_DEVICE_ERROR);
+    }
 
     block_len = (len + BLOCK_LEN - 1) & ~(BLOCK_LEN - 1);
     block_count = block_len / BLOCK_LEN;
@@ -356,11 +376,13 @@ mmc_read(uint32_t addr, void *buf, size_t len)
     //printf("addr=0x%lx, block_addr=0x%lx, offset=%d\n", addr, block_addr, offset);
     //printf("len=%d, block_len=%d, block_count=%d\n", len, block_len, block_count);
 
+    hal_gpio_write(mmc->ss_pin, 0);
+
     cmd = (block_count == 1) ? CMD17 : CMD18;
-    res = send_mmc_cmd(cmd, block_addr);
+    res = send_mmc_cmd(mmc, cmd, block_addr);
     if (res != MMC_OK) {
-        hal_gpio_write(g_ss_pin, 1);
-        return MMC_CARD_ERROR;
+        hal_gpio_write(mmc->ss_pin, 1);
+        return (MMC_CARD_ERROR);
     }
 
     /**
@@ -369,7 +391,7 @@ mmc_read(uint32_t addr, void *buf, size_t len)
      */
     timeout = os_time_get() + OS_TICKS_PER_SEC / 5;
     do {
-        res = hal_spi_tx_val(g_spi_num, 0xff);
+        res = hal_spi_tx_val(mmc->spi_num, 0xff);
         if (res != 0xFF) break;
         os_time_delay(OS_TICKS_PER_SEC / 20);
     } while (os_time_get() < timeout);
@@ -385,12 +407,12 @@ mmc_read(uint32_t addr, void *buf, size_t len)
              */
 
             for (n = 0; n < BLOCK_LEN; n++) {
-                g_block_buf[n] = hal_spi_tx_val(g_spi_num, 0xff);
+                g_block_buf[n] = hal_spi_tx_val(mmc->spi_num, 0xff);
             }
 
             /* FIXME: consume CRC-16, but should check */
-            hal_spi_tx_val(g_spi_num, 0xff);
-            hal_spi_tx_val(g_spi_num, 0xff);
+            hal_spi_tx_val(mmc->spi_num, 0xff);
+            hal_spi_tx_val(mmc->spi_num, 0xff);
 
             amount = MIN(BLOCK_LEN - offset, len);
 
@@ -403,15 +425,15 @@ mmc_read(uint32_t addr, void *buf, size_t len)
         }
 
         if (cmd == CMD18) {
-            send_mmc_cmd(CMD12, 0);
+            send_mmc_cmd(mmc, CMD12, 0);  /* FIXME */
         }
 
-        hal_gpio_write(g_ss_pin, 1);
+        hal_gpio_write(mmc->ss_pin, 1);
 
         return MMC_OK;
     }
 
-    hal_gpio_write(g_ss_pin, 1);
+    hal_gpio_write(mmc->ss_pin, 1);
 
     return MMC_CARD_ERROR;
 }
@@ -420,7 +442,7 @@ mmc_read(uint32_t addr, void *buf, size_t len)
  * @return 0 on success, non-zero on failure
  */
 int
-mmc_write(uint32_t addr, const void *buf, size_t len)
+mmc_write(uint8_t mmc_id, uint32_t addr, const void *buf, size_t len)
 {
     uint8_t cmd;
     uint8_t res;
@@ -433,14 +455,20 @@ mmc_write(uint32_t addr, const void *buf, size_t len)
     size_t index;
     size_t amount;
     int status;
+    struct mmc_cfg *mmc;
 
-    hal_gpio_write(g_ss_pin, 0);
+    mmc = mmc_cfg_dev(mmc_id);
+    if (mmc == NULL) {
+        return (MMC_DEVICE_ERROR);
+    }
 
     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);
 
+    hal_gpio_write(mmc->ss_pin, 0);
+
     /**
      * This code ensures that if the requested address doesn't align with the
      * beginning address of a sector, the initial bytes are first read to the
@@ -450,43 +478,43 @@ mmc_write(uint32_t addr, const void *buf, size_t len)
      * like FAT (offset is always 0).
      */
     if (offset) {
-        res = send_mmc_cmd(CMD17, block_addr);
+        res = send_mmc_cmd(mmc, CMD17, block_addr);
         if (res != MMC_OK) {
-            hal_gpio_write(g_ss_pin, 1);
-            return MMC_CARD_ERROR;
+            hal_gpio_write(mmc->ss_pin, 1);
+            return (MMC_CARD_ERROR);
         }
 
         timeout = os_time_get() + OS_TICKS_PER_SEC / 5;
         do {
-            res = hal_spi_tx_val(g_spi_num, 0xff);
-            if (res != 0xFF) break;
+            res = hal_spi_tx_val(mmc->spi_num, 0xff);
+            if (res != 0xff) break;
             os_time_delay(OS_TICKS_PER_SEC / 20);
         } while (os_time_get() < timeout);
 
-        if (res != 0xFE) {
-            hal_gpio_write(g_ss_pin, 1);
-            return MMC_CARD_ERROR;
+        if (res != 0xfe) {
+            hal_gpio_write(mmc->ss_pin, 1);
+            return (MMC_CARD_ERROR);
         }
 
         for (n = 0; n < BLOCK_LEN; n++) {
-            g_block_buf[n] = hal_spi_tx_val(g_spi_num, 0xff);
+            g_block_buf[n] = hal_spi_tx_val(mmc->spi_num, 0xff);
         }
 
-        hal_spi_tx_val(g_spi_num, 0xff);
-        hal_spi_tx_val(g_spi_num, 0xff);
+        hal_spi_tx_val(mmc->spi_num, 0xff);
+        hal_spi_tx_val(mmc->spi_num, 0xff);
     }
 
     /* now start write */
 
     cmd = (block_count == 1) ? CMD24 : CMD25;
-    res = send_mmc_cmd(cmd, block_addr);
+    res = send_mmc_cmd(mmc, cmd, block_addr);
     if (res != MMC_OK) {
-        hal_gpio_write(g_ss_pin, 1);
-        return MMC_CARD_ERROR;
+        hal_gpio_write(mmc->ss_pin, 1);
+        return (MMC_CARD_ERROR);
     }
 
     /* FIXME: one byte gap, is this really required? */
-    hal_spi_tx_val(g_spi_num, 0xff);
+    hal_spi_tx_val(mmc->spi_num, 0xff);
 
     index = 0;
     do {
@@ -496,26 +524,26 @@ mmc_write(uint32_t addr, const void *buf, size_t len)
          * 7.3.3.2 Start Block Tokens and Stop Tran Token
          */
         if (cmd == CMD24) {
-            hal_spi_tx_val(g_spi_num, 0xFE);
+            hal_spi_tx_val(mmc->spi_num, 0xFE);
         } else {
-            hal_spi_tx_val(g_spi_num, 0xFC);
+            hal_spi_tx_val(mmc->spi_num, 0xFC);
         }
 
         amount = MIN(BLOCK_LEN - offset, len);
         memcpy(&g_block_buf[offset], ((uint8_t *)buf + index), amount);
 
         for (n = 0; n < BLOCK_LEN; n++) {
-            hal_spi_tx_val(g_spi_num, g_block_buf[n]);
+            hal_spi_tx_val(mmc->spi_num, g_block_buf[n]);
         }
 
         /* CRC */
-        hal_spi_tx_val(g_spi_num, 0xff);
-        hal_spi_tx_val(g_spi_num, 0xff);
+        hal_spi_tx_val(mmc->spi_num, 0xff);
+        hal_spi_tx_val(mmc->spi_num, 0xff);
 
         /**
          * 7.3.3.1 Data Response Token
          */
-        res = hal_spi_tx_val(g_spi_num, 0xff);
+        res = hal_spi_tx_val(mmc->spi_num, 0xff);
         if ((res & 0x1f) != 0x05) {
             break;
         }
@@ -531,7 +559,6 @@ mmc_write(uint32_t addr, const void *buf, size_t len)
     }
 
     res &= 0x1f;
-    //printf("final response token: 0x%x\n", res);
     switch (res) {
         case 0x05:
             status = MMC_OK;
@@ -546,12 +573,12 @@ mmc_write(uint32_t addr, const void *buf, size_t len)
 
     timeout = os_time_get() + 5 * OS_TICKS_PER_SEC;
     do {
-        res = hal_spi_tx_val(g_spi_num, 0xff);
+        res = hal_spi_tx_val(mmc->spi_num, 0xff);
         if (res) break;
         os_time_delay(OS_TICKS_PER_SEC / 100);
     } while (os_time_get() < timeout);
 
-    hal_gpio_write(g_ss_pin, 1);
+    hal_gpio_write(mmc->ss_pin, 1);
 
     return status;
 }


[09/12] incubator-mynewt-core git commit: Remove test app

Posted by cc...@apache.org.
Remove test app


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/110184c1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/110184c1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/110184c1

Branch: refs/heads/develop
Commit: 110184c162c0ae75fe6464913939a1401227e6a3
Parents: 8f1144f
Author: Fabio Utzig <ut...@utzig.org>
Authored: Fri Dec 9 08:54:25 2016 -0200
Committer: Fabio Utzig <ut...@utzig.org>
Committed: Fri Dec 9 08:54:25 2016 -0200

----------------------------------------------------------------------
 apps/mmctest/pkg.yml    |  31 ----
 apps/mmctest/src/main.c | 369 -------------------------------------------
 apps/mmctest/syscfg.yml |  22 ---
 3 files changed, 422 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/110184c1/apps/mmctest/pkg.yml
----------------------------------------------------------------------
diff --git a/apps/mmctest/pkg.yml b/apps/mmctest/pkg.yml
deleted file mode 100644
index c42160c..0000000
--- a/apps/mmctest/pkg.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#  http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-pkg.name: apps/mmctest
-pkg.type: app
-pkg.description: TBD
-pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
-pkg.homepage: "http://mynewt.apache.org/"
-pkg.keywords:
-
-pkg.deps:
-    - sys/console/full
-    - kernel/os
-    - hw/drivers/mmc
-    - hw/mcu/stm/stm32f4xx

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/110184c1/apps/mmctest/src/main.c
----------------------------------------------------------------------
diff --git a/apps/mmctest/src/main.c b/apps/mmctest/src/main.c
deleted file mode 100755
index 34847ea..0000000
--- a/apps/mmctest/src/main.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-#include "sysinit/sysinit.h"
-#include "os/os.h"
-#include "bsp/bsp.h"
-#include "hal/hal_gpio.h"
-#include "hal/hal_spi.h"
-#include <mmc/mmc.h>
-#include <mcu/stm32f4xx_mynewt_hal.h>
-#include <os/os_dev.h>
-#include <assert.h>
-#include <string.h>
-#include <console/console.h>
-#ifdef ARCH_sim
-#include <mcu/mcu_sim.h>
-#endif
-
-/* The spi txrx callback */
-struct sblinky_spi_cb_arg
-{
-    int transfers;
-    int txlen;
-    uint32_t tx_rx_bytes;
-};
-struct sblinky_spi_cb_arg spi_cb_obj;
-void *spi_cb_arg;
-
-/* Task 1 */
-#define TASK1_PRIO (1)
-#define TASK1_STACK_SIZE    OS_STACK_ALIGN(1024)
-struct os_task task1;
-
-/* Task 2 */
-#define TASK2_PRIO (2)
-#define TASK2_STACK_SIZE    OS_STACK_ALIGN(512)
-static struct os_task task2;
-
-#define TASK3_PRIO (3)
-#define TASK3_STACK_SIZE    OS_STACK_ALIGN(512)
-static struct os_task task3;
-
-static struct os_eventq mmctest_evq;
-
-/* Global test semaphore */
-struct os_sem g_test_sem;
-
-/* For LED toggling */
-int g_led_pin;
-
-static const int SPI_SS_PIN   = MCU_GPIO_PORTA(4);
-static const int SPI_SCK_PIN  = MCU_GPIO_PORTA(5);
-static const int SPI_MISO_PIN = MCU_GPIO_PORTA(6);
-static const int SPI_MOSI_PIN = MCU_GPIO_PORTA(7);
-
-uint8_t g_spi_tx_buf[32];
-uint8_t g_spi_last_tx_buf[32];
-uint8_t g_spi_rx_buf[32];
-uint32_t g_spi_xfr_num;
-uint8_t g_spi_null_rx;
-uint8_t g_last_tx_len;
-
-static
-void mmctest_validate_last(int len)
-{
-    int i;
-    int curlen;
-    int remlen;
-    int curindex;
-    uint8_t expval;
-
-    if (g_spi_null_rx == 0) {
-        expval = 0xaa;
-        if (g_last_tx_len < len) {
-            curlen = g_last_tx_len;
-            remlen = len - g_last_tx_len;
-        } else {
-            curlen = len;
-            remlen = 0;
-        }
-        for (i = 0; i < curlen; ++i) {
-            if (g_spi_rx_buf[i] != g_spi_last_tx_buf[i]) {
-                assert(0);
-            }
-        }
-        curindex = curlen;
-        for (i = 0; i < remlen; ++i) {
-            if (g_spi_rx_buf[curindex + i] != expval) {
-                assert(0);
-            }
-        }
-    }
-}
-
-void
-sblinky_spi_irqm_handler(void *arg, int len)
-{
-    int i;
-    struct sblinky_spi_cb_arg *cb;
-
-    //hal_gpio_write(SPI_SS_PIN, 1);
-
-    assert(arg == spi_cb_arg);
-    if (spi_cb_arg) {
-        cb = (struct sblinky_spi_cb_arg *)arg;
-        assert(len == cb->txlen);
-        ++cb->transfers;
-    }
-
-    /* Make sure we get back the data we expect! */
-    if (g_spi_xfr_num == 1) {
-        /* The first time we expect entire buffer to be filled with 0x88 */
-        for (i = 0; i < len; ++i) {
-            if (g_spi_rx_buf[i] != 0x88) {
-                assert(0);
-            }
-        }
-
-        /* copy current tx buf to last */
-        memcpy(g_spi_last_tx_buf, g_spi_tx_buf, len);
-    } else {
-        /* Check that we received what we last sent */
-        mmctest_validate_last(len);
-    }
-    ++g_spi_xfr_num;
-}
-
-void
-task1_handler(void *arg)
-{
-    //int i;
-    int rc;
-    //uint16_t rxval;
-    //uint8_t last_val;
-    //uint8_t spi_nb_cntr;
-    //uint8_t spi_b_cntr;
-
-    struct stm32f4_hal_spi_cfg spi_cfg = {
-        .ss_pin   = SPI_SS_PIN,
-        .sck_pin  = SPI_SCK_PIN,
-        .miso_pin = SPI_MISO_PIN,
-        .mosi_pin = SPI_MOSI_PIN,
-        .irq_prio = 2
-    };
-
-    rc = mmc_init(0, &spi_cfg, spi_cfg.ss_pin);
-    printf("mmc_init %d\n", rc);
-
-#if 0
-    /*
-     * Send some bytes in a non-blocking manner to SPI using tx val. The
-     * slave should send back 0x77.
-     */
-    g_spi_tx_buf[0] = 0xde;
-    g_spi_tx_buf[1] = 0xad;
-    g_spi_tx_buf[2] = 0xbe;
-    g_spi_tx_buf[3] = 0xef;
-    hal_gpio_write(SPI_SS_PIN, 0);
-    for (i = 0; i < 4; ++i) {
-        rxval = hal_spi_tx_val(0, g_spi_tx_buf[i]);
-        assert(rxval == 0x77);
-        g_spi_rx_buf[i] = (uint8_t)rxval;
-    }
-    hal_gpio_write(SPI_SS_PIN, 1);
-    ++g_spi_xfr_num;
-
-    /* Set up the callback to use when non-blocking API used */
-    hal_spi_disable(0);
-    spi_cb_arg = &spi_cb_obj;
-    spi_cb_obj.txlen = 32;
-    hal_spi_set_txrx_cb(0, sblinky_spi_irqm_handler, spi_cb_arg);
-    hal_spi_enable(0);
-    spi_nb_cntr = 0;
-    spi_b_cntr = 0;
-
-    while (1) {
-        /* Get random length to send */
-        g_last_tx_len = spi_cb_obj.txlen;
-        spi_cb_obj.txlen = (rand() & 0x1F) + 1;
-        memcpy(g_spi_last_tx_buf, g_spi_tx_buf, g_last_tx_len);
-        last_val = g_spi_last_tx_buf[g_last_tx_len - 1];
-        for (i= 0; i < spi_cb_obj.txlen; ++i) {
-            g_spi_tx_buf[i] = (uint8_t)(last_val + i);
-        }
-
-        if (g_spi_xfr_num & 1) {
-            /* Send non-blocking */
-            ++spi_nb_cntr;
-            assert(hal_gpio_read(SPI_SS_PIN) == 1);
-            hal_gpio_write(SPI_SS_PIN, 0);
-#if 0
-            if (spi_nb_cntr == 7) {
-                g_spi_null_rx = 1;
-                rc = hal_spi_txrx_noblock(0, g_spi_tx_buf, NULL, 32);
-            } else {
-                g_spi_null_rx = 0;
-                rc = hal_spi_txrx_noblock(0, g_spi_tx_buf, g_spi_rx_buf, 32);
-            }
-            assert(!rc);
-#else
-            g_spi_null_rx = 0;
-            rc = hal_spi_txrx_noblock(0, g_spi_tx_buf, g_spi_rx_buf,
-                                      spi_cb_obj.txlen);
-            assert(!rc);
-            console_printf("a transmitted: ");
-            for (i = 0; i < spi_cb_obj.txlen; i++) {
-                console_printf("%2x ", g_spi_tx_buf[i]);
-            }
-            console_printf("\n");
-            console_printf("received: ");
-            for (i = 0; i < spi_cb_obj.txlen; i++) {
-                console_printf("%2x ", g_spi_rx_buf[i]);
-            }
-            console_printf("\n");
-#endif
-        } else {
-            /* Send blocking */
-            ++spi_b_cntr;
-            assert(hal_gpio_read(SPI_SS_PIN) == 1);
-            hal_gpio_write(SPI_SS_PIN, 0);
-#if 0
-            if (spi_b_cntr == 7) {
-                g_spi_null_rx = 1;
-                rc = hal_spi_txrx(0, g_spi_tx_buf, NULL, 32);
-                spi_b_cntr = 0;
-            } else {
-                g_spi_null_rx = 0;
-                rc = hal_spi_txrx(0, g_spi_tx_buf, g_spi_rx_buf, 32);
-            }
-            assert(!rc);
-            hal_gpio_write(SPI_SS_PIN, 1);
-            mmctest_validate_last(spi_cb_obj.txlen);
-#else
-            rc = hal_spi_txrx(0, g_spi_tx_buf, g_spi_rx_buf, spi_cb_obj.txlen);
-            assert(!rc);
-            hal_gpio_write(SPI_SS_PIN, 1);
-            console_printf("b transmitted: ");
-            for (i = 0; i < spi_cb_obj.txlen; i++) {
-                console_printf("%2x ", g_spi_tx_buf[i]);
-            }
-            console_printf("\n");
-            console_printf("received: ");
-            for (i = 0; i < spi_cb_obj.txlen; i++) {
-                console_printf("%2x ", g_spi_rx_buf[i]);
-            }
-            console_printf("\n");
-            mmctest_validate_last(spi_cb_obj.txlen);
-            ++g_spi_xfr_num;
-#endif
-        }
-    }
-#endif
-
-    while (1) {
-        os_time_delay(OS_TICKS_PER_SEC);
-    }
-}
-
-/**
- * This task serves as a container for the shell and newtmgr packages.  These
- * packages enqueue timer events when they need this task to do work.
- */
-static void
-task2_handler(void *arg)
-{
-    while (1) {
-        os_eventq_run(&mmctest_evq);
-    }
-}
-
-static void
-task3_handler(void *arg)
-{
-    while (1) {
-        os_time_delay(OS_TICKS_PER_SEC);
-        hal_gpio_toggle(g_led_pin);
-    }
-}
-
-/**
- * init_tasks
- *
- * Called by main.c after sysinit(). This function performs initializations
- * that are required before tasks are running.
- *
- * @return int 0 success; error otherwise.
- */
-static void
-init_tasks(void)
-{
-    os_stack_t *pstack;
-
-    /* Initialize global test semaphore */
-    os_sem_init(&g_test_sem, 0);
-
-    pstack = malloc(sizeof(os_stack_t)*TASK1_STACK_SIZE);
-    assert(pstack);
-
-    os_task_init(&task1, "task1", task1_handler, NULL,
-            TASK1_PRIO, OS_WAIT_FOREVER, pstack, TASK1_STACK_SIZE);
-
-    pstack = malloc(sizeof(os_stack_t)*TASK2_STACK_SIZE);
-    assert(pstack);
-
-    os_task_init(&task2, "task2", task2_handler, NULL,
-            TASK2_PRIO, OS_WAIT_FOREVER, pstack, TASK2_STACK_SIZE);
-
-    pstack = malloc(sizeof(os_stack_t)*TASK3_STACK_SIZE);
-    assert(pstack);
-
-    os_task_init(&task3, "task3", task3_handler, NULL,
-            TASK3_PRIO, OS_WAIT_FOREVER, pstack, TASK3_STACK_SIZE);
-
-    /* Initialize eventq and designate it as the default.  Packages that need
-     * to schedule work items will piggyback on this eventq.  Example packages
-     * which do this are sys/shell and mgmt/newtmgr.
-     */
-    os_eventq_init(&mmctest_evq);
-    os_eventq_dflt_set(&mmctest_evq);
-}
-
-/**
- * main
- *
- * The main function for the project. This function initializes the os, calls
- * init_tasks to initialize tasks (and possibly other objects), then starts the
- * OS. We should not return from os start.
- *
- * @return int NOTE: this function should never return!
- */
-int
-main(int argc, char **argv)
-{
-    int rc;
-
-#ifdef ARCH_sim
-    mcu_sim_parse_args(argc, argv);
-#endif
-
-    sysinit();
-
-    /* Set the led pin for the devboard */
-    g_led_pin = LED_BLINK_PIN;
-    hal_gpio_init_out(g_led_pin, 0);
-
-    init_tasks();
-    os_start();
-
-    /* os start should never return. If it does, this should be an error */
-    assert(0);
-
-    return rc;
-}
-

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/110184c1/apps/mmctest/syscfg.yml
----------------------------------------------------------------------
diff --git a/apps/mmctest/syscfg.yml b/apps/mmctest/syscfg.yml
deleted file mode 100644
index 40c4c52..0000000
--- a/apps/mmctest/syscfg.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#  http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# Package: apps/mmctest
-
-syscfg.vals:
-    SHELL_TASK: 0


[10/12] incubator-mynewt-core git commit: Add extra doc + errors messages

Posted by cc...@apache.org.
Add extra doc + errors messages


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/3c45dde0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/3c45dde0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/3c45dde0

Branch: refs/heads/develop
Commit: 3c45dde09118c2a43cb3ddba7acf3a6476c9aac1
Parents: 110184c
Author: Fabio Utzig <ut...@utzig.org>
Authored: Fri Dec 9 09:10:24 2016 -0200
Committer: Fabio Utzig <ut...@utzig.org>
Committed: Fri Dec 9 09:10:24 2016 -0200

----------------------------------------------------------------------
 hw/drivers/mmc/include/mmc/mmc.h | 39 +++++++++++++++++++----------------
 hw/drivers/mmc/src/mmc.c         | 22 +++++++++++---------
 2 files changed, 33 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3c45dde0/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 9dbf35e..d65363d 100644
--- a/hw/drivers/mmc/include/mmc/mmc.h
+++ b/hw/drivers/mmc/include/mmc/mmc.h
@@ -29,16 +29,19 @@ extern "C" {
 /**
  * MMC driver errors.
  */
-#define MMC_OK              (0)
-#define MMC_CARD_ERROR      (-1)  /* Is there a card installed? */
-#define MMC_READ_ERROR      (-2)
-#define MMC_WRITE_ERROR     (-3)
-#define MMC_TIMEOUT         (-4)
-#define MMC_PARAM_ERROR     (-5)
-#define MMC_CRC_ERROR       (-6)
-#define MMC_DEVICE_ERROR    (-7)
-#define MMC_RESPONSE_ERROR  (-8)
-#define MMC_VOLTAGE_ERROR   (-9)
+#define MMC_OK                (0)
+#define MMC_CARD_ERROR        (-1)  /* Is there a card installed? */
+#define MMC_READ_ERROR        (-2)
+#define MMC_WRITE_ERROR       (-3)
+#define MMC_TIMEOUT           (-4)
+#define MMC_PARAM_ERROR       (-5)
+#define MMC_CRC_ERROR         (-6)
+#define MMC_DEVICE_ERROR      (-7)
+#define MMC_RESPONSE_ERROR    (-8)
+#define MMC_VOLTAGE_ERROR     (-9)
+#define MMC_INVALID_COMMAND   (-10)
+#define MMC_ERASE_ERROR       (-11)
+#define MMC_ADDR_ERROR        (-12)
 
 /**
  * Initialize the MMC driver
@@ -55,10 +58,10 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin);
 /**
  * Read data from MMC
  *
- * @param mmc_id
- * @param addr
- * @param buf
- * @param len
+ * @param mmc_id Id of the MMC device (currently must be 0)
+ * @param addr Disk address (in bytes) to be read from
+ * @param buf Buffer where data should be copied to
+ * @param len Amount of data to read/copy
  *
  * @return 0 on success, non-zero on failure
  */
@@ -68,10 +71,10 @@ mmc_read(uint8_t mmc_id, uint32_t addr, void *buf, size_t len);
 /**
  * Write data to the MMC
  *
- * @param mmc_id
- * @param addr
- * @param buf
- * @param len
+ * @param mmc_id Id of the MMC device (currently must be 0)
+ * @param addr Disk address (in bytes) to be written to
+ * @param buf Buffer where data should be copied from
+ * @param len Amount of data to copy/write
  *
  * @return 0 on success, non-zero on failure
  */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3c45dde0/hw/drivers/mmc/src/mmc.c
----------------------------------------------------------------------
diff --git a/hw/drivers/mmc/src/mmc.c b/hw/drivers/mmc/src/mmc.c
index 653e08f..6c5dcbe 100644
--- a/hw/drivers/mmc/src/mmc.c
+++ b/hw/drivers/mmc/src/mmc.c
@@ -86,27 +86,29 @@ static struct mmc_cfg {
 static int
 error_by_response(uint8_t status)
 {
+    int rc = MMC_CARD_ERROR;
+
     if (status == 0) {
-        return MMC_OK;
+        rc = MMC_OK;
     } else if (status == 0xff) {
-        return MMC_CARD_ERROR;
+        rc = MMC_CARD_ERROR;
     } else if (status & R_IDLE) {
-        return MMC_TIMEOUT;
+        rc = MMC_TIMEOUT;
     } else if (status & R_ERASE_RESET) {
-        /* TODO */
+        rc = MMC_ERASE_ERROR;
     } else if (status & R_ILLEGAL_COMMAND) {
-        /* TODO */
+        rc = MMC_INVALID_COMMAND;
     } else if (status & R_CRC_ERROR) {
-        return MMC_CRC_ERROR;
+        rc = MMC_CRC_ERROR;
     } else if (status & R_ERASE_ERROR) {
-        /* TODO */
+        rc = MMC_ERASE_ERROR;
     } else if (status & R_ADDR_ERROR) {
-        /* TODO */
+        rc = MMC_ADDR_ERROR;
     } else if (status & R_PARAM_ERROR) {
-        return MMC_PARAM_ERROR;
+        rc = MMC_PARAM_ERROR;
     }
 
-    return MMC_CARD_ERROR;
+    return (rc);
 }
 
 static struct mmc_cfg *


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

Posted by cc...@apache.org.
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;
 }


[12/12] incubator-mynewt-core git commit: This closes #137.

Posted by cc...@apache.org.
This closes #137.

Merge remote-tracking branch 'utzig/mmc-support' into develop

* utzig/mmc-support:
  Remove empty comment block
  Add extra doc + errors messages
  Remove test app
  Fix multi-block write, misc refactors
  Misc fixes + fix multi-block read
  Better error checking + cleanups/refactorings
  Initial bare support for multiple MMC
  Write support working - WIP
  Add write support - WIP
  Add mmc read support - WIP
  MMC driver 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/d19cb51b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/d19cb51b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/d19cb51b

Branch: refs/heads/develop
Commit: d19cb51b015c375a528afcfd54d7c47515132f8c
Parents: 1caa492 e3ac9e3
Author: Christopher Collins <cc...@apache.org>
Authored: Tue Dec 13 11:33:12 2016 -0800
Committer: Christopher Collins <cc...@apache.org>
Committed: Tue Dec 13 11:33:12 2016 -0800

----------------------------------------------------------------------
 hw/drivers/mmc/include/mmc/mmc.h |  88 +++++
 hw/drivers/mmc/pkg.yml           |  27 ++
 hw/drivers/mmc/src/mmc.c         | 585 ++++++++++++++++++++++++++++++++++
 3 files changed, 700 insertions(+)
----------------------------------------------------------------------



[08/12] incubator-mynewt-core git commit: Fix multi-block write, misc refactors

Posted by cc...@apache.org.
Fix multi-block write, misc refactors


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/8f1144f7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/8f1144f7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/8f1144f7

Branch: refs/heads/develop
Commit: 8f1144f71633e7de204f01306b6202c975b48a97
Parents: 17e7f9c
Author: Fabio Utzig <ut...@utzig.org>
Authored: Fri Dec 9 08:49:43 2016 -0200
Committer: Fabio Utzig <ut...@utzig.org>
Committed: Fri Dec 9 08:49:43 2016 -0200

----------------------------------------------------------------------
 hw/drivers/mmc/src/mmc.c | 120 ++++++++++++++++++++++++------------------
 1 file changed, 68 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8f1144f7/hw/drivers/mmc/src/mmc.c
----------------------------------------------------------------------
diff --git a/hw/drivers/mmc/src/mmc.c b/hw/drivers/mmc/src/mmc.c
index f0fe71d..653e08f 100644
--- a/hw/drivers/mmc/src/mmc.c
+++ b/hw/drivers/mmc/src/mmc.c
@@ -58,6 +58,10 @@
 #define R_ADDR_ERROR        (0x20)
 #define R_PARAM_ERROR       (0x40)
 
+#define START_BLOCK         (0xFE)
+#define START_BLOCK_TOKEN   (0xFC)
+#define STOP_TRAN_TOKEN     (0xFD)
+
 #define BLOCK_LEN           (512)
 
 static uint8_t g_block_buf[BLOCK_LEN];
@@ -80,7 +84,7 @@ static struct mmc_cfg {
 } g_mmc_cfg;
 
 static int
-mmc_error_by_status(uint8_t status)
+error_by_response(uint8_t status)
 {
     if (status == 0) {
         return MMC_OK;
@@ -153,8 +157,6 @@ send_mmc_cmd(struct mmc_cfg *mmc, uint8_t cmd, uint32_t payload)
     }
     hal_spi_tx_val(mmc->spi_num, crc);
 
-    //printf("==> sending cmd %d\n", cmd & ~0x80);
-
     for (n = 255; n > 0; n--) {
         status = hal_spi_tx_val(mmc->spi_num, 0xff);
         if ((status & 0x80) == 0) break;
@@ -231,11 +233,19 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
 
     /* No card inserted or bad card? */
     if (status != R_IDLE) {
-        rc = mmc_error_by_status(status);
+        rc = error_by_response(status);
         goto out;
     }
 
     /**
+     * FIXME: while doing a hot-swap of the card or powering off the board
+     * it is required to send a CMD1 here otherwise CMD8's response will
+     * be always invalid.
+     *
+     * Why is this happening? CMD1 should never be required for SDxC cards...
+     */
+
+    /**
      * 4.3.13: Ask for 2.7-3.3V range, send 0xAA pattern
      *
      * NOTE: cards that are not compliant with "Physical Spec Version 2.00"
@@ -282,7 +292,7 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
         }
 
         if (status) {
-            rc = mmc_error_by_status(status);
+            rc = error_by_response(status);
             goto out;
         }
 
@@ -298,16 +308,11 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
             /**
              * TODO: if CCS is set this is an SDHC or SDXC card!
              *       SDSC uses byte addressing, SDHC/SDXC block addressing
+             *
+             *       can also check the whole voltage range supported here
              */
         }
 
-#if 0  /* TODO: Can check all possible voltages supported by card */
-    printf("Card supports: ");
-    if (ocr & (1 << 15)) {
-        printf("2.7-2.8 ");
-    }
-#endif
-
     } else if (status != 0xff && status & R_ILLEGAL_COMMAND) {
 
         /**
@@ -325,7 +330,7 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
         /* TODO: set blocklen */
 
     } else {
-        rc = mmc_error_by_status(status);
+        rc = error_by_response(status);
     }
 
 out:
@@ -334,6 +339,27 @@ out:
 }
 
 /**
+ * Commands that return response in R1b format and write
+ * commands enter busy state and keep return 0 while the
+ * operations are in progress.
+ */
+static uint8_t
+wait_busy(struct mmc_cfg *mmc)
+{
+    os_time_t timeout;
+    uint8_t res;
+
+    timeout = os_time_get() + OS_TICKS_PER_SEC / 2;
+    do {
+        res = hal_spi_tx_val(mmc->spi_num, 0xff);
+        if (res) break;
+        os_time_delay(OS_TICKS_PER_SEC / 1000);
+    } while (os_time_get() < timeout);
+
+    return res;
+}
+
+/**
  * @return 0 on success, non-zero on failure
  */
 int
@@ -364,15 +390,12 @@ mmc_read(uint8_t mmc_id, uint32_t addr, void *buf, size_t len)
     block_addr = addr / BLOCK_LEN;
     offset = addr - (block_addr * BLOCK_LEN);
 
-    //printf("addr=0x%lx, block_addr=0x%lx, offset=%d\n", addr, block_addr, offset);
-    //printf("len=%d, block_len=%d, block_count=%d\n", len, block_len, block_count);
-
     hal_gpio_write(mmc->ss_pin, 0);
 
     cmd = (block_count == 1) ? CMD17 : CMD18;
     res = send_mmc_cmd(mmc, cmd, block_addr);
     if (res) {
-        rc = mmc_error_by_status(res);
+        rc = error_by_response(res);
         goto out;
     }
 
@@ -390,7 +413,7 @@ mmc_read(uint8_t mmc_id, uint32_t addr, void *buf, size_t len)
     /**
      * 7.3.3.2 Start Block Tokens and Stop Tran Token
      */
-    if (res != 0xFE) {
+    if (res != START_BLOCK) {
         rc = MMC_TIMEOUT;
         goto out;
     }
@@ -416,8 +439,7 @@ mmc_read(uint8_t mmc_id, uint32_t addr, void *buf, size_t len)
 
     if (cmd == CMD18) {
         send_mmc_cmd(mmc, CMD12, 0);
-        /* FIXME: sending extra cycle to wait for stop, need to loop here? */
-        hal_spi_tx_val(mmc->spi_num, 0xff);
+        wait_busy(mmc);
     }
 
 out:
@@ -441,7 +463,7 @@ mmc_write(uint8_t mmc_id, uint32_t addr, const void *buf, size_t len)
     size_t offset;
     size_t index;
     size_t amount;
-    int status;
+    int rc;
     struct mmc_cfg *mmc;
 
     mmc = mmc_cfg_dev(mmc_id);
@@ -466,9 +488,9 @@ mmc_write(uint8_t mmc_id, uint32_t addr, const void *buf, size_t len)
      */
     if (offset) {
         res = send_mmc_cmd(mmc, CMD17, block_addr);
-        if (res != MMC_OK) {
-            hal_gpio_write(mmc->ss_pin, 1);
-            return (MMC_CARD_ERROR);
+        if (res != 0) {
+            rc = error_by_response(res);
+            goto out;
         }
 
         timeout = os_time_get() + OS_TICKS_PER_SEC / 5;
@@ -478,9 +500,9 @@ mmc_write(uint8_t mmc_id, uint32_t addr, const void *buf, size_t len)
             os_time_delay(OS_TICKS_PER_SEC / 20);
         } while (os_time_get() < timeout);
 
-        if (res != 0xfe) {
-            hal_gpio_write(mmc->ss_pin, 1);
-            return (MMC_CARD_ERROR);
+        if (res != START_BLOCK) {
+            rc = MMC_CARD_ERROR;
+            goto out;
         }
 
         for (n = 0; n < BLOCK_LEN; n++) {
@@ -495,25 +517,20 @@ mmc_write(uint8_t mmc_id, uint32_t addr, const void *buf, size_t len)
 
     cmd = (block_count == 1) ? CMD24 : CMD25;
     res = send_mmc_cmd(mmc, cmd, block_addr);
-    if (res != MMC_OK) {
-        hal_gpio_write(mmc->ss_pin, 1);
-        return (MMC_CARD_ERROR);
+    if (res) {
+        rc = error_by_response(res);
+        goto out;
     }
 
-    /* FIXME: one byte gap, is this really required? */
-    hal_spi_tx_val(mmc->spi_num, 0xff);
-
     index = 0;
-    do {
-        /* FIXME: must wait for ready here? */
-
+    while (block_count--) {
         /**
          * 7.3.3.2 Start Block Tokens and Stop Tran Token
          */
         if (cmd == CMD24) {
-            hal_spi_tx_val(mmc->spi_num, 0xFE);
+            hal_spi_tx_val(mmc->spi_num, START_BLOCK);
         } else {
-            hal_spi_tx_val(mmc->spi_num, 0xFC);
+            hal_spi_tx_val(mmc->spi_num, START_BLOCK_TOKEN);
         }
 
         amount = MIN(BLOCK_LEN - offset, len);
@@ -535,37 +552,36 @@ mmc_write(uint8_t mmc_id, uint32_t addr, const void *buf, size_t len)
             break;
         }
 
+        if (cmd == CMD25) {
+            wait_busy(mmc);
+        }
+
         offset = 0;
         len -= amount;
         index += amount;
+    }
 
-    } while (len);
-
-    /* TODO: send stop tran token */
     if (cmd == CMD25) {
+        hal_spi_tx_val(mmc->spi_num, STOP_TRAN_TOKEN);
+        wait_busy(mmc);
     }
 
     res &= 0x1f;
     switch (res) {
         case 0x05:
-            status = MMC_OK;
+            rc = MMC_OK;
             break;
         case 0x0b:
-            status = MMC_CRC_ERROR;
+            rc = MMC_CRC_ERROR;
             break;
         case 0x0d:  /* passthrough */
         default:
-            status = MMC_WRITE_ERROR;
+            rc = MMC_WRITE_ERROR;
     }
 
-    timeout = os_time_get() + 5 * OS_TICKS_PER_SEC;
-    do {
-        res = hal_spi_tx_val(mmc->spi_num, 0xff);
-        if (res) break;
-        os_time_delay(OS_TICKS_PER_SEC / 100);
-    } while (os_time_get() < timeout);
+    wait_busy(mmc);
 
+out:
     hal_gpio_write(mmc->ss_pin, 1);
-
-    return status;
+    return (rc);
 }


[11/12] incubator-mynewt-core git commit: Remove empty comment block

Posted by cc...@apache.org.
Remove empty comment block


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/e3ac9e3c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/e3ac9e3c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/e3ac9e3c

Branch: refs/heads/develop
Commit: e3ac9e3c1c2927c2f7a0ecd24aac2e4ea69a6290
Parents: 3c45dde
Author: Fabio Utzig <ut...@utzig.org>
Authored: Fri Dec 9 09:14:12 2016 -0200
Committer: Fabio Utzig <ut...@utzig.org>
Committed: Fri Dec 9 09:14:12 2016 -0200

----------------------------------------------------------------------
 hw/drivers/mmc/src/mmc.c | 4 ----
 1 file changed, 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e3ac9e3c/hw/drivers/mmc/src/mmc.c
----------------------------------------------------------------------
diff --git a/hw/drivers/mmc/src/mmc.c b/hw/drivers/mmc/src/mmc.c
index 6c5dcbe..ca89434 100644
--- a/hw/drivers/mmc/src/mmc.c
+++ b/hw/drivers/mmc/src/mmc.c
@@ -168,10 +168,6 @@ send_mmc_cmd(struct mmc_cfg *mmc, uint8_t cmd, uint32_t payload)
 }
 
 /**
- * NOTE:
- */
-
-/**
  * Initialize the MMC driver
  *
  * @param spi_num Number of the SPI channel to be used by MMC


[02/12] incubator-mynewt-core git commit: Better error checking + cleanups/refactorings

Posted by cc...@apache.org.
Better error checking + cleanups/refactorings


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/2d89fc4b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/2d89fc4b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/2d89fc4b

Branch: refs/heads/develop
Commit: 2d89fc4b8b7758498a816d1368dba9a11d20d538
Parents: b4040d7
Author: Fabio Utzig <ut...@utzig.org>
Authored: Tue Dec 6 23:14:57 2016 -0200
Committer: Fabio Utzig <ut...@utzig.org>
Committed: Thu Dec 8 22:00:32 2016 -0200

----------------------------------------------------------------------
 hw/drivers/mmc/include/mmc/mmc.h |   2 +
 hw/drivers/mmc/src/mmc.c         | 199 ++++++++++++++++------------------
 2 files changed, 94 insertions(+), 107 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2d89fc4b/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 2f434ef..9dbf35e 100644
--- a/hw/drivers/mmc/include/mmc/mmc.h
+++ b/hw/drivers/mmc/include/mmc/mmc.h
@@ -37,6 +37,8 @@ extern "C" {
 #define MMC_PARAM_ERROR     (-5)
 #define MMC_CRC_ERROR       (-6)
 #define MMC_DEVICE_ERROR    (-7)
+#define MMC_RESPONSE_ERROR  (-8)
+#define MMC_VOLTAGE_ERROR   (-9)
 
 /**
  * Initialize the MMC driver

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2d89fc4b/hw/drivers/mmc/src/mmc.c
----------------------------------------------------------------------
diff --git a/hw/drivers/mmc/src/mmc.c b/hw/drivers/mmc/src/mmc.c
index 199b201..8b30929 100644
--- a/hw/drivers/mmc/src/mmc.c
+++ b/hw/drivers/mmc/src/mmc.c
@@ -26,7 +26,7 @@
 
 #define MIN(n, m) (((n) < (m)) ? (n) : (m))
 
-/* Currently used MMC commands */
+/* MMC commands used by the driver */
 #define CMD0                (0)            /* GO_IDLE_STATE */
 #define CMD1                (1)            /* SEND_OP_COND (MMC) */
 #define CMD8                (8)            /* SEND_IF_COND */
@@ -40,14 +40,16 @@
 #define CMD58               (58)           /* READ_OCR */
 #define ACMD41              (0x80 + 41)    /* SEND_OP_COND (SDC) */
 
+#define HCS                 ((uint32_t) 1 << 30)
+
 /* Response types */
 #define R1                  (0)
 #define R1b                 (1)
 #define R2                  (2)
-#define R3                  (3)
-#define R7                  (4)
+#define R3                  (3)            /* CMD58 */
+#define R7                  (4)            /* CMD8 */
 
-/* Response status */
+/* R1 response status */
 #define R_IDLE              (0x01)
 #define R_ERASE_RESET       (0x02)
 #define R_ILLEGAL_COMMAND   (0x04)
@@ -80,58 +82,26 @@ static struct mmc_cfg {
 static int
 mmc_error_by_status(uint8_t status)
 {
-    if (status == 0xff) {
-        return MMC_CARD_ERROR;
+    if (status == 0) {
+        return MMC_OK;
     } else if (status & R_IDLE) {
         return MMC_TIMEOUT;
     } else if (status & R_ERASE_RESET) {
+        /* TODO */
     } else if (status & R_ILLEGAL_COMMAND) {
+        /* TODO */
     } else if (status & R_CRC_ERROR) {
+        return MMC_CRC_ERROR;
     } else if (status & R_ERASE_ERROR) {
+        /* TODO */
     } else if (status & R_ADDR_ERROR) {
+        /* TODO */
     } else if (status & R_PARAM_ERROR) {
+        return MMC_PARAM_ERROR;
     }
 
-    return MMC_OK;
-}
-
-static int8_t
-response_type_by_cmd(uint8_t cmd)
-{
-    switch (cmd) {
-        case CMD8   : return R7;
-        case CMD58  : return R3;
-    }
-    return R1;
-}
-
-/*
-static uint32_t
-ocr_from_r3(uint8_t *response)
-{
-    uint32_t ocr;
-
-    ocr  = (uint32_t) response[3];
-    ocr |= (uint32_t) response[2] <<  8;
-    ocr |= (uint32_t) response[1] << 16;
-    ocr |= (uint32_t) response[0] << 24;
-
-#if 0
-    printf("Card supports: ");
-    if (ocr & (1 << 15)) {
-        printf("2.7-2.8 ");
-    }
-#endif
-
-    return ocr;
-}
-
-static uint8_t
-voltage_from_r7(uint8_t *response)
-{
-    return response[2] & 0xF;
+    return MMC_CARD_ERROR;
 }
-*/
 
 static struct mmc_cfg *
 mmc_cfg_dev(uint8_t id)
@@ -147,9 +117,7 @@ static uint8_t
 send_mmc_cmd(struct mmc_cfg *mmc, uint8_t cmd, uint32_t payload)
 {
     int n;
-    uint8_t response[4];
     uint8_t status;
-    uint8_t type;
     uint8_t crc;
 
     if (cmd & 0x80) {
@@ -195,31 +163,6 @@ send_mmc_cmd(struct mmc_cfg *mmc, uint8_t cmd, uint32_t payload)
         return status;
     }
 
-    type = response_type_by_cmd(cmd);
-
-    /* FIXME:
-     *       R1 and R1b don't have extra payload
-     *       R2 has extra status byte
-     *       R3 has 4 extra bytes for OCR
-     *       R7 has 4 extra bytes with pattern, voltage, etc
-     */
-    if (!(type == R1 || status & R_ILLEGAL_COMMAND || status & R_CRC_ERROR)) {
-        /* Read remaining data for this command */
-        for (n = 0; n < sizeof(response); n++) {
-            response[n] = (uint8_t) hal_spi_tx_val(mmc->spi_num, 0xff);
-        }
-
-        switch (type) {
-            case R3:
-                /* NOTE: ocr is defined in section 5.1 */
-                //printf("ocr=0x%08lx\n", ocr_from_r3(response));
-                break;
-            case R7:
-                //printf("voltage=0x%x\n", voltage_from_r7(response));
-                break;
-        }
-    }
-
     return status;
 }
 
@@ -243,28 +186,32 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
     int rc;
     int i;
     uint8_t status;
+    uint8_t cmd_resp[4];
     uint32_t ocr;
-    os_time_t wait_to;
+    os_time_t timeout;
+    struct mmc_cfg *mmc;
 
-    g_mmc_cfg.spi_num = spi_num;
-    g_mmc_cfg.ss_pin = ss_pin;
-    g_mmc_cfg.spi_cfg = spi_cfg;
-    g_mmc_cfg.settings = &mmc_settings;
+    /* TODO: create new struct for every new spi mmc, add to SLIST */
+    mmc = &g_mmc_cfg;
+    mmc->spi_num = spi_num;
+    mmc->ss_pin = ss_pin;
+    mmc->spi_cfg = spi_cfg;
+    mmc->settings = &mmc_settings;
 
-    hal_gpio_init_out(g_mmc_cfg.ss_pin, 1);
+    hal_gpio_init_out(mmc->ss_pin, 1);
 
-    rc = hal_spi_init(g_mmc_cfg.spi_num, g_mmc_cfg.spi_cfg, HAL_SPI_TYPE_MASTER);
+    rc = hal_spi_init(mmc->spi_num, mmc->spi_cfg, HAL_SPI_TYPE_MASTER);
     if (rc) {
         return (rc);
     }
 
-    rc = hal_spi_config(g_mmc_cfg.spi_num, g_mmc_cfg.settings);
+    rc = hal_spi_config(mmc->spi_num, mmc->settings);
     if (rc) {
         return (rc);
     }
 
-    hal_spi_set_txrx_cb(g_mmc_cfg.spi_num, NULL, NULL);
-    hal_spi_enable(g_mmc_cfg.spi_num);
+    hal_spi_set_txrx_cb(mmc->spi_num, NULL, NULL);
+    hal_spi_enable(mmc->spi_num);
 
     /**
      * NOTE: The state machine below follows:
@@ -275,21 +222,21 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
     /* give 10ms for VDD rampup */
     os_time_delay(OS_TICKS_PER_SEC / 100);
 
-    hal_gpio_write(g_mmc_cfg.ss_pin, 0);
-    hal_spi_tx_val(g_mmc_cfg.spi_num, 0xff);
+    hal_gpio_write(mmc->ss_pin, 0);
+    hal_spi_tx_val(mmc->spi_num, 0xff);
 
     /* send the required >= 74 clock cycles */
     for (i = 0; i < 74; i++) {
-        hal_spi_tx_val(g_mmc_cfg.spi_num, 0xff);
+        hal_spi_tx_val(mmc->spi_num, 0xff);
     }
 
     /* put card in idle state */
-    status = send_mmc_cmd(&g_mmc_cfg, CMD0, 0);
+    status = send_mmc_cmd(mmc, CMD0, 0);
 
+    /* No card inserted or bad card? */
     if (status != R_IDLE) {
-        /* No card inserted or bad card! */
-        hal_gpio_write(g_mmc_cfg.ss_pin, 1);
-        return mmc_error_by_status(status);
+        rc = mmc_error_by_status(status);
+        goto out;
     }
 
     /**
@@ -298,11 +245,15 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
      * NOTE: cards that are not compliant with "Physical Spec Version 2.00"
      *       will answer this with R_ILLEGAL_COMMAND.
      */
-    status = send_mmc_cmd(&g_mmc_cfg, CMD8, 0x1AA);
+    status = send_mmc_cmd(mmc, CMD8, 0x1AA);
+    for (i = 0; i < 4; i++) {
+        cmd_resp[i] = (uint8_t) hal_spi_tx_val(mmc->spi_num, 0xff);
+    }
+
     if (status & R_ILLEGAL_COMMAND) {
         /* Ver1.x SD Memory Card or Not SD Memory Card */
 
-        ocr = send_mmc_cmd(&g_mmc_cfg, CMD58, 0);
+        ocr = send_mmc_cmd(mmc, CMD58, 0);
 
         /* TODO: check if voltage range is ok! */
 
@@ -313,35 +264,69 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
         /* TODO: set blocklen */
 
     } else {
-        /* Ver2.00 or later SD Memory Card */
 
-        /* TODO:
-         * 1) check CMD8 response pattern and voltage range.
-         * 2) DONE: send ACMD41 while in R_IDLE up to 1s.
-         * 3) send CMD58, check CCS in response.
+        /**
+         * Ver2.00 or later SD Memory Card
          */
 
-#define TIME_TO_WAIT (3 * OS_TICKS_PER_SEC)
+        if (cmd_resp[3] != 0xAA) {
+            rc = MMC_RESPONSE_ERROR;
+            goto out;
+        }
+
+        /**
+         * 4.3.13 Send Interface Condition Command (CMD8)
+         *   Check VHS for 2.7-3.6V support
+         */
+        if (cmd_resp[2] != 0x01) {
+            rc = MMC_VOLTAGE_ERROR;
+            goto out;
+        }
 
-        wait_to = os_time_get() + TIME_TO_WAIT;
-        status = send_mmc_cmd(&g_mmc_cfg, ACMD41, 0x40000000); /* FIXME */
+        /**
+         * Wait for card to leave IDLE state or time out
+         */
 
-        while (status & R_IDLE) {
-            if (os_time_get() > wait_to) {
+        timeout = os_time_get() + OS_TICKS_PER_SEC;
+        for (;;) {
+            status = send_mmc_cmd(mmc, ACMD41, HCS);
+            if ((status & R_IDLE) == 0 || os_time_get() > timeout) {
                 break;
             }
             os_time_delay(OS_TICKS_PER_SEC / 10);
-            status = send_mmc_cmd(&g_mmc_cfg, ACMD41, 0);
         }
-        //printf("ACMD41 status=%x\n", status);
 
-        /* TODO: check CCS = OCR[30] */
-        status = send_mmc_cmd(&g_mmc_cfg, CMD58, 0);
-        //printf("CMD58 status=%x\n", status);
+        if (status) {
+            rc = mmc_error_by_status(status);
+            goto out;
+        }
+
+        /**
+         * Check if this is an high density card
+         */
+
+        status = send_mmc_cmd(mmc, CMD58, 0);
+        for (i = 0; i < 4; i++) {
+            cmd_resp[i] = (uint8_t) hal_spi_tx_val(mmc->spi_num, 0xff);
+        }
+        if (status == 0 && (cmd_resp[0] & (1 << 6))) {  /* FIXME: CCS */
+            /**
+             * TODO: if CCS is set this is an SDHC or SDXC card!
+             *       SDSC uses byte addressing, SDHC/SDXC block addressing
+             */
+        }
+
+#if 0  /* TODO: Can check all possible voltages supported by card */
+    printf("Card supports: ");
+    if (ocr & (1 << 15)) {
+        printf("2.7-2.8 ");
     }
+#endif
 
-    hal_gpio_write(g_mmc_cfg.ss_pin, 1);
+    }
 
+out:
+    hal_gpio_write(mmc->ss_pin, 1);
     return rc;
 }
 


[03/12] incubator-mynewt-core git commit: MMC driver WIP

Posted by cc...@apache.org.
MMC driver 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/163843f4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/163843f4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/163843f4

Branch: refs/heads/develop
Commit: 163843f4ee76194796c6f60c89bf0463386c28bc
Parents: e5bca71
Author: Fabio Utzig <ut...@utzig.org>
Authored: Wed Nov 30 17:01:49 2016 -0200
Committer: Fabio Utzig <ut...@utzig.org>
Committed: Thu Dec 8 22:00:32 2016 -0200

----------------------------------------------------------------------
 apps/mmctest/pkg.yml             |  31 +++
 apps/mmctest/src/main.c          | 369 ++++++++++++++++++++++++++++++++++
 apps/mmctest/syscfg.yml          |  22 ++
 hw/drivers/mmc/include/mmc/mmc.h |  52 +++++
 hw/drivers/mmc/pkg.yml           |  27 +++
 hw/drivers/mmc/src/mmc.c         | 311 ++++++++++++++++++++++++++++
 6 files changed, 812 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/163843f4/apps/mmctest/pkg.yml
----------------------------------------------------------------------
diff --git a/apps/mmctest/pkg.yml b/apps/mmctest/pkg.yml
new file mode 100644
index 0000000..c42160c
--- /dev/null
+++ b/apps/mmctest/pkg.yml
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: apps/mmctest
+pkg.type: app
+pkg.description: TBD
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - sys/console/full
+    - kernel/os
+    - hw/drivers/mmc
+    - hw/mcu/stm/stm32f4xx

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/163843f4/apps/mmctest/src/main.c
----------------------------------------------------------------------
diff --git a/apps/mmctest/src/main.c b/apps/mmctest/src/main.c
new file mode 100755
index 0000000..34847ea
--- /dev/null
+++ b/apps/mmctest/src/main.c
@@ -0,0 +1,369 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include "sysinit/sysinit.h"
+#include "os/os.h"
+#include "bsp/bsp.h"
+#include "hal/hal_gpio.h"
+#include "hal/hal_spi.h"
+#include <mmc/mmc.h>
+#include <mcu/stm32f4xx_mynewt_hal.h>
+#include <os/os_dev.h>
+#include <assert.h>
+#include <string.h>
+#include <console/console.h>
+#ifdef ARCH_sim
+#include <mcu/mcu_sim.h>
+#endif
+
+/* The spi txrx callback */
+struct sblinky_spi_cb_arg
+{
+    int transfers;
+    int txlen;
+    uint32_t tx_rx_bytes;
+};
+struct sblinky_spi_cb_arg spi_cb_obj;
+void *spi_cb_arg;
+
+/* Task 1 */
+#define TASK1_PRIO (1)
+#define TASK1_STACK_SIZE    OS_STACK_ALIGN(1024)
+struct os_task task1;
+
+/* Task 2 */
+#define TASK2_PRIO (2)
+#define TASK2_STACK_SIZE    OS_STACK_ALIGN(512)
+static struct os_task task2;
+
+#define TASK3_PRIO (3)
+#define TASK3_STACK_SIZE    OS_STACK_ALIGN(512)
+static struct os_task task3;
+
+static struct os_eventq mmctest_evq;
+
+/* Global test semaphore */
+struct os_sem g_test_sem;
+
+/* For LED toggling */
+int g_led_pin;
+
+static const int SPI_SS_PIN   = MCU_GPIO_PORTA(4);
+static const int SPI_SCK_PIN  = MCU_GPIO_PORTA(5);
+static const int SPI_MISO_PIN = MCU_GPIO_PORTA(6);
+static const int SPI_MOSI_PIN = MCU_GPIO_PORTA(7);
+
+uint8_t g_spi_tx_buf[32];
+uint8_t g_spi_last_tx_buf[32];
+uint8_t g_spi_rx_buf[32];
+uint32_t g_spi_xfr_num;
+uint8_t g_spi_null_rx;
+uint8_t g_last_tx_len;
+
+static
+void mmctest_validate_last(int len)
+{
+    int i;
+    int curlen;
+    int remlen;
+    int curindex;
+    uint8_t expval;
+
+    if (g_spi_null_rx == 0) {
+        expval = 0xaa;
+        if (g_last_tx_len < len) {
+            curlen = g_last_tx_len;
+            remlen = len - g_last_tx_len;
+        } else {
+            curlen = len;
+            remlen = 0;
+        }
+        for (i = 0; i < curlen; ++i) {
+            if (g_spi_rx_buf[i] != g_spi_last_tx_buf[i]) {
+                assert(0);
+            }
+        }
+        curindex = curlen;
+        for (i = 0; i < remlen; ++i) {
+            if (g_spi_rx_buf[curindex + i] != expval) {
+                assert(0);
+            }
+        }
+    }
+}
+
+void
+sblinky_spi_irqm_handler(void *arg, int len)
+{
+    int i;
+    struct sblinky_spi_cb_arg *cb;
+
+    //hal_gpio_write(SPI_SS_PIN, 1);
+
+    assert(arg == spi_cb_arg);
+    if (spi_cb_arg) {
+        cb = (struct sblinky_spi_cb_arg *)arg;
+        assert(len == cb->txlen);
+        ++cb->transfers;
+    }
+
+    /* Make sure we get back the data we expect! */
+    if (g_spi_xfr_num == 1) {
+        /* The first time we expect entire buffer to be filled with 0x88 */
+        for (i = 0; i < len; ++i) {
+            if (g_spi_rx_buf[i] != 0x88) {
+                assert(0);
+            }
+        }
+
+        /* copy current tx buf to last */
+        memcpy(g_spi_last_tx_buf, g_spi_tx_buf, len);
+    } else {
+        /* Check that we received what we last sent */
+        mmctest_validate_last(len);
+    }
+    ++g_spi_xfr_num;
+}
+
+void
+task1_handler(void *arg)
+{
+    //int i;
+    int rc;
+    //uint16_t rxval;
+    //uint8_t last_val;
+    //uint8_t spi_nb_cntr;
+    //uint8_t spi_b_cntr;
+
+    struct stm32f4_hal_spi_cfg spi_cfg = {
+        .ss_pin   = SPI_SS_PIN,
+        .sck_pin  = SPI_SCK_PIN,
+        .miso_pin = SPI_MISO_PIN,
+        .mosi_pin = SPI_MOSI_PIN,
+        .irq_prio = 2
+    };
+
+    rc = mmc_init(0, &spi_cfg, spi_cfg.ss_pin);
+    printf("mmc_init %d\n", rc);
+
+#if 0
+    /*
+     * Send some bytes in a non-blocking manner to SPI using tx val. The
+     * slave should send back 0x77.
+     */
+    g_spi_tx_buf[0] = 0xde;
+    g_spi_tx_buf[1] = 0xad;
+    g_spi_tx_buf[2] = 0xbe;
+    g_spi_tx_buf[3] = 0xef;
+    hal_gpio_write(SPI_SS_PIN, 0);
+    for (i = 0; i < 4; ++i) {
+        rxval = hal_spi_tx_val(0, g_spi_tx_buf[i]);
+        assert(rxval == 0x77);
+        g_spi_rx_buf[i] = (uint8_t)rxval;
+    }
+    hal_gpio_write(SPI_SS_PIN, 1);
+    ++g_spi_xfr_num;
+
+    /* Set up the callback to use when non-blocking API used */
+    hal_spi_disable(0);
+    spi_cb_arg = &spi_cb_obj;
+    spi_cb_obj.txlen = 32;
+    hal_spi_set_txrx_cb(0, sblinky_spi_irqm_handler, spi_cb_arg);
+    hal_spi_enable(0);
+    spi_nb_cntr = 0;
+    spi_b_cntr = 0;
+
+    while (1) {
+        /* Get random length to send */
+        g_last_tx_len = spi_cb_obj.txlen;
+        spi_cb_obj.txlen = (rand() & 0x1F) + 1;
+        memcpy(g_spi_last_tx_buf, g_spi_tx_buf, g_last_tx_len);
+        last_val = g_spi_last_tx_buf[g_last_tx_len - 1];
+        for (i= 0; i < spi_cb_obj.txlen; ++i) {
+            g_spi_tx_buf[i] = (uint8_t)(last_val + i);
+        }
+
+        if (g_spi_xfr_num & 1) {
+            /* Send non-blocking */
+            ++spi_nb_cntr;
+            assert(hal_gpio_read(SPI_SS_PIN) == 1);
+            hal_gpio_write(SPI_SS_PIN, 0);
+#if 0
+            if (spi_nb_cntr == 7) {
+                g_spi_null_rx = 1;
+                rc = hal_spi_txrx_noblock(0, g_spi_tx_buf, NULL, 32);
+            } else {
+                g_spi_null_rx = 0;
+                rc = hal_spi_txrx_noblock(0, g_spi_tx_buf, g_spi_rx_buf, 32);
+            }
+            assert(!rc);
+#else
+            g_spi_null_rx = 0;
+            rc = hal_spi_txrx_noblock(0, g_spi_tx_buf, g_spi_rx_buf,
+                                      spi_cb_obj.txlen);
+            assert(!rc);
+            console_printf("a transmitted: ");
+            for (i = 0; i < spi_cb_obj.txlen; i++) {
+                console_printf("%2x ", g_spi_tx_buf[i]);
+            }
+            console_printf("\n");
+            console_printf("received: ");
+            for (i = 0; i < spi_cb_obj.txlen; i++) {
+                console_printf("%2x ", g_spi_rx_buf[i]);
+            }
+            console_printf("\n");
+#endif
+        } else {
+            /* Send blocking */
+            ++spi_b_cntr;
+            assert(hal_gpio_read(SPI_SS_PIN) == 1);
+            hal_gpio_write(SPI_SS_PIN, 0);
+#if 0
+            if (spi_b_cntr == 7) {
+                g_spi_null_rx = 1;
+                rc = hal_spi_txrx(0, g_spi_tx_buf, NULL, 32);
+                spi_b_cntr = 0;
+            } else {
+                g_spi_null_rx = 0;
+                rc = hal_spi_txrx(0, g_spi_tx_buf, g_spi_rx_buf, 32);
+            }
+            assert(!rc);
+            hal_gpio_write(SPI_SS_PIN, 1);
+            mmctest_validate_last(spi_cb_obj.txlen);
+#else
+            rc = hal_spi_txrx(0, g_spi_tx_buf, g_spi_rx_buf, spi_cb_obj.txlen);
+            assert(!rc);
+            hal_gpio_write(SPI_SS_PIN, 1);
+            console_printf("b transmitted: ");
+            for (i = 0; i < spi_cb_obj.txlen; i++) {
+                console_printf("%2x ", g_spi_tx_buf[i]);
+            }
+            console_printf("\n");
+            console_printf("received: ");
+            for (i = 0; i < spi_cb_obj.txlen; i++) {
+                console_printf("%2x ", g_spi_rx_buf[i]);
+            }
+            console_printf("\n");
+            mmctest_validate_last(spi_cb_obj.txlen);
+            ++g_spi_xfr_num;
+#endif
+        }
+    }
+#endif
+
+    while (1) {
+        os_time_delay(OS_TICKS_PER_SEC);
+    }
+}
+
+/**
+ * This task serves as a container for the shell and newtmgr packages.  These
+ * packages enqueue timer events when they need this task to do work.
+ */
+static void
+task2_handler(void *arg)
+{
+    while (1) {
+        os_eventq_run(&mmctest_evq);
+    }
+}
+
+static void
+task3_handler(void *arg)
+{
+    while (1) {
+        os_time_delay(OS_TICKS_PER_SEC);
+        hal_gpio_toggle(g_led_pin);
+    }
+}
+
+/**
+ * init_tasks
+ *
+ * Called by main.c after sysinit(). This function performs initializations
+ * that are required before tasks are running.
+ *
+ * @return int 0 success; error otherwise.
+ */
+static void
+init_tasks(void)
+{
+    os_stack_t *pstack;
+
+    /* Initialize global test semaphore */
+    os_sem_init(&g_test_sem, 0);
+
+    pstack = malloc(sizeof(os_stack_t)*TASK1_STACK_SIZE);
+    assert(pstack);
+
+    os_task_init(&task1, "task1", task1_handler, NULL,
+            TASK1_PRIO, OS_WAIT_FOREVER, pstack, TASK1_STACK_SIZE);
+
+    pstack = malloc(sizeof(os_stack_t)*TASK2_STACK_SIZE);
+    assert(pstack);
+
+    os_task_init(&task2, "task2", task2_handler, NULL,
+            TASK2_PRIO, OS_WAIT_FOREVER, pstack, TASK2_STACK_SIZE);
+
+    pstack = malloc(sizeof(os_stack_t)*TASK3_STACK_SIZE);
+    assert(pstack);
+
+    os_task_init(&task3, "task3", task3_handler, NULL,
+            TASK3_PRIO, OS_WAIT_FOREVER, pstack, TASK3_STACK_SIZE);
+
+    /* Initialize eventq and designate it as the default.  Packages that need
+     * to schedule work items will piggyback on this eventq.  Example packages
+     * which do this are sys/shell and mgmt/newtmgr.
+     */
+    os_eventq_init(&mmctest_evq);
+    os_eventq_dflt_set(&mmctest_evq);
+}
+
+/**
+ * main
+ *
+ * The main function for the project. This function initializes the os, calls
+ * init_tasks to initialize tasks (and possibly other objects), then starts the
+ * OS. We should not return from os start.
+ *
+ * @return int NOTE: this function should never return!
+ */
+int
+main(int argc, char **argv)
+{
+    int rc;
+
+#ifdef ARCH_sim
+    mcu_sim_parse_args(argc, argv);
+#endif
+
+    sysinit();
+
+    /* Set the led pin for the devboard */
+    g_led_pin = LED_BLINK_PIN;
+    hal_gpio_init_out(g_led_pin, 0);
+
+    init_tasks();
+    os_start();
+
+    /* os start should never return. If it does, this should be an error */
+    assert(0);
+
+    return rc;
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/163843f4/apps/mmctest/syscfg.yml
----------------------------------------------------------------------
diff --git a/apps/mmctest/syscfg.yml b/apps/mmctest/syscfg.yml
new file mode 100644
index 0000000..40c4c52
--- /dev/null
+++ b/apps/mmctest/syscfg.yml
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Package: apps/mmctest
+
+syscfg.vals:
+    SHELL_TASK: 0

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/163843f4/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
new file mode 100644
index 0000000..1a03edb
--- /dev/null
+++ b/hw/drivers/mmc/include/mmc/mmc.h
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef __MMC_H__
+#define __MMC_H__
+
+#include <os/os_dev.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * MMC driver errors.
+ */
+#define MMC_OK              (0)
+#define MMC_CARD_ERROR      (1)  /* Is there a card installed? */
+#define MMC_TIMEOUT         (2)
+
+/**
+ * Initialize the MMC driver
+ *
+ * @param spi_num Number of the SPI channel to be used by MMC
+ * @param spi_cfg Low-level device specific SPI configuration
+ * @param ss_pin Number of SS pin if SW controlled, -1 otherwise
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+mmc_init(int spi_num, void *spi_cfg, int ss_pin);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ADC_H__ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/163843f4/hw/drivers/mmc/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/drivers/mmc/pkg.yml b/hw/drivers/mmc/pkg.yml
new file mode 100644
index 0000000..ee98870
--- /dev/null
+++ b/hw/drivers/mmc/pkg.yml
@@ -0,0 +1,27 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: hw/drivers/mmc
+pkg.description: MMC interfaces
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - hw/hal

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/163843f4/hw/drivers/mmc/src/mmc.c
----------------------------------------------------------------------
diff --git a/hw/drivers/mmc/src/mmc.c b/hw/drivers/mmc/src/mmc.c
new file mode 100644
index 0000000..6aefce4
--- /dev/null
+++ b/hw/drivers/mmc/src/mmc.c
@@ -0,0 +1,311 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <hal/hal_spi.h>
+#include <hal/hal_gpio.h>
+
+#include <mmc/mmc.h>
+
+#include <stdio.h>
+
+/* Current used MMC commands */
+#define CMD0                (0)            /* GO_IDLE_STATE */
+#define CMD1                (1)            /* SEND_OP_COND (MMC) */
+#define CMD8                (8)            /* SEND_IF_COND */
+#define CMD16               (16)           /* SET_BLOCKLEN */
+#define CMD17               (17)           /* READ_SINGLE_BLOCK */
+#define CMD18               (18)           /* READ_MULTIPLE_BLOCK */
+#define CMD24               (24)           /* WRITE_BLOCK */
+#define CMD25               (25)           /* WRITE_MULTIPLE_BLOCK */
+#define CMD55               (55)           /* APP_CMD */
+#define CMD58               (58)           /* READ_OCR */
+#define ACMD41              (0x80 + 41)    /* SEND_OP_COND (SDC) */
+
+/* Response types */
+#define R1                  (0)
+#define R1b                 (1)
+#define R2                  (2)
+#define R3                  (3)
+#define R7                  (4)
+
+/* Response status */
+#define R_IDLE              (0x01)
+#define R_ERASE_RESET       (0x02)
+#define R_ILLEGAL_COMMAND   (0x04)
+#define R_CRC_ERROR         (0x08)
+#define R_ERASE_ERROR       (0x10)
+#define R_ADDR_ERROR        (0x20)
+#define R_PARAM_ERROR       (0x40)
+
+static struct hal_spi_settings mmc_settings = {
+    .data_order = HAL_SPI_MSB_FIRST,
+    .data_mode  = HAL_SPI_MODE0,
+    /* XXX: MMC initialization accepts clocks in the range 100-400KHz */
+    .baudrate   = 100,
+    .word_size  = HAL_SPI_WORD_SIZE_8BIT,
+};
+
+static int g_spi_num = -1;
+static int g_ss_pin = -1;
+
+/**
+ * TODO: switch to high-speed SPI after initialization.
+ */
+
+static int
+mmc_error_by_status(uint8_t status)
+{
+    return MMC_OK;
+}
+
+static int8_t
+response_type_by_cmd(uint8_t cmd)
+{
+    switch (cmd) {
+        case CMD8   : return R7;
+        case CMD58  : return R3;
+    }
+    return R1;
+}
+
+static uint32_t
+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;
+
+    return ocr;
+}
+
+static uint8_t
+status_from_r1(uint8_t *response)
+{
+    return response[0];
+}
+
+static uint8_t
+voltage_from_r7(uint8_t *response)
+{
+    return response[3] & 0xF;
+}
+
+static uint8_t
+send_mmc_cmd(uint8_t cmd, uint32_t payload)
+{
+    int n;
+    uint8_t response[5];
+    uint8_t status;
+    uint8_t type;
+
+    if (cmd & 0x80) {
+        /* TODO: refactor recursion? */
+        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));
+
+    hal_spi_tx_val(g_spi_num, payload >> 24 & 0xff);
+    hal_spi_tx_val(g_spi_num, payload >> 16 & 0xff);
+    hal_spi_tx_val(g_spi_num, payload >>  8 & 0xff);
+    hal_spi_tx_val(g_spi_num, payload       & 0xff);
+
+    /**
+     * 7.2.2 Bus Transfer Protection
+     *   NOTE: SD is in CRC off mode by default but CMD0 and CMD8 always
+     *   require a valid CRC.
+     *   NOTE: CRC can be turned on with CMD59 (CRC_ON_OFF).
+     */
+    if (cmd == CMD0) {
+        hal_spi_tx_val(g_spi_num, 0x95);
+    } else if (cmd == CMD8) {
+        hal_spi_tx_val(g_spi_num, 0x87);
+    } else {
+        /* Any value is OK */
+        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);
+
+    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);
+            }
+
+            printf("response=[%0x][%0x][%0x][%0x]\n",
+                    response[1], response[2], response[3], response[4]);
+
+            switch (type) {
+                case R3:
+                    /* NOTE: ocr is defined in section 5.1 */
+                    printf("ocr=0x%08lx\n", ocr_from_r3(response));
+                    break;
+                case R7:
+                    printf("voltage=0x%x\n", voltage_from_r7(response));
+                    break;
+            }
+        }
+    }
+
+    printf("\n");
+
+    hal_gpio_write(g_ss_pin, 1);
+
+    return status;
+}
+
+/**
+ * NOTE:
+ */
+
+/**
+ * Initialize the MMC driver
+ *
+ * @param spi_num Number of the SPI channel to be used by MMC
+ * @param spi_cfg Low-level device specific SPI configuration
+ * @param ss_pin Number of SS pin if SW controlled, -1 otherwise
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+mmc_init(int spi_num, void *spi_cfg, int ss_pin)
+{
+    int rc;
+    int i;
+    uint8_t status;
+    uint32_t ocr;
+
+    g_ss_pin = ss_pin;
+    g_spi_num = spi_num;
+
+    if (g_ss_pin != -1) {
+        hal_gpio_init_out(g_ss_pin, 1);
+    }
+
+    rc = hal_spi_init(g_spi_num, spi_cfg, HAL_SPI_TYPE_MASTER);
+    if (rc) {
+        return (rc);
+    }
+
+    rc = hal_spi_config(g_spi_num, &mmc_settings);
+    if (rc) {
+        return (rc);
+    }
+
+    hal_spi_set_txrx_cb(0, NULL, NULL);
+    hal_spi_enable(0);
+
+    /**
+     * NOTE: The state machine below follows:
+     *       Section 6.4.1: Power Up Sequence for SD Bus Interface.
+     *       Section 7.2.1: Mode Selection and Initialization.
+     */
+
+    /* 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);
+
+    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! */
+        return mmc_error_by_status(status);
+    }
+
+    /**
+     * 4.3.13: Ask for 2.7-3.3V range, send 0xAA pattern
+     *
+     * NOTE: cards that are not compliant with "Physical Spec Version 2.00"
+     *       will answer this with R_ILLEGAL_COMMAND.
+     */
+    status = send_mmc_cmd(CMD8, 0x1AA);
+    if (status & R_ILLEGAL_COMMAND) {
+        /* Ver1.x SD Memory Card or Not SD Memory Card */
+
+        ocr = send_mmc_cmd(CMD58, 0);
+
+        /* TODO: check if voltage range is ok! */
+
+        if (ocr & R_ILLEGAL_COMMAND) {
+
+        }
+    } 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.
+         * 3) send CMD58, check CCS in response.
+         */
+
+        status = send_mmc_cmd(ACMD41, 0);
+
+        /* CCS = OCR[30] */
+        status = send_mmc_cmd(CMD58, 0);
+    }
+
+    return rc;
+}
+
+/**
+ * @return 0 on success, non-zero on failure
+ */
+int
+mmc_read(void *buf, size_t len)
+{
+    hal_gpio_write(g_ss_pin, 0);
+    hal_gpio_write(g_ss_pin, 1);
+    return 0;
+}
+
+/**
+ * @return 0 on success, non-zero on failure
+ */
+int
+mmc_write(void *buf, size_t len)
+{
+    return 0;
+}


[07/12] incubator-mynewt-core git commit: Write support working - WIP

Posted by cc...@apache.org.
Write support working - 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/70bbb748
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/70bbb748
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/70bbb748

Branch: refs/heads/develop
Commit: 70bbb748105ac8332d60625ac2183ff9fefd2c7e
Parents: f4aaf68
Author: Fabio Utzig <ut...@utzig.org>
Authored: Tue Dec 6 16:37:03 2016 -0200
Committer: Fabio Utzig <ut...@utzig.org>
Committed: Thu Dec 8 22:00:32 2016 -0200

----------------------------------------------------------------------
 hw/drivers/mmc/include/mmc/mmc.h |  2 +-
 hw/drivers/mmc/src/mmc.c         | 94 ++++++++++++++++++++---------------
 2 files changed, 55 insertions(+), 41 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/70bbb748/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 add9b9b..c9b03af 100644
--- a/hw/drivers/mmc/include/mmc/mmc.h
+++ b/hw/drivers/mmc/include/mmc/mmc.h
@@ -71,7 +71,7 @@ mmc_read(uint32_t addr, void *buf, size_t len);
  * @return 0 on success, non-zero on failure
  */
 int
-mmc_write(uint32_t addr, void *buf, size_t len);
+mmc_write(uint32_t addr, const void *buf, size_t len);
 
 #ifdef __cplusplus
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/70bbb748/hw/drivers/mmc/src/mmc.c
----------------------------------------------------------------------
diff --git a/hw/drivers/mmc/src/mmc.c b/hw/drivers/mmc/src/mmc.c
index 92acc45..d6e4a0d 100644
--- a/hw/drivers/mmc/src/mmc.c
+++ b/hw/drivers/mmc/src/mmc.c
@@ -104,6 +104,7 @@ response_type_by_cmd(uint8_t cmd)
     return R1;
 }
 
+/*
 static uint32_t
 ocr_from_r3(uint8_t *response)
 {
@@ -129,6 +130,7 @@ voltage_from_r7(uint8_t *response)
 {
     return response[2] & 0xF;
 }
+*/
 
 static uint8_t
 send_mmc_cmd(uint8_t cmd, uint32_t payload)
@@ -168,12 +170,13 @@ send_mmc_cmd(uint8_t cmd, uint32_t payload)
 
     //printf("==> sending cmd %d\n", cmd & ~0x80);
 
-    n = 10;
-    do {
+    for (n = 255; n > 0; n--) {
         status = hal_spi_tx_val(g_spi_num, 0xff);
-    } while ((status & 0x80) && --n);
+        if ((status & 0x80) == 0) break;
+        //os_time_delay(OS_TICKS_PER_SEC / 1000);
+    }
 
-    if (!n) {
+    if (n == 0) {
         return status;
     }
 
@@ -191,21 +194,13 @@ send_mmc_cmd(uint8_t cmd, uint32_t payload)
             response[n] = (uint8_t) hal_spi_tx_val(g_spi_num, 0xff);
         }
 
-#if 0
-        printf("response=");
-        for (n = 0; n < sizeof(response); n++) {
-            printf("[%02x]", response[n]);
-        }
-        printf(" \n");
-#endif
-
         switch (type) {
             case R3:
                 /* NOTE: ocr is defined in section 5.1 */
-                printf("ocr=0x%08lx\n", ocr_from_r3(response));
+                //printf("ocr=0x%08lx\n", ocr_from_r3(response));
                 break;
             case R7:
-                printf("voltage=0x%x\n", voltage_from_r7(response));
+                //printf("voltage=0x%x\n", voltage_from_r7(response));
                 break;
         }
     }
@@ -265,6 +260,7 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
     os_time_delay(OS_TICKS_PER_SEC / 100);
 
     hal_gpio_write(g_ss_pin, 0);
+    hal_spi_tx_val(0, 0xff);
 
     /* send the required >= 74 clock cycles */
     for (i = 0; i < 74; i++) {
@@ -321,9 +317,11 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
             os_time_delay(OS_TICKS_PER_SEC / 10);
             status = send_mmc_cmd(ACMD41, 0);
         }
+        //printf("ACMD41 status=%x\n", status);
 
         /* TODO: check CCS = OCR[30] */
         status = send_mmc_cmd(CMD58, 0);
+        //printf("CMD58 status=%x\n", status);
     }
 
     hal_gpio_write(g_ss_pin, 1);
@@ -343,7 +341,7 @@ mmc_read(uint32_t addr, void *buf, size_t len)
     size_t block_len;
     size_t block_count;
     os_time_t timeout;
-    size_t block_addr;
+    uint32_t block_addr;
     size_t offset;
     size_t index;
     size_t amount;
@@ -355,7 +353,7 @@ mmc_read(uint32_t addr, void *buf, size_t len)
     block_addr = addr / BLOCK_LEN;
     offset = addr - (block_addr * BLOCK_LEN);
 
-    //printf("block_addr=%d, offset=%d\n", block_addr, offset);
+    //printf("addr=0x%lx, block_addr=0x%lx, offset=%d\n", addr, block_addr, offset);
     //printf("len=%d, block_len=%d, block_count=%d\n", len, block_len, block_count);
 
     cmd = (block_count == 1) ? CMD17 : CMD18;
@@ -396,7 +394,7 @@ mmc_read(uint32_t addr, void *buf, size_t len)
 
             amount = MIN(BLOCK_LEN - offset, len);
 
-            printf("copying %d bytes to index %d\n", amount, index);
+            //printf("copying %d bytes to index %d\n", amount, index);
             memcpy(((uint8_t *)buf + index), &g_block_buf[offset], amount);
 
             offset = 0;
@@ -422,7 +420,7 @@ mmc_read(uint32_t addr, void *buf, size_t len)
  * @return 0 on success, non-zero on failure
  */
 int
-mmc_write(uint32_t addr, void *buf, size_t len)
+mmc_write(uint32_t addr, const void *buf, size_t len)
 {
     uint8_t cmd;
     uint8_t res;
@@ -430,16 +428,27 @@ mmc_write(uint32_t addr, void *buf, size_t len)
     size_t block_len;
     size_t block_count;
     os_time_t timeout;
-    size_t block_addr;
+    uint32_t block_addr;
     size_t offset;
     size_t index;
     size_t amount;
+    int status;
+
+    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);
 
+    /**
+     * This code ensures that if the requested address doesn't align with the
+     * beginning address of a sector, the initial bytes are first read to the
+     * buffer to be then written later.
+     *
+     * NOTE: this code will never run when using a FS that is sector addressed
+     * like FAT (offset is always 0).
+     */
     if (offset) {
         res = send_mmc_cmd(CMD17, block_addr);
         if (res != MMC_OK) {
@@ -476,21 +485,8 @@ mmc_write(uint32_t addr, void *buf, size_t len)
         return MMC_CARD_ERROR;
     }
 
-    /**
-     * 7.3.3 Control tokens
-     *   Wait up to 500ms for control token.
-     */
-    timeout = os_time_get() + OS_TICKS_PER_SEC / 2;
-    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);
-
-    if (res == 0xFF) {
-        hal_gpio_write(g_ss_pin, 1);
-        return MMC_CARD_ERROR;
-    }
+    /* FIXME: one byte gap, is this really required? */
+    hal_spi_tx_val(g_spi_num, 0xff);
 
     index = 0;
     do {
@@ -530,14 +526,32 @@ mmc_write(uint32_t addr, void *buf, size_t len)
 
     } while (len);
 
-    hal_gpio_write(g_ss_pin, 1);
+    /* TODO: send stop tran token */
+    if (cmd == CMD25) {
+    }
 
     res &= 0x1f;
-    if (res == 0x0b) {
-        return MMC_CRC_ERROR;
-    } else if (res == 0x0d) {
-        return MMC_WRITE_ERROR;
+    //printf("final response token: 0x%x\n", res);
+    switch (res) {
+        case 0x05:
+            status = MMC_OK;
+            break;
+        case 0x0b:
+            status = MMC_CRC_ERROR;
+            break;
+        case 0x0d:  /* passthrough */
+        default:
+            status = MMC_WRITE_ERROR;
     }
 
-    return MMC_OK;
+    timeout = os_time_get() + 5 * OS_TICKS_PER_SEC;
+    do {
+        res = hal_spi_tx_val(g_spi_num, 0xff);
+        if (res) break;
+        os_time_delay(OS_TICKS_PER_SEC / 100);
+    } while (os_time_get() < timeout);
+
+    hal_gpio_write(g_ss_pin, 1);
+
+    return status;
 }