From 0da2b9d0d87312b9fd50f368689be8f870055542 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 14 Nov 2009 14:57:32 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1291 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/io/mmc_spi.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- os/io/mmc_spi.h | 1 + 2 files changed, 67 insertions(+), 1 deletion(-) (limited to 'os') diff --git a/os/io/mmc_spi.c b/os/io/mmc_spi.c index 517291814..d3370ea8c 100644 --- a/os/io/mmc_spi.c +++ b/os/io/mmc_spi.c @@ -143,6 +143,26 @@ static uint8_t send_command(MMCDriver *mmcp, uint8_t cmd, uint32_t arg) { return r1; } +/** + * @brief Waits that the card reaches an idle state. + * + * @param[in] mmcp pointer to the @p MMCDriver object + */ +static void sync(MMCDriver *mmcp) { + uint8_t buf[1]; + + spiSelect(mmcp->mmc_spip); + while (TRUE) { + spiReceive(mmcp->mmc_spip, 1, buf); + if (buf[0] == 0xFF) + break; +#ifdef MMC_NICE_WAITING + chThdSleep(1); /* Trying to be nice with the other threads.*/ +#endif + } + spiUnselect(mmcp->mmc_spip); +} + /*===========================================================================*/ /* Driver exported functions. */ /*===========================================================================*/ @@ -301,6 +321,38 @@ bool_t mmcConnect(MMCDriver *mmcp) { return TRUE; } +/** + * @brief Brings the driver in a state safe for card removal. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @return The operation status. + * @retval FALSE the operation was successful and the driver is now + * in the @p MMC_INSERTED state. + * @retval TRUE the operation failed. + */ +bool_t mmcDisconnect(MMCDriver *mmcp) { + + chDbgCheck(mmcp != NULL, "mmcConnect"); + + chDbgAssert((mmcp->mmc_state != MMC_UNINIT) && + (mmcp->mmc_state != MMC_STOP), + "mmcDisconnect(), #1", + "invalid state"); + switch (mmcp->mmc_state) { + case MMC_READY: + /* Wait for the pending write operations to complete.*/ + sync(mmcp); + chSysLock(); + if (mmcp->mmc_state == MMC_READY) + mmcp->mmc_state = MMC_INSERTED; + chSysUnlock(); + case MMC_INSERTED: + return FALSE; + default: + return TRUE; + } +} + /** * @brief Starts a sequential read. * @@ -455,6 +507,8 @@ bool_t mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk) { * @retval TRUE the operation failed. */ bool_t mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer) { + static const uint8_t start[] = {0xFF, 0xFC}; + uint8_t b[1]; chDbgCheck((mmcp != NULL) && (buffer != NULL), "mmcSequentialRead"); @@ -465,8 +519,19 @@ bool_t mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer) { } chSysUnlock(); - /**/ + spiSend(mmcp->mmc_spip, sizeof(start), start); /* Data prologue. */ + spiSend(mmcp->mmc_spip, MMC_BLOCK_SIZE, buffer); /* Data. */ + spiIgnore(mmcp->mmc_spip, 2); /* CRC ignored. */ + spiReceive(mmcp->mmc_spip, 1, b); + if ((b[0] & 0x1F) == 0x05) + return FALSE; + /* Error.*/ + spiUnselect(mmcp->mmc_spip); + chSysLock(); + if (mmcp->mmc_state == MMC_WRITING) + mmcp->mmc_state = MMC_READY; + chSysUnlock(); return TRUE; } diff --git a/os/io/mmc_spi.h b/os/io/mmc_spi.h index e89f17117..717f80b84 100644 --- a/os/io/mmc_spi.h +++ b/os/io/mmc_spi.h @@ -178,6 +178,7 @@ extern "C" { void mmcStart(MMCDriver *mmcp, const MMCConfig *config); void mmcStop(MMCDriver *mmcp); bool_t mmcConnect(MMCDriver *mmcp); + bool_t mmcDisconnect(MMCDriver *mmcp); bool_t mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk); bool_t mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer); bool_t mmcStopSequentialRead(MMCDriver *mmcp); -- cgit v1.2.3