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;
}