You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by st...@apache.org on 2016/12/18 21:56:54 UTC
[26/50] incubator-mynewt-core git commit: Better error checking +
cleanups/refactorings
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/373ae607
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/373ae607
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/373ae607
Branch: refs/heads/sensors_branch
Commit: 373ae607dccf0a0a40f041507384510c6505253f
Parents: 41c17c4
Author: Fabio Utzig <ut...@utzig.org>
Authored: Tue Dec 6 23:14:57 2016 -0200
Committer: Sterling Hughes <st...@apache.org>
Committed: Sun Dec 18 13:56:16 2016 -0800
----------------------------------------------------------------------
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/373ae607/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/373ae607/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;
}