git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2908 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
dd9cac5ffa
commit
40c7b22bf4
|
@ -36,6 +36,18 @@
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
#define SDC_CMD_GO_IDLE_STATE 0
|
#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. */
|
/* Driver pre-compile time settings. */
|
||||||
|
|
|
@ -189,6 +189,8 @@ void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) {
|
||||||
* @brief Sends an SDIO command with no response expected.
|
* @brief Sends an SDIO command with no response expected.
|
||||||
*
|
*
|
||||||
* @param[in] sdcp pointer to the @p SDCDriver object
|
* @param[in] sdcp pointer to the @p SDCDriver object
|
||||||
|
* @param[in[ cmd card command
|
||||||
|
* @param[in] arg command argument
|
||||||
*
|
*
|
||||||
* @notapi
|
* @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.
|
* @brief Sends an SDIO command with a short response expected.
|
||||||
*
|
*
|
||||||
* @param[in] sdcp pointer to the @p SDCDriver object
|
* @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.
|
* @return The operation status.
|
||||||
* @retval FALSE the operation succeeded.
|
* @retval FALSE the operation succeeded.
|
||||||
* @retval TRUE the operation failed because timeout, CRC check or
|
* @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,
|
bool_t sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
|
||||||
uint32_t *resp) {
|
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.
|
* @brief Sends an SDIO command with a long response expected.
|
||||||
*
|
*
|
||||||
* @param[in] sdcp pointer to the @p SDCDriver object
|
* @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.
|
* @return The operation status.
|
||||||
* @retval FALSE the operation succeeded.
|
* @retval FALSE the operation succeeded.
|
||||||
* @retval TRUE the operation failed because timeout, CRC check or
|
* @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,
|
bool_t sdc_lld_send_cmd_long(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
|
||||||
uint32_t *resp) {
|
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 */
|
#endif /* HAL_USE_SDC */
|
||||||
|
|
|
@ -98,6 +98,11 @@ typedef enum {
|
||||||
SDC_MODE_8BIT
|
SDC_MODE_8BIT
|
||||||
} sdcbusmode_t;
|
} sdcbusmode_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type of card flags.
|
||||||
|
*/
|
||||||
|
typedef uint32_t sdcmode_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Type of a structure representing an SDC driver.
|
* @brief Type of a structure representing an SDC driver.
|
||||||
*/
|
*/
|
||||||
|
@ -123,6 +128,10 @@ struct SDCDriver {
|
||||||
* @brief Current configuration data.
|
* @brief Current configuration data.
|
||||||
*/
|
*/
|
||||||
const SDCConfig *config;
|
const SDCConfig *config;
|
||||||
|
/**
|
||||||
|
* @brief Various flags regarding the mounted card.
|
||||||
|
*/
|
||||||
|
sdcmode_t cardmode;
|
||||||
/* End of the mandatory fields.*/
|
/* End of the mandatory fields.*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -144,7 +153,7 @@ extern "C" {
|
||||||
void sdc_lld_init(void);
|
void sdc_lld_init(void);
|
||||||
void sdc_lld_start(SDCDriver *sdcp);
|
void sdc_lld_start(SDCDriver *sdcp);
|
||||||
void sdc_lld_stop(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_set_data_clk(SDCDriver *sdcp);
|
||||||
void sdc_lld_stop_clk(SDCDriver *sdcp);
|
void sdc_lld_stop_clk(SDCDriver *sdcp);
|
||||||
void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode);
|
void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode);
|
||||||
|
|
|
@ -127,6 +127,7 @@ void sdcStop(SDCDriver *sdcp) {
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
bool_t sdcConnect(SDCDriver *sdcp) {
|
bool_t sdcConnect(SDCDriver *sdcp) {
|
||||||
|
uint32_t resp;
|
||||||
|
|
||||||
chDbgCheck(sdcp != NULL, "sdcConnect");
|
chDbgCheck(sdcp != NULL, "sdcConnect");
|
||||||
|
|
||||||
|
@ -135,12 +136,60 @@ bool_t sdcConnect(SDCDriver *sdcp) {
|
||||||
sdcp->state = SDC_INITNG;
|
sdcp->state = SDC_INITNG;
|
||||||
chSysUnlock();
|
chSysUnlock();
|
||||||
|
|
||||||
|
/* Resets card attributes.*/
|
||||||
|
sdcp->cardmode = 0;
|
||||||
|
|
||||||
|
/* Card clock initialization.*/
|
||||||
sdc_lld_start_clk(sdcp);
|
sdc_lld_start_clk(sdcp);
|
||||||
|
|
||||||
|
/* Enforces the initial card state.*/
|
||||||
sdc_lld_send_cmd_none(sdcp, SDC_CMD_GO_IDLE_STATE, 0);
|
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;
|
sdcp->state = SDC_ACTIVE;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
failed:
|
||||||
|
sdc_lld_stop_clk(sdcp);
|
||||||
|
sdcp->state = SDC_READY;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue