diff options
author | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2011-05-01 09:10:22 +0000 |
---|---|---|
committer | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2011-05-01 09:10:22 +0000 |
commit | 40c7b22bf43d795d9e6822f67907a1665aa6d7b6 (patch) | |
tree | f2b67a5fcdb85a4ef348c7fbe29184b76b316433 /os/hal | |
parent | dd9cac5ffa29031b1175bb750e587a20362f5276 (diff) | |
download | ChibiOS-40c7b22bf43d795d9e6822f67907a1665aa6d7b6.tar.gz ChibiOS-40c7b22bf43d795d9e6822f67907a1665aa6d7b6.tar.bz2 ChibiOS-40c7b22bf43d795d9e6822f67907a1665aa6d7b6.zip |
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2908 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal')
-rw-r--r-- | os/hal/include/sdc.h | 12 | ||||
-rw-r--r-- | os/hal/platforms/STM32/sdc_lld.c | 34 | ||||
-rw-r--r-- | os/hal/platforms/STM32/sdc_lld.h | 11 | ||||
-rw-r--r-- | os/hal/src/sdc.c | 49 |
4 files changed, 105 insertions, 1 deletions
diff --git a/os/hal/include/sdc.h b/os/hal/include/sdc.h index 860bbbbda..027eee2c0 100644 --- a/os/hal/include/sdc.h +++ b/os/hal/include/sdc.h @@ -36,6 +36,18 @@ /*===========================================================================*/
#define SDC_CMD_GO_IDLE_STATE 0
+#define SDC_CMD_SEND_IF_COND 8
+#define SDC_CMD_APP_OP_COND 41
+#define SDC_CMD_APP_CMD 55
+
+#define SDC_MODE_CARDTYPE_MASK 0xF
+#define SDC_MODE_CARDTYPE_SD 0 /**< Old SD card. */
+#define SDC_MODE_CARDTYPE_SDV20 1 /**< Card is V2.0 compliant. */
+#define SDC_MODE_CARDTYPE_MMC 2 /**< Card is MMC. */
+
+#define SDC_CMD8_PATTERN 0x000001AA
+
+#define SDC_ACMD41_RETRY 100
/*===========================================================================*/
/* Driver pre-compile time settings. */
diff --git a/os/hal/platforms/STM32/sdc_lld.c b/os/hal/platforms/STM32/sdc_lld.c index 8517a040d..626702084 100644 --- a/os/hal/platforms/STM32/sdc_lld.c +++ b/os/hal/platforms/STM32/sdc_lld.c @@ -189,6 +189,8 @@ void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) { * @brief Sends an SDIO command with no response expected.
*
* @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in[ cmd card command
+ * @param[in] arg command argument
*
* @notapi
*/
@@ -206,6 +208,9 @@ void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg) { * @brief Sends an SDIO command with a short response expected.
*
* @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in[ cmd card command
+ * @param[in] arg command argument
+ * @param[out] resp pointer to the response buffer (one word)
* @return The operation status.
* @retval FALSE the operation succeeded.
* @retval TRUE the operation failed because timeout, CRC check or
@@ -215,13 +220,28 @@ void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg) { */
bool_t sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
uint32_t *resp) {
+ uint32_t sta;
+ (void)sdcp;
+ SDIO->ARG = arg;
+ SDIO->CMD = (uint32_t)cmd | SDIO_CMD_WAITRESP_0 | SDIO_CMD_CPSMEN;
+ while (((sta = SDIO->STA) & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT |
+ SDIO_STA_CCRCFAIL)) == 0)
+ ;
+ SDIO->ICR = 0xFFFFFFFF;
+ if ((sta & (SDIO_STA_CTIMEOUT | SDIO_STA_CCRCFAIL)) != 0)
+ return TRUE;
+ *resp = SDIO->RESP1;
+ return FALSE;
}
/**
* @brief Sends an SDIO command with a long response expected.
*
* @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in[ cmd card command
+ * @param[in] arg command argument
+ * @param[out] resp pointer to the response buffer (four words)
* @return The operation status.
* @retval FALSE the operation succeeded.
* @retval TRUE the operation failed because timeout, CRC check or
@@ -232,6 +252,20 @@ bool_t sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, bool_t sdc_lld_send_cmd_long(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
uint32_t *resp) {
+ uint32_t sta;
+
+ (void)sdcp;
+ SDIO->ARG = arg;
+ SDIO->CMD = (uint32_t)cmd | SDIO_CMD_WAITRESP_0 | SDIO_CMD_WAITRESP_1 |
+ SDIO_CMD_CPSMEN;
+ while (((sta = SDIO->STA) & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT |
+ SDIO_STA_CCRCFAIL)) == 0)
+ ;
+ SDIO->ICR = 0xFFFFFFFF;
+ if ((sta & (SDIO_STA_CTIMEOUT | SDIO_STA_CCRCFAIL)) != 0)
+ return TRUE;
+ *resp = SDIO->RESP1;
+ return FALSE;
}
#endif /* HAL_USE_SDC */
diff --git a/os/hal/platforms/STM32/sdc_lld.h b/os/hal/platforms/STM32/sdc_lld.h index 729244e91..fff6133b2 100644 --- a/os/hal/platforms/STM32/sdc_lld.h +++ b/os/hal/platforms/STM32/sdc_lld.h @@ -99,6 +99,11 @@ typedef enum { } sdcbusmode_t;
/**
+ * @brief Type of card flags.
+ */
+typedef uint32_t sdcmode_t;
+
+/**
* @brief Type of a structure representing an SDC driver.
*/
typedef struct SDCDriver SDCDriver;
@@ -123,6 +128,10 @@ struct SDCDriver { * @brief Current configuration data.
*/
const SDCConfig *config;
+ /**
+ * @brief Various flags regarding the mounted card.
+ */
+ sdcmode_t cardmode;
/* End of the mandatory fields.*/
};
@@ -144,7 +153,7 @@ extern "C" { void sdc_lld_init(void);
void sdc_lld_start(SDCDriver *sdcp);
void sdc_lld_stop(SDCDriver *sdcp);
- void sdc_lld_set_init_clk(SDCDriver *sdcp);
+ void sdc_lld_start_clk(SDCDriver *sdcp);
void sdc_lld_set_data_clk(SDCDriver *sdcp);
void sdc_lld_stop_clk(SDCDriver *sdcp);
void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode);
diff --git a/os/hal/src/sdc.c b/os/hal/src/sdc.c index b64dcf9c5..07f25aa65 100644 --- a/os/hal/src/sdc.c +++ b/os/hal/src/sdc.c @@ -127,6 +127,7 @@ void sdcStop(SDCDriver *sdcp) { * @api
*/
bool_t sdcConnect(SDCDriver *sdcp) {
+ uint32_t resp;
chDbgCheck(sdcp != NULL, "sdcConnect");
@@ -135,12 +136,60 @@ bool_t sdcConnect(SDCDriver *sdcp) { sdcp->state = SDC_INITNG;
chSysUnlock();
+ /* Resets card attributes.*/
+ sdcp->cardmode = 0;
+
+ /* Card clock initialization.*/
sdc_lld_start_clk(sdcp);
+ /* Enforces the initial card state.*/
sdc_lld_send_cmd_none(sdcp, SDC_CMD_GO_IDLE_STATE, 0);
+ /* V2.0 cards detection.*/
+ if (!sdc_lld_send_cmd_short(sdcp, SDC_CMD_SEND_IF_COND,
+ SDC_CMD8_PATTERN, &resp))
+ sdcp->cardmode |= SDC_MODE_CARDTYPE_SDV20;
+ /* Voltage verification.*/
+ if (((resp >> 8) & 0xF) != 1)
+ goto failed;
+ if (sdc_lld_send_cmd_short(sdcp, SDC_CMD_APP_CMD, 0, &resp))
+ goto failed;
+ else {
+ /* MMC or SD detection.*/
+ if (sdc_lld_send_cmd_short(sdcp, SDC_CMD_APP_CMD, 0, &resp))
+ sdcp->cardmode |= SDC_MODE_CARDTYPE_MMC;
+ }
+
+ if ((sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) == SDC_MODE_CARDTYPE_MMC) {
+ }
+ else {
+ uint32_t ocr = 0x80100000;
+ unsigned i;
+
+ if ((sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) == SDC_MODE_CARDTYPE_SDV20)
+ ocr |= 0x40000000;
+
+ /* SD-type initialization. */
+ i = 0;
+ while (TRUE) {
+ chThdSleepMilliseconds(10);
+ if (sdc_lld_send_cmd_short(sdcp, SDC_CMD_APP_CMD, 0, &resp))
+ goto failed;
+ if (sdc_lld_send_cmd_short(sdcp, SDC_CMD_APP_OP_COND, ocr, &resp))
+ goto failed;
+ if ((resp & 0x80000000) != 0)
+ break;
+ if (++i >= SDC_ACMD41_RETRY)
+ goto failed;
+ }
+ }
+
sdcp->state = SDC_ACTIVE;
return FALSE;
+failed:
+ sdc_lld_stop_clk(sdcp);
+ sdcp->state = SDC_READY;
+ return TRUE;
}
/**
|