git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4347 35acf78f-673a-0410-8e92-d51de3d6d3f4

master
gdisirio 2012-06-25 16:53:21 +00:00
parent 1d674cc603
commit 80443125b2
3 changed files with 207 additions and 326 deletions

View File

@ -59,21 +59,6 @@
#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) #if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
#define MMC_NICE_WAITING TRUE #define MMC_NICE_WAITING TRUE
#endif #endif
/**
* @brief Number of positive insertion queries before generating the
* insertion event.
*/
#if !defined(MMC_POLLING_INTERVAL) || defined(__DOXYGEN__)
#define MMC_POLLING_INTERVAL 10
#endif
/**
* @brief Interval, in milliseconds, between insertion queries.
*/
#if !defined(MMC_POLLING_DELAY) || defined(__DOXYGEN__)
#define MMC_POLLING_DELAY 10
#endif
/** @} */ /** @} */
/*===========================================================================*/ /*===========================================================================*/
@ -92,13 +77,14 @@
* @brief Driver state machine possible states. * @brief Driver state machine possible states.
*/ */
typedef enum { typedef enum {
MMC_UNINIT = 0, /**< Not initialized. */ MMC_UNINIT = 0, /**< Not initialized. */
MMC_STOP = 1, /**< Stopped. */ MMC_STOP = 1, /**< Stopped. */
MMC_WAIT = 2, /**< Waiting card. */ MMC_READY = 2, /**< Ready. */
MMC_INSERTED = 3, /**< Card inserted. */ MMC_CONNECTING = 3, /**< Card connection in progress. */
MMC_READY = 4, /**< Card ready. */ MMC_DISCONNECTING = 4, /**< Card disconnection in progress. */
MMC_READING = 5, /**< Reading. */ MMC_ACTIVE = 5, /**< Cart initialized. */
MMC_WRITING = 6 /**< Writing. */ MMC_READING = 6, /**< Read operation in progress. */
MMC_WRITING = 7, /**< Write operation in progress. */
} mmcstate_t; } mmcstate_t;
/** /**
@ -153,22 +139,6 @@ typedef struct {
* @brief Current configuration data. * @brief Current configuration data.
*/ */
const MMCConfig *config; const MMCConfig *config;
/**
* @brief Card insertion event source.
*/
EventSource inserted_event;
/**
* @brief Card removal event source.
*/
EventSource removed_event;
/**
* @brief MMC insertion polling timer.
*/
VirtualTimer vt;
/**
* @brief Insertion counter.
*/
uint_fast8_t cnt;
/*** /***
* @brief Addresses use blocks instead of bytes. * @brief Addresses use blocks instead of bytes.
*/ */
@ -193,6 +163,22 @@ typedef struct {
*/ */
#define mmcGetDriverState(mmcp) ((mmcp)->state) #define mmcGetDriverState(mmcp) ((mmcp)->state)
/**
* @brief Returns the card insertion status.
* @note This macro wraps a low level function named
* @p sdc_lld_is_card_inserted(), this function must be
* provided by the application because it is not part of the
* SDC driver.
*
* @param[in] mmcp pointer to the @p MMCDriver object
* @return The card state.
* @retval FALSE card not inserted.
* @retval TRUE card inserted.
*
* @api
*/
#define mmcIsCardInserted(mmcp) mmc_lld_is_card_inserted(mmcp)
/** /**
* @brief Returns the write protect status. * @brief Returns the write protect status.
* *

View File

@ -49,10 +49,10 @@
/*===========================================================================*/ /*===========================================================================*/
/* Forward declarations required by mmc_vmt.*/ /* Forward declarations required by mmc_vmt.*/
bool_t mmc_read(void *instance, uint32_t startblk, static bool_t mmc_read(void *instance, uint32_t startblk,
uint8_t *buffer, uint32_t n); uint8_t *buffer, uint32_t n);
bool_t mmc_write(void *instance, uint32_t startblk, static bool_t mmc_write(void *instance, uint32_t startblk,
const uint8_t *buffer, uint32_t n); const uint8_t *buffer, uint32_t n);
/** /**
* @brief Virtual methods table. * @brief Virtual methods table.
@ -100,36 +100,36 @@ static const uint8_t crc7_lookup_table[256] = {
/* Driver local functions. */ /* Driver local functions. */
/*===========================================================================*/ /*===========================================================================*/
bool_t mmc_read(void *instance, uint32_t startblk, static bool_t mmc_read(void *instance, uint32_t startblk,
uint8_t *buffer, uint32_t n) { uint8_t *buffer, uint32_t n) {
if (mmcStartSequentialRead((MMCDriver *)instance, startblk)) if (mmcStartSequentialRead((MMCDriver *)instance, startblk))
return TRUE; return CH_FAILED;
while (n > 0) { while (n > 0) {
if (mmcSequentialRead((MMCDriver *)instance, buffer)) if (mmcSequentialRead((MMCDriver *)instance, buffer))
return TRUE; return CH_FAILED;
buffer += MMCSD_BLOCK_SIZE; buffer += MMCSD_BLOCK_SIZE;
n--; n--;
} }
if (mmcStopSequentialRead((MMCDriver *)instance)) if (mmcStopSequentialRead((MMCDriver *)instance))
return TRUE; return CH_FAILED;
return FALSE; return CH_SUCCESS;
} }
bool_t mmc_write(void *instance, uint32_t startblk, static bool_t mmc_write(void *instance, uint32_t startblk,
const uint8_t *buffer, uint32_t n) { const uint8_t *buffer, uint32_t n) {
if (mmcStartSequentialWrite((MMCDriver *)instance, startblk)) if (mmcStartSequentialWrite((MMCDriver *)instance, startblk))
return TRUE; return CH_FAILED;
while (n > 0) { while (n > 0) {
if (mmcSequentialWrite((MMCDriver *)instance, buffer)) if (mmcSequentialWrite((MMCDriver *)instance, buffer))
return TRUE; return CH_FAILED;
buffer += MMCSD_BLOCK_SIZE; buffer += MMCSD_BLOCK_SIZE;
n--; n--;
} }
if (mmcStopSequentialWrite((MMCDriver *)instance)) if (mmcStopSequentialWrite((MMCDriver *)instance))
return TRUE; return CH_FAILED;
return FALSE; return CH_SUCCESS;
} }
/** /**
@ -147,38 +147,6 @@ static uint8_t crc7(uint8_t crc, const uint8_t *buffer, size_t len) {
return crc; return crc;
} }
/**
* @brief Insertion monitor timer callback function.
*
* @param[in] p pointer to the @p MMCDriver object
*
* @notapi
*/
static void tmrfunc(void *p) {
MMCDriver *mmcp = p;
chSysLockFromIsr();
if (mmcp->cnt > 0) {
if (mmc_lld_is_card_inserted(mmcp)) {
if (--mmcp->cnt == 0) {
mmcp->state = MMC_INSERTED;
chEvtBroadcastI(&mmcp->inserted_event);
}
}
else
mmcp->cnt = MMC_POLLING_INTERVAL;
}
else {
if (!mmc_lld_is_card_inserted(mmcp)) {
mmcp->state = MMC_WAIT;
mmcp->cnt = MMC_POLLING_INTERVAL;
chEvtBroadcastI(&mmcp->removed_event);
}
}
chVTSetI(&mmcp->vt, MS2ST(MMC_POLLING_DELAY), tmrfunc, mmcp);
chSysUnlockFromIsr();
}
/** /**
* @brief Waits an idle condition. * @brief Waits an idle condition.
* *
@ -325,8 +293,8 @@ static uint8_t send_command_R3(MMCDriver *mmcp, uint8_t cmd, uint32_t arg,
* @param[out] csd pointer to the CSD buffer * @param[out] csd pointer to the CSD buffer
* *
* @return The operation status. * @return The operation status.
* @retval FALSE the operation succeeded. * @retval CH_FAILED the operation succeeded.
* @retval TRUE the operation failed. * @retval CH_SUCCESS the operation failed.
* *
* @notapi * @notapi
*/ */
@ -338,7 +306,7 @@ static bool_t read_CxD(MMCDriver *mmcp, uint8_t cmd, uint32_t cxd[4]) {
send_hdr(mmcp, cmd, 0); send_hdr(mmcp, cmd, 0);
if (recvr1(mmcp) != 0x00) { if (recvr1(mmcp) != 0x00) {
spiUnselect(mmcp->config->spip); spiUnselect(mmcp->config->spip);
return TRUE; return CH_FAILED;
} }
/* Wait for data availability.*/ /* Wait for data availability.*/
@ -359,10 +327,10 @@ static bool_t read_CxD(MMCDriver *mmcp, uint8_t cmd, uint32_t cxd[4]) {
spiIgnore(mmcp->config->spip, 2); spiIgnore(mmcp->config->spip, 2);
spiUnselect(mmcp->config->spip); spiUnselect(mmcp->config->spip);
return FALSE; return CH_SUCCESS;
} }
} }
return TRUE; return CH_FAILED;
} }
/** /**
@ -415,8 +383,6 @@ void mmcObjectInit(MMCDriver *mmcp) {
mmcp->state = MMC_STOP; mmcp->state = MMC_STOP;
mmcp->config = NULL; mmcp->config = NULL;
mmcp->block_addresses = FALSE; mmcp->block_addresses = FALSE;
chEvtInit(&mmcp->inserted_event);
chEvtInit(&mmcp->removed_event);
} }
/** /**
@ -432,11 +398,10 @@ void mmcStart(MMCDriver *mmcp, const MMCConfig *config) {
chDbgCheck((mmcp != NULL) && (config != NULL), "mmcStart"); chDbgCheck((mmcp != NULL) && (config != NULL), "mmcStart");
chSysLock(); chSysLock();
chDbgAssert(mmcp->state == MMC_STOP, "mmcStart(), #1", "invalid state"); chDbgAssert((mmcp->state == MMC_STOP) || (mmcp->state == MMC_READY),
"mmcStart(), #1", "invalid state");
mmcp->config = config; mmcp->config = config;
mmcp->state = MMC_WAIT; mmcp->state = MMC_READY;
mmcp->cnt = MMC_POLLING_INTERVAL;
chVTSetI(&mmcp->vt, MS2ST(MMC_POLLING_DELAY), tmrfunc, mmcp);
chSysUnlock(); chSysUnlock();
} }
@ -452,14 +417,9 @@ void mmcStop(MMCDriver *mmcp) {
chDbgCheck(mmcp != NULL, "mmcStop"); chDbgCheck(mmcp != NULL, "mmcStop");
chSysLock(); chSysLock();
chDbgAssert((mmcp->state != MMC_UNINIT) && chDbgAssert((mmcp->state == MMC_STOP) || (mmcp->state == MMC_READY),
(mmcp->state != MMC_READING) &&
(mmcp->state != MMC_WRITING),
"mmcStop(), #1", "invalid state"); "mmcStop(), #1", "invalid state");
if (mmcp->state != MMC_STOP) { mmcp->state = MMC_STOP;
mmcp->state = MMC_STOP;
chVTResetI(&mmcp->vt);
}
chSysUnlock(); chSysUnlock();
spiStop(mmcp->config->spip); spiStop(mmcp->config->spip);
} }
@ -475,111 +435,102 @@ void mmcStop(MMCDriver *mmcp) {
* @param[in] mmcp pointer to the @p MMCDriver object * @param[in] mmcp pointer to the @p MMCDriver object
* *
* @return The operation status. * @return The operation status.
* @retval FALSE the operation succeeded and the driver is now * @retval CH_FAILED the operation succeeded and the driver is now
* in the @p MMC_READY state. * in the @p MMC_READY state.
* @retval TRUE the operation failed. * @retval CH_SUCCESS the operation failed.
* *
* @api * @api
*/ */
bool_t mmcConnect(MMCDriver *mmcp) { bool_t mmcConnect(MMCDriver *mmcp) {
unsigned i; unsigned i;
bool_t result;
chDbgCheck(mmcp != NULL, "mmcConnect"); chDbgCheck(mmcp != NULL, "mmcConnect");
chDbgAssert((mmcp->state != MMC_UNINIT) && (mmcp->state != MMC_STOP), chSysLock();
chDbgAssert((mmcp->state == MMC_READY) || (mmcp->state == MMC_ACTIVE),
"mmcConnect(), #1", "invalid state"); "mmcConnect(), #1", "invalid state");
mmcp->state = MMC_CONNECTING;
chSysUnlock();
if (mmcp->state == MMC_INSERTED) { /* Slow clock mode and 128 clock pulses.*/
/* Slow clock mode and 128 clock pulses.*/ spiStart(mmcp->config->spip, mmcp->config->lscfg);
spiStart(mmcp->config->spip, mmcp->config->lscfg); spiIgnore(mmcp->config->spip, 16);
spiIgnore(mmcp->config->spip, 16);
/* SPI mode selection.*/ /* SPI mode selection.*/
i = 0; i = 0;
while (TRUE) { while (TRUE) {
if (send_command_R1(mmcp, MMCSD_CMD_GO_IDLE_STATE, 0) == 0x01) if (send_command_R1(mmcp, MMCSD_CMD_GO_IDLE_STATE, 0) == 0x01)
break; break;
if (++i >= MMC_CMD0_RETRY) if (++i >= MMC_CMD0_RETRY)
return TRUE; goto failed;
chThdSleepMilliseconds(10); chThdSleepMilliseconds(10);
}
/* Try to detect if this is a high capacity card and switch to block
addresses if possible.
This method is based on "How to support SDC Ver2 and high capacity cards"
by ElmChan.*/
uint8_t r3[4];
if (send_command_R3(mmcp, MMCSD_CMD_SEND_IF_COND,
MMCSD_CMD8_PATTERN, r3) != 0x05) {
/* Switch to SDHC mode.*/
i = 0;
while (TRUE) {
if ((send_command_R1(mmcp, MMCSD_CMD_APP_CMD, 0) == 0x01) &&
(send_command_R3(mmcp, MMCSD_CMD_APP_OP_COND,
0x400001aa, r3) == 0x00))
break;
if (++i >= MMC_ACMD41_RETRY)
return TRUE;
chThdSleepMilliseconds(10);
}
/* Execute dedicated read on OCR register */
send_command_R3(mmcp, MMCSD_CMD_READ_OCR, 0, r3);
/* Check if CCS is set in response. Card operates in block mode if set.*/
if(r3[0] & 0x40)
mmcp->block_addresses = TRUE;
}
/* Initialization.*/
i = 0;
while (TRUE) {
uint8_t b = send_command_R1(mmcp, MMCSD_CMD_INIT, 0);
if (b == 0x00)
break;
if (b != 0x01)
return TRUE;
if (++i >= MMC_CMD1_RETRY)
return TRUE;
chThdSleepMilliseconds(10);
}
/* Initialization complete, full speed.*/
spiStart(mmcp->config->spip, mmcp->config->hscfg);
/* Setting block size.*/
if (send_command_R1(mmcp, MMCSD_CMD_SET_BLOCKLEN,
MMCSD_BLOCK_SIZE) != 0x00)
return TRUE;
/* Determine capacity.*/
if (read_CxD(mmcp, MMCSD_CMD_SEND_CSD, mmcp->csd))
return TRUE;
mmcp->capacity = mmcsdGetCapacity(mmcp->csd);
if (mmcp->capacity == 0)
return TRUE;
if (read_CxD(mmcp, MMCSD_CMD_SEND_CID, mmcp->cid))
return TRUE;
/* Transition to MMC_READY state (if not extracted).*/
chSysLock();
if (mmcp->state == MMC_INSERTED) {
mmcp->state = MMC_READY;
result = FALSE;
}
else
result = TRUE;
chSysUnlock();
return result;
} }
if (mmcp->state == MMC_READY)
return FALSE; /* Try to detect if this is a high capacity card and switch to block
/* Any other state is invalid.*/ addresses if possible.
return TRUE; This method is based on "How to support SDC Ver2 and high capacity cards"
by ElmChan.*/
uint8_t r3[4];
if (send_command_R3(mmcp, MMCSD_CMD_SEND_IF_COND,
MMCSD_CMD8_PATTERN, r3) != 0x05) {
/* Switch to SDHC mode.*/
i = 0;
while (TRUE) {
if ((send_command_R1(mmcp, MMCSD_CMD_APP_CMD, 0) == 0x01) &&
(send_command_R3(mmcp, MMCSD_CMD_APP_OP_COND,
0x400001aa, r3) == 0x00))
break;
if (++i >= MMC_ACMD41_RETRY)
goto failed;
chThdSleepMilliseconds(10);
}
/* Execute dedicated read on OCR register */
send_command_R3(mmcp, MMCSD_CMD_READ_OCR, 0, r3);
/* Check if CCS is set in response. Card operates in block mode if set.*/
if(r3[0] & 0x40)
mmcp->block_addresses = TRUE;
}
/* Initialization.*/
i = 0;
while (TRUE) {
uint8_t b = send_command_R1(mmcp, MMCSD_CMD_INIT, 0);
if (b == 0x00)
break;
if (b != 0x01)
goto failed;
if (++i >= MMC_CMD1_RETRY)
goto failed;
chThdSleepMilliseconds(10);
}
/* Initialization complete, full speed.*/
spiStart(mmcp->config->spip, mmcp->config->hscfg);
/* Setting block size.*/
if (send_command_R1(mmcp, MMCSD_CMD_SET_BLOCKLEN,
MMCSD_BLOCK_SIZE) != 0x00)
goto failed;
/* Determine capacity.*/
if (read_CxD(mmcp, MMCSD_CMD_SEND_CSD, mmcp->csd))
goto failed;
mmcp->capacity = mmcsdGetCapacity(mmcp->csd);
if (mmcp->capacity == 0)
goto failed;
if (read_CxD(mmcp, MMCSD_CMD_SEND_CID, mmcp->cid))
goto failed;
mmcp->state = MMC_READY;
return CH_SUCCESS;
failed:
mmcp->state = MMC_READY;
return CH_FAILED;
} }
/** /**
@ -588,34 +539,32 @@ bool_t mmcConnect(MMCDriver *mmcp) {
* @param[in] mmcp pointer to the @p MMCDriver object * @param[in] mmcp pointer to the @p MMCDriver object
* @return The operation status. * @return The operation status.
* *
* @retval FALSE the operation succeeded and the driver is now * @retval CH_FAILED the operation succeeded and the driver is now
* in the @p MMC_INSERTED state. * in the @p MMC_INSERTED state.
* @retval TRUE the operation failed. * @retval CH_SUCCESS the operation failed.
* *
* @api * @api
*/ */
bool_t mmcDisconnect(MMCDriver *mmcp) { bool_t mmcDisconnect(MMCDriver *mmcp) {
bool_t status;
chDbgCheck(mmcp != NULL, "mmcDisconnect"); chDbgCheck(mmcp != NULL, "mmcDisconnect");
chDbgAssert((mmcp->state != MMC_UNINIT) && (mmcp->state != MMC_STOP), chSysLock();
chDbgAssert((mmcp->state == MMC_READY) || (mmcp->state == MMC_ACTIVE),
"mmcDisconnect(), #1", "invalid state"); "mmcDisconnect(), #1", "invalid state");
switch (mmcp->state) { if (mmcp->state == MMC_READY) {
case MMC_READY:
/* Wait for the pending write operations to complete.*/
sync(mmcp);
chSysLock();
if (mmcp->state == MMC_READY)
mmcp->state = MMC_INSERTED;
chSysUnlock(); chSysUnlock();
case MMC_INSERTED: return CH_SUCCESS;
status = FALSE;
default:
status = TRUE;
} }
mmcp->state = MMC_DISCONNECTING;
chSysUnlock();
/* Wait for the pending write operations to complete.*/
sync(mmcp);
spiStop(mmcp->config->spip); spiStop(mmcp->config->spip);
return status;
mmcp->state = MMC_READY;
return CH_SUCCESS;
} }
/** /**
@ -625,8 +574,8 @@ bool_t mmcDisconnect(MMCDriver *mmcp) {
* @param[in] startblk first block to read * @param[in] startblk first block to read
* *
* @return The operation status. * @return The operation status.
* @retval FALSE the operation succeeded. * @retval CH_FAILED the operation succeeded.
* @retval TRUE the operation failed. * @retval CH_SUCCESS the operation failed.
* *
* @api * @api
*/ */
@ -635,13 +584,13 @@ bool_t mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk) {
chDbgCheck(mmcp != NULL, "mmcStartSequentialRead"); chDbgCheck(mmcp != NULL, "mmcStartSequentialRead");
chSysLock(); chSysLock();
if (mmcp->state != MMC_READY) { chDbgAssert(mmcp->state == MMC_ACTIVE,
chSysUnlock(); "mmcStartSequentialRead(), #1", "invalid state");
return TRUE;
}
mmcp->state = MMC_READING; mmcp->state = MMC_READING;
chSysUnlock(); chSysUnlock();
/* (Re)starting the SPI in case it has been reprogrammed externally, it can
happen if the SPI bus is shared among multiple peripherals.*/
spiStart(mmcp->config->spip, mmcp->config->hscfg); spiStart(mmcp->config->spip, mmcp->config->hscfg);
spiSelect(mmcp->config->spip); spiSelect(mmcp->config->spip);
@ -651,14 +600,10 @@ bool_t mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk) {
send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk * MMCSD_BLOCK_SIZE); send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk * MMCSD_BLOCK_SIZE);
if (recvr1(mmcp) != 0x00) { if (recvr1(mmcp) != 0x00) {
spiUnselect(mmcp->config->spip); mmcp->state = MMC_READY;
chSysLock(); return CH_FAILED;
if (mmcp->state == MMC_READING)
mmcp->state = MMC_READY;
chSysUnlock();
return TRUE;
} }
return FALSE; return CH_SUCCESS;
} }
/** /**
@ -668,8 +613,8 @@ bool_t mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk) {
* @param[out] buffer pointer to the read buffer * @param[out] buffer pointer to the read buffer
* *
* @return The operation status. * @return The operation status.
* @retval FALSE the operation succeeded. * @retval CH_FAILED the operation succeeded.
* @retval TRUE the operation failed. * @retval CH_SUCCESS the operation failed.
* *
* @api * @api
*/ */
@ -678,12 +623,8 @@ bool_t mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer) {
chDbgCheck((mmcp != NULL) && (buffer != NULL), "mmcSequentialRead"); chDbgCheck((mmcp != NULL) && (buffer != NULL), "mmcSequentialRead");
chSysLock(); if (mmcp->state != MMC_READING)
if (mmcp->state != MMC_READING) { return CH_FAILED;
chSysUnlock();
return TRUE;
}
chSysUnlock();
for (i = 0; i < MMC_WAIT_DATA; i++) { for (i = 0; i < MMC_WAIT_DATA; i++) {
spiReceive(mmcp->config->spip, 1, buffer); spiReceive(mmcp->config->spip, 1, buffer);
@ -691,16 +632,13 @@ bool_t mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer) {
spiReceive(mmcp->config->spip, MMCSD_BLOCK_SIZE, buffer); spiReceive(mmcp->config->spip, MMCSD_BLOCK_SIZE, buffer);
/* CRC ignored. */ /* CRC ignored. */
spiIgnore(mmcp->config->spip, 2); spiIgnore(mmcp->config->spip, 2);
return FALSE; return CH_SUCCESS;
} }
} }
/* Timeout.*/ /* Timeout.*/
spiUnselect(mmcp->config->spip); spiUnselect(mmcp->config->spip);
chSysLock(); mmcp->state = MMC_READY;
if (mmcp->state == MMC_READING) return CH_FAILED;
mmcp->state = MMC_READY;
chSysUnlock();
return TRUE;
} }
/** /**
@ -709,37 +647,28 @@ bool_t mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer) {
* @param[in] mmcp pointer to the @p MMCDriver object * @param[in] mmcp pointer to the @p MMCDriver object
* *
* @return The operation status. * @return The operation status.
* @retval FALSE the operation succeeded. * @retval CH_FAILED the operation succeeded.
* @retval TRUE the operation failed. * @retval CH_SUCCESS the operation failed.
* *
* @api * @api
*/ */
bool_t mmcStopSequentialRead(MMCDriver *mmcp) { bool_t mmcStopSequentialRead(MMCDriver *mmcp) {
static const uint8_t stopcmd[] = {0x40 | MMCSD_CMD_STOP_TRANSMISSION, static const uint8_t stopcmd[] = {0x40 | MMCSD_CMD_STOP_TRANSMISSION,
0, 0, 0, 0, 1, 0xFF}; 0, 0, 0, 0, 1, 0xFF};
bool_t result;
chDbgCheck(mmcp != NULL, "mmcStopSequentialRead"); chDbgCheck(mmcp != NULL, "mmcStopSequentialRead");
chSysLock(); if (mmcp->state != MMC_READING)
if (mmcp->state != MMC_READING) { return CH_FAILED;
chSysUnlock();
return TRUE;
}
chSysUnlock();
spiSend(mmcp->config->spip, sizeof(stopcmd), stopcmd); spiSend(mmcp->config->spip, sizeof(stopcmd), stopcmd);
/* result = recvr1(mmcp) != 0x00;*/ /* result = recvr1(mmcp) != 0x00;*/
/* Note, ignored r1 response, it can be not zero, unknown issue.*/ /* Note, ignored r1 response, it can be not zero, unknown issue.*/
recvr1(mmcp); (void) recvr1(mmcp);
result = FALSE;
spiUnselect(mmcp->config->spip);
chSysLock(); spiUnselect(mmcp->config->spip);
if (mmcp->state == MMC_READING) mmcp->state = MMC_READY;
mmcp->state = MMC_READY; return CH_SUCCESS;
chSysUnlock();
return result;
} }
/** /**
@ -749,8 +678,8 @@ bool_t mmcStopSequentialRead(MMCDriver *mmcp) {
* @param[in] startblk first block to write * @param[in] startblk first block to write
* *
* @return The operation status. * @return The operation status.
* @retval FALSE the operation succeeded. * @retval CH_FAILED the operation succeeded.
* @retval TRUE the operation failed. * @retval CH_SUCCESS the operation failed.
* *
* @api * @api
*/ */
@ -759,10 +688,8 @@ bool_t mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk) {
chDbgCheck(mmcp != NULL, "mmcStartSequentialWrite"); chDbgCheck(mmcp != NULL, "mmcStartSequentialWrite");
chSysLock(); chSysLock();
if (mmcp->state != MMC_READY) { chDbgAssert(mmcp->state == MMC_ACTIVE,
chSysUnlock(); "mmcStartSequentialWrite(), #1", "invalid state");
return TRUE;
}
mmcp->state = MMC_WRITING; mmcp->state = MMC_WRITING;
chSysUnlock(); chSysUnlock();
@ -774,16 +701,11 @@ bool_t mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk) {
send_hdr(mmcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, send_hdr(mmcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK,
startblk * MMCSD_BLOCK_SIZE); startblk * MMCSD_BLOCK_SIZE);
if (recvr1(mmcp) != 0x00) { if (recvr1(mmcp) != 0x00) {
spiUnselect(mmcp->config->spip); mmcp->state = MMC_READY;
chSysLock(); return CH_FAILED;
if (mmcp->state == MMC_WRITING)
mmcp->state = MMC_READY;
chSysUnlock();
return TRUE;
} }
return FALSE; return CH_SUCCESS;
} }
/** /**
@ -793,8 +715,8 @@ bool_t mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk) {
* @param[out] buffer pointer to the write buffer * @param[out] buffer pointer to the write buffer
* *
* @return The operation status. * @return The operation status.
* @retval FALSE the operation succeeded. * @retval CH_FAILED the operation succeeded.
* @retval TRUE the operation failed. * @retval CH_SUCCESS the operation failed.
* *
* @api * @api
*/ */
@ -804,12 +726,8 @@ bool_t mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer) {
chDbgCheck((mmcp != NULL) && (buffer != NULL), "mmcSequentialWrite"); chDbgCheck((mmcp != NULL) && (buffer != NULL), "mmcSequentialWrite");
chSysLock(); if (mmcp->state != MMC_WRITING)
if (mmcp->state != MMC_WRITING) { return CH_FAILED;
chSysUnlock();
return TRUE;
}
chSysUnlock();
spiSend(mmcp->config->spip, sizeof(start), start); /* Data prologue. */ spiSend(mmcp->config->spip, sizeof(start), start); /* Data prologue. */
spiSend(mmcp->config->spip, MMCSD_BLOCK_SIZE, buffer);/* Data. */ spiSend(mmcp->config->spip, MMCSD_BLOCK_SIZE, buffer);/* Data. */
@ -817,16 +735,13 @@ bool_t mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer) {
spiReceive(mmcp->config->spip, 1, b); spiReceive(mmcp->config->spip, 1, b);
if ((b[0] & 0x1F) == 0x05) { if ((b[0] & 0x1F) == 0x05) {
wait(mmcp); wait(mmcp);
return FALSE; return CH_SUCCESS;
} }
/* Error.*/ /* Error.*/
spiUnselect(mmcp->config->spip); spiUnselect(mmcp->config->spip);
chSysLock(); mmcp->state = MMC_READY;
if (mmcp->state == MMC_WRITING) return CH_FAILED;
mmcp->state = MMC_READY;
chSysUnlock();
return TRUE;
} }
/** /**
@ -835,8 +750,8 @@ bool_t mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer) {
* @param[in] mmcp pointer to the @p MMCDriver object * @param[in] mmcp pointer to the @p MMCDriver object
* *
* @return The operation status. * @return The operation status.
* @retval FALSE the operation succeeded. * @retval CH_FAILED the operation succeeded.
* @retval TRUE the operation failed. * @retval CH_SUCCESS the operation failed.
* *
* @api * @api
*/ */
@ -845,24 +760,15 @@ bool_t mmcStopSequentialWrite(MMCDriver *mmcp) {
chDbgCheck(mmcp != NULL, "mmcStopSequentialWrite"); chDbgCheck(mmcp != NULL, "mmcStopSequentialWrite");
chSysLock(); if (mmcp->state != MMC_WRITING)
if (mmcp->state != MMC_WRITING) { return CH_FAILED;
chSysUnlock();
return TRUE;
}
chSysUnlock();
spiSend(mmcp->config->spip, sizeof(stop), stop); spiSend(mmcp->config->spip, sizeof(stop), stop);
spiUnselect(mmcp->config->spip); spiUnselect(mmcp->config->spip);
chSysLock(); chSysLock();
if (mmcp->state == MMC_WRITING) { mmcp->state = MMC_READY;
mmcp->state = MMC_READY; return CH_SUCCESS;
chSysUnlock();
return FALSE;
}
chSysUnlock();
return TRUE;
} }
/** /**
@ -871,8 +777,8 @@ bool_t mmcStopSequentialWrite(MMCDriver *mmcp) {
* @param[in] mmcp pointer to the @p MMCDriver object * @param[in] mmcp pointer to the @p MMCDriver object
* *
* @return The operation status. * @return The operation status.
* @retval FALSE the operation succeeded. * @retval CH_FAILED the operation succeeded.
* @retval TRUE the operation failed. * @retval CH_SUCCESS the operation failed.
* *
* @api * @api
*/ */
@ -880,16 +786,11 @@ bool_t mmcSync(MMCDriver *mmcp) {
chDbgCheck(mmcp != NULL, "mmcSync"); chDbgCheck(mmcp != NULL, "mmcSync");
chSysLock(); if (mmcp->state != MMC_READY)
if (mmcp->state != MMC_READY) { return CH_FAILED;
chSysUnlock();
return TRUE;
}
chSysUnlock();
sync(mmcp); sync(mmcp);
return CH_SUCCESS;
return FALSE;
} }
/** /**
@ -899,27 +800,21 @@ bool_t mmcSync(MMCDriver *mmcp) {
* @param[out] bdip pointer to a @p BlockDeviceInfo structure * @param[out] bdip pointer to a @p BlockDeviceInfo structure
* *
* @return The operation status. * @return The operation status.
* @retval FALSE the operation succeeded. * @retval CH_FAILED the operation succeeded.
* @retval TRUE the operation failed. * @retval CH_SUCCESS the operation failed.
* *
* @api * @api
*/ */
bool_t mmcGetInfo(MMCDriver *mmcp, BlockDeviceInfo *bdip) { bool_t mmcGetInfo(MMCDriver *mmcp, BlockDeviceInfo *bdip) {
chDbgCheck((mmcp != NULL) && (bdip != NULL), "mmcGetInfo"); chDbgCheck((mmcp != NULL) && (bdip != NULL), "mmcGetInfo");
chSysLock(); if (mmcp->state != MMC_READY)
if (mmcp->state != MMC_READY) { return CH_FAILED;
chSysUnlock();
return TRUE;
}
chSysUnlock();
bdip->blk_num = mmcp->capacity; bdip->blk_num = mmcp->capacity;
bdip->blk_size = MMCSD_BLOCK_SIZE; bdip->blk_size = MMCSD_BLOCK_SIZE;
return CH_SUCCESS;
return FALSE;
} }
/** /**
@ -930,8 +825,8 @@ bool_t mmcGetInfo(MMCDriver *mmcp, BlockDeviceInfo *bdip) {
* @param[in] endblk ending block number * @param[in] endblk ending block number
* *
* @return The operation status. * @return The operation status.
* @retval FALSE the operation succeeded. * @retval CH_FAILED the operation succeeded.
* @retval TRUE the operation failed. * @retval CH_SUCCESS the operation failed.
* *
* @api * @api
*/ */
@ -940,15 +835,15 @@ bool_t mmcErase(MMCDriver *mmcp, uint32_t startblk, uint32_t endblk) {
chDbgCheck((mmcp != NULL), "mmcErase"); chDbgCheck((mmcp != NULL), "mmcErase");
if (send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_START, startblk)) if (send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_START, startblk))
return TRUE; return CH_FAILED;
if (send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_END, endblk)) if (send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_END, endblk))
return TRUE; return CH_FAILED;
if (send_command_R1(mmcp, MMCSD_CMD_ERASE, 0)) if (send_command_R1(mmcp, MMCSD_CMD_ERASE, 0))
return TRUE; return CH_FAILED;
return FALSE; return CH_SUCCESS;
} }

View File

@ -230,7 +230,7 @@ bool_t sdcConnect(SDCDriver *sdcp) {
#if SDC_MMC_SUPPORT #if SDC_MMC_SUPPORT
if ((sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) == SDC_MODE_CARDTYPE_MMC) { if ((sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) == SDC_MODE_CARDTYPE_MMC) {
/* TODO: MMC initialization.*/ /* TODO: MMC initialization.*/
return CH_FAILED; goto failed;
} }
else else
#endif /* SDC_MMC_SUPPORT */ #endif /* SDC_MMC_SUPPORT */
@ -337,7 +337,7 @@ bool_t sdcDisconnect(SDCDriver *sdcp) {
chDbgCheck(sdcp != NULL, "sdcDisconnect"); chDbgCheck(sdcp != NULL, "sdcDisconnect");
chSysLock(); chSysLock();
chDbgAssert(sdcp->state == SDC_ACTIVE, chDbgAssert((sdcp->state == SDC_READY) || (sdcp->state == SDC_ACTIVE),
"sdcDisconnect(), #1", "invalid state"); "sdcDisconnect(), #1", "invalid state");
if (sdcp->state == SDC_READY) { if (sdcp->state == SDC_READY) {
chSysUnlock(); chSysUnlock();