From 85cf8d37b5923dfa3e324c0e13e5e4d6efb884df Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 8 Nov 2009 18:36:55 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1277 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/io/mmc_spi.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++--------- os/io/mmc_spi.h | 17 +++--- 2 files changed, 141 insertions(+), 32 deletions(-) (limited to 'os') diff --git a/os/io/mmc_spi.c b/os/io/mmc_spi.c index ae29c4d34..20d7162ec 100644 --- a/os/io/mmc_spi.c +++ b/os/io/mmc_spi.c @@ -237,9 +237,9 @@ void mmcStop(MMCDriver *mmcp) { if (mmcp->mmc_state != MMC_STOP) { mmcp->mmc_state = MMC_STOP; chVTResetI(&mmcp->mmc_vt); - spiStop(mmcp->mmc_spip); } chSysUnlock(); + spiStop(mmcp->mmc_spip); } /** @@ -257,37 +257,143 @@ void mmcStop(MMCDriver *mmcp) { * in the @p MMC_READY state. * @retval TRUE the operation failed. */ -bool_t mmcOpen(MMCDriver *mmcp) { +bool_t mmcConnect(MMCDriver *mmcp) { unsigned i; - /* Slow clock mode and 128 clock pulses.*/ - spiStart(mmcp->mmc_spip, mmcp->mmc_lscfg); + chDbgCheck(mmcp != NULL, "mmcConnect"); - /* SPI mode selection.*/ - i = 0; - while (TRUE) { - if (send_command(mmcp, MMC_CMDGOIDLE, 0) == 0x01) - break; - if (++i >= MMC_CMD0_RETRY) - return TRUE; - chThdSleepMilliseconds(10); + chDbgAssert((mmcp->mmc_state != MMC_UNINIT) && + (mmcp->mmc_state != MMC_STOP), + "mmcConnect(), #1", + "invalid state"); + + if (mmcp->mmc_state == MMC_INSERTED) { + /* Slow clock mode and 128 clock pulses.*/ + spiStart(mmcp->mmc_spip, mmcp->mmc_lscfg); + + /* SPI mode selection.*/ + i = 0; + while (TRUE) { + if (send_command(mmcp, MMC_CMDGOIDLE, 0) == 0x01) + break; + if (++i >= MMC_CMD0_RETRY) + return TRUE; + chThdSleepMilliseconds(10); + } + + /* Initialization. */ + i = 0; + while (TRUE) { + uint8_t b = send_command(mmcp, MMC_CMDINIT, 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->mmc_spip, mmcp->mmc_hscfg); + mmcp->mmc_state = MMC_READY; + return FALSE; } + if (mmcp->mmc_state == MMC_READY) + return FALSE; + /* Any other state is invalid.*/ + return TRUE; +} - /* Initialization. */ - i = 0; - while (TRUE) { - uint8_t b = send_command(mmcp, MMC_CMDINIT, 0); - if (b == 0x00) - break; - if (b != 0x01) - return TRUE; - if (++i >= MMC_CMD1_RETRY) - return TRUE; - chThdSleepMilliseconds(10); +/** + * @brief Starts a sequential read. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[in] startblk first block to read + * + * @return The operation status. + * @retval FALSE the operation was successful. + * @retval TRUE the operation failed. + */ +bool_t mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk) { + + chDbgCheck(mmcp != NULL, "mmcStartSequentialRead"); + + chSysLock(); + if (mmcp->mmc_state != MMC_READY) { + chSysUnlock(); + return TRUE; + } + mmcp->mmc_state = MMC_RUNNING; + chSysUnlock(); + + spiSelect(mmcp->mmc_spip); + send_hdr(mmcp, MMC_CMDREADMULTIPLE, startblk << 9); + if (recvr1() != 0x00) { + spiUnselect(mmcp->mmc_spip); + chSysLock(); + if (mmcp->mmc_state == MMC_RUNNING) + mmcp->mmc_state = MMC_READY; + chSysUnlock(); + return TRUE; + } + return FALSE; +} + +/** + * @brief Reads a block within a sequential read operation. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[out] buffer pointer to the read buffer + * + * @return The operation status. + * @retval FALSE the operation was successful. + * @retval TRUE the operation failed. + */ +bool_t mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer) { + int i; + uint8_t ignored[2]; + + chDbgCheck((mmcp != NULL) && (buffer != NULL), "mmcSequentialRead"); + + if (mmcp->mmc_state != MMC_RUNNING) + return TRUE; + + for (i = 0; i < MMC_WAIT_DATA; i++) { + spiReceive(mmcp->mmc_spip, 1, buf); + if (buf[0] == 0xFE) { + spiReceive(mmcp->mmc_spip, 512, buf); + /* CRC ignored. */ + spiReceive(mmcp->mmc_spip, 2, ignored); + return FALSE; + } } + /* Timeout.*/ + spiUnselect(mmcp->mmc_spip); + chSysLock(); + if (mmcp->mmc_state == MMC_RUNNING) + mmcp->mmc_state = MMC_READY; + chSysUnlock(); + return TRUE; +} + +/** + * @brief Stops a sequential read gracefully. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * + * @return The operation status. + * @retval FALSE the operation was successful. + * @retval TRUE the operation failed. + */ +bool_t mmcStopSequentialRead(MMCDriver *mmcp) { + + chDbgCheck(mmcp != NULL, "mmcStopSequentialRead"); + + if (mmcp->mmc_state != MMC_RUNNING) + return TRUE; - /* Initialization complete, full speed. */ - spiStart(mmcp->mmc_spip, mmcp->mmc_hscfg); + mmcp->mmc_state = MMC_READY; return FALSE; } diff --git a/os/io/mmc_spi.h b/os/io/mmc_spi.h index 00f0e617b..538f46430 100644 --- a/os/io/mmc_spi.h +++ b/os/io/mmc_spi.h @@ -83,12 +83,12 @@ * @brief Driver state machine possible states. */ typedef enum { - MMC_UNINIT = 0, /**< @brief Not initialized. *///!< MMC_UNINIT - MMC_STOP = 1, /**< @brief Stopped. *///!< MMC_STOP - MMC_WAIT = 2, /**< @brief Waiting card. *///!< MMC_WAIT - MMC_INSERTED = 3, /**< @brief Card inserted. *///!< MMC_INSERTED - MMC_READY = 4, /**< @brief Card ready. *///!< MMC_READY - MMC_RUNNING = 5 /**< @brief Reading or writing. *///!< MMC_RUNNING + MMC_UNINIT = 0, /**< @brief Not initialized. */ + MMC_STOP = 1, /**< @brief Stopped. */ + MMC_WAIT = 2, /**< @brief Waiting card. */ + MMC_INSERTED = 3, /**< @brief Card inserted. */ + MMC_READY = 4, /**< @brief Card ready. */ + MMC_RUNNING = 5 /**< @brief Reading or writing. */ } mmcstate_t; /** @@ -168,7 +168,10 @@ extern "C" { mmcquery_t is_protected, mmcquery_t is_inserted); void mmcStart(MMCDriver *mmcp, const MMCConfig *config); void mmcStop(MMCDriver *mmcp); - bool_t mmcOpen(MMCDriver *mmcp); + bool_t mmcConnect(MMCDriver *mmcp); + bool_t mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk); + bool_t mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer); + bool_t mmcStopSequentialRead(MMCDriver *mmcp); #ifdef __cplusplus } #endif -- cgit v1.2.3