Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: DM_FATFileSystem DM_HttpServer DM_USBHost EthernetInterface USBDevice mbed-rpc mbed-rtos mbed-src
Fork of DMSupport by
Diff: FileSystems/MCIFileSystem.cpp
- Revision:
- 0:6b68dac0d986
- Child:
- 9:a33326afd686
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FileSystems/MCIFileSystem.cpp Fri Nov 21 11:42:51 2014 +0000
@@ -0,0 +1,1832 @@
+/*
+ * Copyright 2013 Embedded Artists AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/******************************************************************************
+ * Includes
+ *****************************************************************************/
+
+#include "MCIFileSystem.h"
+#include "mbed_debug.h"
+
+#include "diskio.h" //STA_* defines
+#include "gpdma.h"
+
+/******************************************************************************
+ * Defines and typedefs
+ *****************************************************************************/
+
+#define MCI_DBG 0
+
+#define CMD_TIMEOUT (0x10000)
+
+#define DATA_TIMER_VALUE_R (SDC_TRAN_CLOCK_RATE / 4) // 250ms
+#define DATA_TIMER_VALUE_W (SDC_TRAN_CLOCK_RATE) // 1000ms
+#define ACQUIRE_DELAY (0.100f) /*!< inter-command acquire oper condition delay in seconds */
+
+#define SYSCTL_CLOCK_SDC (1<<28)
+
+/**
+ * @brief SDC Clear Register bit definitions
+ */
+/** Clear all status flag*/
+#define SDC_CLEAR_ALL ((uint32_t) 0x7FF)
+
+/*
+ * SDMMC Card bus clock rate definitions
+ */
+/** Card bus clock in Card Identification Mode */
+#define SDC_IDENT_CLOCK_RATE (400000) /* 400KHz */
+/** Card bus clock in Data Transfer Mode */
+#define SDC_TRAN_CLOCK_RATE (20000000) /* 20MHz */
+
+/**
+ * @brief SDC Power Control Register bit definitions
+ */
+/** SD_CMD Output Control */
+#define SDC_PWR_OPENDRAIN (((uint32_t) 1) << 6)
+
+/**
+ * @brief SDC Command Register bit definitions
+ */
+/** SDC Command Register Bitmask */
+#define SDC_COMMAND_BITMASK ((uint32_t) 0x7FF)
+/** SDC Command Index Bitmask */
+#define SDC_COMMAND_INDEX_BITMASK ((uint32_t) 0x3F)
+/** Set SDC Command Index */
+#define SDC_COMMAND_INDEX(n) ((uint32_t) n & 0x3F)
+/** No response is expected */
+#define SDC_COMMAND_NO_RSP (((uint32_t) 0 ) << 6)
+/** Short response is expected */
+#define SDC_COMMAND_SHORT_RSP (((uint32_t) 1 ) << 6)
+/** Long response is expected */
+#define SDC_COMMAND_LONG_RSP (((uint32_t) 3 ) << 6)
+/** Response bit mask */
+#define SDC_COMMAND_RSP_BITMASK (((uint32_t) 3 ) << 6)
+/** Mark that command timer is disabled and CPSM waits for interrupt request */
+#define SDC_COMMAND_INTERRUPT (((uint32_t) 1 ) << 8)
+/** Mark that CPSM waits for CmdPend before starting sending a command*/
+#define SDC_COMMAND_PENDING (((uint32_t) 1 ) << 9)
+/** Enable CPSM */
+#define SDC_COMMAND_ENABLE (((uint32_t) 1 ) << 10)
+
+/**
+ * @brief SDC Command Response Register bit definitions
+ */
+/** SDC Command Response value */
+#define SDC_RESPCOMMAND_VAL(n) ((uint32_t) n & 0x3F)
+
+/*
+ * SD/MMC Response type definitions
+ */
+#define CMDRESP_NONE_TYPE (SDC_COMMAND_NO_RSP)
+#define CMDRESP_R1_TYPE (SDC_COMMAND_SHORT_RSP)
+#define CMDRESP_R1b_TYPE (SDC_COMMAND_SHORT_RSP)
+#define CMDRESP_R2_TYPE (SDC_COMMAND_LONG_RSP)
+#define CMDRESP_R3_TYPE (SDC_COMMAND_SHORT_RSP)
+#define CMDRESP_R6_TYPE (SDC_COMMAND_SHORT_RSP)
+#define CMDRESP_R7_TYPE (SDC_COMMAND_SHORT_RSP)
+
+/*
+ * SD command values (Command Index, Response)
+ */
+#define SD_GO_IDLE_STATE (SDC_COMMAND_INDEX(MMC_GO_IDLE_STATE) | CMDRESP_NONE_TYPE | SDC_COMMAND_INTERRUPT) /*!< GO_IDLE_STATE(MMC) or RESET(SD) */
+#define SD_CMD1_SEND_OP_COND (SDC_COMMAND_INDEX(MMC_SEND_OP_COND) | CMDRESP_R3_TYPE | 0) /*!< SEND_OP_COND(MMC) or ACMD41(SD) */
+#define SD_CMD2_ALL_SEND_CID (SDC_COMMAND_INDEX(MMC_ALL_SEND_CID) | CMDRESP_R2_TYPE | 0) /*!< ALL_SEND_CID */
+#define SD_CMD3_SET_RELATIVE_ADDR (SDC_COMMAND_INDEX(MMC_SET_RELATIVE_ADDR) | CMDRESP_R1_TYPE | 0) /*!< SET_RELATE_ADDR */
+#define SD_CMD3_SEND_RELATIVE_ADDR (SDC_COMMAND_INDEX(SD_SEND_RELATIVE_ADDR) | CMDRESP_R6_TYPE | 0) /*!< SEND_RELATE_ADDR */
+#define SD_CMD7_SELECT_CARD (SDC_COMMAND_INDEX(MMC_SELECT_CARD) | CMDRESP_R1b_TYPE | 0) /*!< SELECT/DESELECT_CARD */
+#define SD_CMD8_SEND_IF_COND (SDC_COMMAND_INDEX(SD_CMD8) | CMDRESP_R7_TYPE | 0) /*!< SEND_IF_COND */
+#define SD_CMD9_SEND_CSD (SDC_COMMAND_INDEX(MMC_SEND_CSD) | CMDRESP_R2_TYPE | 0) /*!< SEND_CSD */
+#define SD_CMD12_STOP_TRANSMISSION (SDC_COMMAND_INDEX(MMC_STOP_TRANSMISSION) | CMDRESP_R1_TYPE | 0) /*!< STOP_TRANSMISSION */
+#define SD_CMD13_SEND_STATUS (SDC_COMMAND_INDEX(MMC_SEND_STATUS) | CMDRESP_R1_TYPE | 0) /*!< SEND_STATUS */
+
+/* Block-Oriented Read Commands (class 2) */
+#define SD_CMD16_SET_BLOCKLEN (SDC_COMMAND_INDEX(MMC_SET_BLOCKLEN) | CMDRESP_R1_TYPE | 0) /*!< SET_BLOCK_LEN */
+#define SD_CMD17_READ_SINGLE_BLOCK (SDC_COMMAND_INDEX(MMC_READ_SINGLE_BLOCK) | CMDRESP_R1_TYPE | 0) /*!< READ_SINGLE_BLOCK */
+#define SD_CMD18_READ_MULTIPLE_BLOCK (SDC_COMMAND_INDEX(MMC_READ_MULTIPLE_BLOCK) | CMDRESP_R1_TYPE | 0) /*!< READ_MULTIPLE_BLOCK */
+
+/* Block-Oriented Write Commands (class 4) */
+#define SD_CMD24_WRITE_BLOCK (SDC_COMMAND_INDEX(MMC_WRITE_BLOCK) | CMDRESP_R1_TYPE | 0) /*!< WRITE_BLOCK */
+#define SD_CMD25_WRITE_MULTIPLE_BLOCK (SDC_COMMAND_INDEX(MMC_WRITE_MULTIPLE_BLOCK) | CMDRESP_R1_TYPE | 0) /*!< WRITE_MULTIPLE_BLOCK */
+
+/* Erase Commands (class 5) */
+#define SD_CMD32_ERASE_WR_BLK_START (SDC_COMMAND_INDEX(SD_ERASE_WR_BLK_START) | CMDRESP_R1_TYPE | 0) /*!< ERASE_WR_BLK_START */
+#define SD_CMD33_ERASE_WR_BLK_END (SDC_COMMAND_INDEX(SD_ERASE_WR_BLK_END) | CMDRESP_R1_TYPE | 0) /*!< ERASE_WR_BLK_END */
+#define SD_CMD38_ERASE (SDC_COMMAND_INDEX(SD_ERASE) | CMDRESP_R1b_TYPE | 0) /*!< ERASE */
+
+/* Application-Specific Commands (class 8) */
+#define SD_CMD55_APP_CMD (SDC_COMMAND_INDEX(MMC_APP_CMD) | CMDRESP_R1_TYPE | 0) /*!< APP_CMD */
+#define SD_ACMD6_SET_BUS_WIDTH (SDC_COMMAND_INDEX(SD_APP_SET_BUS_WIDTH) | CMDRESP_R1_TYPE | 0) /*!< SET_BUS_WIDTH */
+#define SD_ACMD13_SEND_SD_STATUS (SDC_COMMAND_INDEX(MMC_SEND_STATUS) | CMDRESP_R1_TYPE | 0) /*!< SEND_SD_STATUS */
+#define SD_ACMD41_SD_SEND_OP_COND (SDC_COMMAND_INDEX(SD_APP_OP_COND) | CMDRESP_R3_TYPE | 0) /*!< SD_SEND_OP_COND */
+
+/**
+ * @brief SDC Interrupt Mask Register bit definitions
+ */
+/** Mask CmdCrcFail flag.*/
+#define SDC_MASK0_CMDCRCFAIL (((uint32_t) 1 ) << 0)
+/** Mask DataCrcFail flag. */
+#define SDC_MASK0_DATACRCFAIL (((uint32_t) 1 ) << 1)
+/** Mask CmdTimeOut flag. */
+#define SDC_MASK0_CMDTIMEOUT (((uint32_t) 1 ) << 2)
+/** Mask DataTimeOut flag. */
+#define SDC_MASK0_DATATIMEOUT (((uint32_t) 1 ) << 3)
+/** Mask TxUnderrun flag. */
+#define SDC_MASK0_TXUNDERRUN (((uint32_t) 1 ) << 4)
+/** Mask RxOverrun flag. */
+#define SDC_MASK0_RXOVERRUN (((uint32_t) 1 ) << 5)
+/** Mask CmdRespEnd flag. */
+#define SDC_MASK0_CMDRESPEND (((uint32_t) 1 ) << 6)
+/** Mask CmdSent flag.*/
+#define SDC_MASK0_CMDSENT (((uint32_t) 1 ) << 7)
+/** Mask DataEnd flag.*/
+#define SDC_MASK0_DATAEND (((uint32_t) 1 ) << 8)
+/** Mask StartBitErr flag.*/
+#define SDC_MASK0_STARTBITERR (((uint32_t) 1 ) << 9)
+/** Mask DataBlockEnd flag.*/
+#define SDC_MASK0_DATABLOCKEND (((uint32_t) 1 ) << 10)
+/** Mask CmdActive flag.*/
+#define SDC_MASK0_CMDACTIVE (((uint32_t) 1 ) << 11)
+/** Mask TxActive flag.*/
+#define SDC_MASK0_TXACTIVE (((uint32_t) 1 ) << 12)
+/** Mask RxActive flag.*/
+#define SDC_MASK0_RXACTIVE (((uint32_t) 1 ) << 13)
+/** Mask TxFifoHalfEmpty flag.*/
+#define SDC_MASK0_TXFIFOHALFEMPTY (((uint32_t) 1 ) << 14)
+/** Mask RxFifoHalfFull flag.*/
+#define SDC_MASK0_RXFIFOHALFFULL (((uint32_t) 1 ) << 15)
+/** Mask TxFifoFull flag.*/
+#define SDC_MASK0_TXFIFOFULL (((uint32_t) 1 ) << 16)
+/** Mask RxFifoFull flag.*/
+#define SDC_MASK0_RXFIFOFULL (((uint32_t) 1 ) << 17)
+/** Mask TxFifoEmpty flag.*/
+#define SDC_MASK0_TXFIFOEMPTY (((uint32_t) 1 ) << 18)
+/** Mask RxFifoEmpty flag.*/
+#define SDC_MASK0_RXFIFOEMPTY (((uint32_t) 1 ) << 19)
+/** Mask TxDataAvlbl flag.*/
+#define SDC_MASK0_TXDATAAVLBL (((uint32_t) 1 ) << 20)
+/** Mask RxDataAvlbl flag.*/
+#define SDC_MASK0_RXDATAAVLBL (((uint32_t) 1 ) << 21)
+/** CMD error interrupt mask */
+#define SDC_MASK0_CMDERR (SDC_MASK0_CMDCRCFAIL | SDC_MASK0_CMDTIMEOUT | SDC_MASK0_STARTBITERR)
+/** Data Transmit Error interrupt mask */
+#define SDC_MASK0_TXDATAERR (SDC_MASK0_DATACRCFAIL | SDC_MASK0_DATATIMEOUT | SDC_MASK0_TXUNDERRUN | SDC_MASK0_STARTBITERR)
+/** Data Receive Error interrupt mask */
+#define SDC_MASK0_RXDATAERR (SDC_MASK0_DATACRCFAIL | SDC_MASK0_DATATIMEOUT | SDC_MASK0_RXOVERRUN | SDC_MASK0_STARTBITERR)
+/** Data Transfer interrupt mask*/
+#define SDC_MASK0_DATA (SDC_MASK0_DATAEND | SDC_MASK0_DATABLOCKEND )
+
+/**
+ * @brief SDC Clock Control Register bit definitions
+ */
+/** SDC Clock Control Register Bitmask */
+#define SDC_CLOCK_BITMASK ((uint32_t) 0xFFF)
+/** SDC Clock Divider Bitmask */
+#define SDC_CLOCK_CLKDIV_BITMASK (((uint32_t) 0xFF ) << 0)
+/** Set SDC Clock Divide value */
+#define SDC_CLOCK_CLKDIV(n) (((uint32_t) (n & 0x0FF)) << 0)
+
+/**
+ * @brief SDC Status Register bit definitions
+ */
+/** Command Response received (CRC check failed) */
+#define SDC_STATUS_CMDCRCFAIL (((uint32_t) 1 ) << 0)
+/** Data block sent/received (CRC check failed). */
+#define SDC_STATUS_DATACRCFAIL (((uint32_t) 1 ) << 1)
+/** Command response timeout.. */
+#define SDC_STATUS_CMDTIMEOUT (((uint32_t) 1 ) << 2)
+/** Data timeout. */
+#define SDC_STATUS_DATATIMEOUT (((uint32_t) 1 ) << 3)
+/** Transmit FIFO underrun error. */
+#define SDC_STATUS_TXUNDERRUN (((uint32_t) 1 ) << 4)
+/** Receive FIFO overrun error. */
+#define SDC_STATUS_RXOVERRUN (((uint32_t) 1 ) << 5)
+/** Command response received (CRC check passed). */
+#define SDC_STATUS_CMDRESPEND (((uint32_t) 1 ) << 6)
+/** Command sent (no response required).*/
+#define SDC_STATUS_CMDSENT (((uint32_t) 1 ) << 7)
+/** Data end (data counter is zero).*/
+#define SDC_STATUS_DATAEND (((uint32_t) 1 ) << 8)
+/** Start bit not detected on all data signals in wide bus mode..*/
+#define SDC_STATUS_STARTBITERR (((uint32_t) 1 ) << 9)
+/** Data block sent/received (CRC check passed).*/
+#define SDC_STATUS_DATABLOCKEND (((uint32_t) 1 ) << 10)
+/** Command transfer in progress.*/
+#define SDC_STATUS_CMDACTIVE (((uint32_t) 1 ) << 11)
+/** Data transmit in progress.*/
+#define SDC_STATUS_TXACTIVE (((uint32_t) 1 ) << 12)
+/** Data receive in progress.*/
+#define SDC_STATUS_RXACTIVE (((uint32_t) 1 ) << 13)
+/** Transmit FIFO half empty.*/
+#define SDC_STATUS_TXFIFOHALFEMPTY (((uint32_t) 1 ) << 14)
+/** Receive FIFO half full.*/
+#define SDC_STATUS_RXFIFOHALFFULL (((uint32_t) 1 ) << 15)
+/** Transmit FIFO full.*/
+#define SDC_STATUS_TXFIFOFULL (((uint32_t) 1 ) << 16)
+/** Receive FIFO full.*/
+#define SDC_STATUS_RXFIFOFULL (((uint32_t) 1 ) << 17)
+/** Transmit FIFO empty.*/
+#define SDC_STATUS_TXFIFOEMPTY (((uint32_t) 1 ) << 18)
+/** Receive FIFO empty.*/
+#define SDC_STATUS_RXFIFOEMPTY (((uint32_t) 1 ) << 19)
+/** Data available in transmit FIFO.*/
+#define SDC_STATUS_TXDATAAVLBL (((uint32_t) 1 ) << 20)
+/** Data available in receive FIFO.*/
+#define SDC_STATUS_RXDATAAVLBL (((uint32_t) 1 ) << 21)
+/** Command Error Status */
+#define SDC_STATUS_CMDERR (SDC_STATUS_CMDCRCFAIL | SDC_STATUS_CMDTIMEOUT | SDC_STATUS_STARTBITERR)
+/** Data Error Status */
+#define SDC_STATUS_DATAERR (SDC_STATUS_DATACRCFAIL | SDC_STATUS_DATATIMEOUT | SDC_STATUS_TXUNDERRUN \
+ | SDC_STATUS_RXOVERRUN | SDC_STATUS_STARTBITERR)
+/** FIFO Status*/
+#define SDC_STATUS_FIFO (SDC_STATUS_TXFIFOHALFEMPTY | SDC_STATUS_RXFIFOHALFFULL \
+ | SDC_STATUS_TXFIFOFULL | SDC_STATUS_RXFIFOFULL \
+ | SDC_STATUS_TXFIFOEMPTY | SDC_STATUS_RXFIFOEMPTY \
+ | SDC_STATUS_DATABLOCKEND)
+
+/** Data Transfer Status*/
+#define SDC_STATUS_DATA (SDC_STATUS_DATAEND )
+
+/**
+ * @brief SDC Data Control Register bit definitions
+ */
+/** SDC Data Control Register Bitmask */
+#define SDC_DATACTRL_BITMASK ((uint32_t) 0xFF)
+/** Enable Data Transfer */
+#define SDC_DATACTRL_ENABLE (((uint32_t) 1 ) << 0)
+/** Mark that Data is transfer from card to controller */
+#define SDC_DATACTRL_DIR_FROMCARD (((uint32_t) 1 ) << 1)
+/** Mark that Data is transfer from controller to card */
+#define SDC_DATACTRL_DIR_TOCARD ((uint32_t) 0)
+/** Mark that the transfer mode is Stream Data Transfer */
+#define SDC_DATACTRL_XFER_MODE_STREAM (((uint32_t) 1 ) << 2)
+/** Mark that the transfer mode is Block Data Transfer */
+#define SDC_DATACTRL_XFER_MODE_BLOCK ((uint32_t) 0)
+/** Enable DMA */
+#define SDC_DATACTRL_DMA_ENABLE (((uint32_t) 1 ) << 3)
+/** Set Data Block size */
+#define SDC_DATACTRL_BLOCKSIZE(n) (((uint32_t) (n & 0x0F) ) << 4)
+/** Get Data Block size value */
+#define SDC_DATACTRL_BLOCKSIZE_VAL(n) (((uint32_t) 1) << n)
+
+/**
+ * @brief OCR Register definitions
+ */
+/** Support voltage range 2.7-3.6 */
+#define SDC_OCR_27_36 ((uint32_t) 0x00FF8000)
+/** Card power up status bit */
+#define SDC_OCR_IDLE (((uint32_t) 1) << 31)
+#define SDC_OCR_BUSY (((uint32_t) 0) << 31)
+
+
+/* SD/MMC commands - this matrix shows the command, response types, and
+ supported card type for that command.
+ Command Number Resp SD MMC
+ ----------------------- ------ ----- --- ---
+ Reset (go idle) CMD0 NA x x
+ Send op condition CMD1 R3 x
+ All send CID CMD2 R2 x x
+ Send relative address CMD3 R1 x
+ Send relative address CMD3 R6 x
+ Program DSR CMD4 NA x
+ Select/deselect card CMD7 R1b x
+ Select/deselect card CMD7 R1 x
+ Send CSD CMD9 R2 x x
+ Send CID CMD10 R2 x x
+ Read data until stop CMD11 R1 x x
+ Stop transmission CMD12 R1/b x x
+ Send status CMD13 R1 x x
+ Go inactive state CMD15 NA x x
+ Set block length CMD16 R1 x x
+ Read single block CMD17 R1 x x
+ Read multiple blocks CMD18 R1 x x
+ Write data until stop CMD20 R1 x
+ Setblock count CMD23 R1 x
+ Write single block CMD24 R1 x x
+ Write multiple blocks CMD25 R1 x x
+ Program CID CMD26 R1 x
+ Program CSD CMD27 R1 x x
+ Set write protection CMD28 R1b x x
+ Clear write protection CMD29 R1b x x
+ Send write protection CMD30 R1 x x
+ Erase block start CMD32 R1 x
+ Erase block end CMD33 R1 x
+ Erase block start CMD35 R1 x
+ Erase block end CMD36 R1 x
+ Erase blocks CMD38 R1b x
+ Fast IO CMD39 R4 x
+ Go IRQ state CMD40 R5 x
+ Lock/unlock CMD42 R1b x
+ Application command CMD55 R1 x
+ General command CMD56 R1b x
+
+ *** SD card application commands - these must be preceded with ***
+ *** MMC CMD55 application specific command first ***
+ Set bus width ACMD6 R1 x
+ Send SD status ACMD13 R1 x
+ Send number WR blocks ACMD22 R1 x
+ Set WR block erase cnt ACMD23 R1 x
+ Send op condition ACMD41 R3 x
+ Set clear card detect ACMD42 R1 x
+ Send CSR ACMD51 R1 x */
+
+/**
+ * @brief Possible SDMMC card state types
+ */
+typedef enum {
+ SDMMC_IDLE_ST = 0, /*!< Idle state */
+ SDMMC_READY_ST, /*!< Ready state */
+ SDMMC_IDENT_ST, /*!< Identification State */
+ SDMMC_STBY_ST, /*!< standby state */
+ SDMMC_TRAN_ST, /*!< transfer state */
+ SDMMC_DATA_ST, /*!< Sending-data State */
+ SDMMC_RCV_ST, /*!< Receive-data State */
+ SDMMC_PRG_ST, /*!< Programming State */
+ SDMMC_DIS_ST /*!< Disconnect State */
+} SDMMC_STATE_T;
+
+
+/**
+ * @brief SD/MMC commands, arguments and responses
+ * Standard SD/MMC commands (3.1) type argument response
+ */
+/* class 1 */
+#define MMC_GO_IDLE_STATE 0 /* bc */
+#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */
+#define MMC_ALL_SEND_CID 2 /* bcr R2 */
+#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */
+#define MMC_SET_DSR 4 /* bc [31:16] RCA */
+#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */
+#define MMC_SEND_EXT_CSD 8 /* bc R1 */
+#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */
+#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */
+#define MMC_STOP_TRANSMISSION 12 /* ac R1b */
+#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */
+#define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */
+
+/* class 2 */
+#define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */
+#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */
+#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */
+
+/* class 3 */
+#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */
+
+/* class 4 */
+#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */
+#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */
+#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */
+#define MMC_PROGRAM_CID 26 /* adtc R1 */
+#define MMC_PROGRAM_CSD 27 /* adtc R1 */
+
+/* class 6 */
+#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */
+#define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */
+#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */
+
+/* class 5 */
+#define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */
+#define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */
+#define MMC_ERASE 37 /* ac R1b */
+#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
+#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
+#define SD_ERASE 38 /* ac R1b */
+
+/* class 9 */
+#define MMC_FAST_IO 39 /* ac <Complex> R4 */
+#define MMC_GO_IRQ_STATE 40 /* bcr R5 */
+
+/* class 7 */
+#define MMC_LOCK_UNLOCK 42 /* adtc R1b */
+
+/* class 8 */
+#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
+#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1b */
+
+/* SD commands type argument response */
+/* class 8 */
+/* This is basically the same command as for MMC with some quirks. */
+#define SD_SEND_RELATIVE_ADDR 3 /* ac R6 */
+#define SD_CMD8 8 /* bcr [31:0] OCR R3 */
+
+/* Application commands */
+#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
+#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R1 (R4) */
+#define SD_APP_SEND_SCR 51 /* adtc R1 */
+
+
+/**
+ * @brief MMC status in R1<br>
+ * Type<br>
+ * e : error bit<br>
+ * s : status bit<br>
+ * r : detected and set for the actual command response<br>
+ * x : detected and set during command execution. the host must poll
+ * the card by sending status command in order to read these bits.
+ * Clear condition<br>
+ * a : according to the card state<br>
+ * b : always related to the previous command. Reception of
+ * a valid command will clear it (with a delay of one command)<br>
+ * c : clear by read<br>
+ */
+
+#define R1_OUT_OF_RANGE (1UL << 31) /* er, c */
+#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */
+#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */
+#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */
+#define R1_ERASE_PARAM (1 << 27) /* ex, c */
+#define R1_WP_VIOLATION (1 << 26) /* erx, c */
+#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */
+#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */
+#define R1_COM_CRC_ERROR (1 << 23) /* er, b */
+#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */
+#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */
+#define R1_CC_ERROR (1 << 20) /* erx, c */
+#define R1_ERROR (1 << 19) /* erx, c */
+#define R1_UNDERRUN (1 << 18) /* ex, c */
+#define R1_OVERRUN (1 << 17) /* ex, c */
+#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */
+#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */
+#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */
+#define R1_ERASE_RESET (1 << 13) /* sr, c */
+#define R1_STATUS(x) (x & 0xFFFFE000)
+#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
+#define R1_READY_FOR_DATA (1 << 8) /* sx, a */
+#define R1_APP_CMD (1 << 5) /* sr, c */
+
+
+/**
+ * @brief SD/MMC card OCR register bits
+ */
+#define OCR_ALL_READY (1UL << 31) /* Card Power up status bit */
+#define OCR_HC_CCS (1 << 30) /* High capacity card */
+#define OCR_VOLTAGE_RANGE_MSK (0x00FF8000)
+
+#define SD_SEND_IF_ARG 0x000001AA
+#define SD_SEND_IF_ECHO_MSK 0x000000FF
+#define SD_SEND_IF_RESP 0x000000AA
+
+/**
+ * @brief R3 response definitions
+ */
+#define CMDRESP_R3_OCR_VAL(n) (((uint32_t) n) & 0xFFFFFF)
+#define CMDRESP_R3_S18A (((uint32_t) 1 ) << 24)
+#define CMDRESP_R3_HC_CCS (((uint32_t) 1 ) << 30)
+#define CMDRESP_R3_INIT_COMPLETE (((uint32_t) 1 ) << 31)
+
+/**
+ * @brief R6 response definitions
+ */
+#define CMDRESP_R6_RCA_VAL(n) (((uint32_t) (n >> 16)) & 0xFFFF)
+#define CMDRESP_R6_CARD_STATUS(n) (((uint32_t) (n & 0x1FFF)) | \
+ ((n & (1 << 13)) ? (1 << 19) : 0) | \
+ ((n & (1 << 14)) ? (1 << 22) : 0) | \
+ ((n & (1 << 15)) ? (1 << 23) : 0))
+
+/**
+ * @brief R7 response definitions
+ */
+/** Echo-back of check-pattern */
+#define CMDRESP_R7_CHECK_PATTERN(n) (((uint32_t) n ) & 0xFF)
+/** Voltage accepted */
+#define CMDRESP_R7_VOLTAGE_ACCEPTED (((uint32_t) 1 ) << 8)
+
+/**
+ * @brief CMD3 command definitions
+ */
+/** Card Address */
+#define CMD3_RCA(n) (((uint32_t) (n & 0xFFFF) ) << 16)
+
+/**
+ * @brief CMD7 command definitions
+ */
+/** Card Address */
+#define CMD7_RCA(n) (((uint32_t) (n & 0xFFFF) ) << 16)
+
+/**
+ * @brief CMD8 command definitions
+ */
+/** Check pattern */
+#define CMD8_CHECKPATTERN(n) (((uint32_t) (n & 0xFF) ) << 0)
+/** Recommended pattern */
+#define CMD8_DEF_PATTERN (0xAA)
+/** Voltage supplied.*/
+#define CMD8_VOLTAGESUPPLIED_27_36 (((uint32_t) 1 ) << 8)
+
+/**
+ * @brief CMD9 command definitions
+ */
+#define CMD9_RCA(n) (((uint32_t) (n & 0xFFFF) ) << 16)
+
+/**
+ * @brief CMD13 command definitions
+ */
+#define CMD13_RCA(n) (((uint32_t) (n & 0xFFFF) ) << 16)
+
+/**
+ * @brief APP_CMD command definitions
+ */
+#define CMD55_RCA(n) (((uint32_t) (n & 0xFFFF) ) << 16)
+
+/**
+ * @brief ACMD41 command definitions
+ */
+#define ACMD41_OCR(n) (((uint32_t) n) & 0xFFFFFF)
+#define ACMD41_S18R (((uint32_t) 1 ) << 24)
+#define ACMD41_XPC (((uint32_t) 1 ) << 28)
+#define ACMD41_HCS (((uint32_t) 1 ) << 30)
+
+/**
+ * @brief ACMD6 command definitions
+ */
+#define ACMD6_BUS_WIDTH(n) ((uint32_t) n & 0x03)
+#define ACMD6_BUS_WIDTH_1 (0)
+#define ACMD6_BUS_WIDTH_4 (2)
+
+/** @brief Card type defines
+ */
+#define CARD_TYPE_SD (1 << 0)
+#define CARD_TYPE_4BIT (1 << 1)
+#define CARD_TYPE_8BIT (1 << 2)
+#define CARD_TYPE_HC (OCR_HC_CCS)/*!< high capacity card > 2GB */
+
+/**
+ * @brief SD/MMC sector size in bytes
+ */
+#define MMC_SECTOR_SIZE 512
+
+/******************************************************************************
+ * External global variables
+ *****************************************************************************/
+
+/******************************************************************************
+ * Local variables
+ *****************************************************************************/
+
+static MCIFileSystem* pUglyForIRQ = NULL;
+
+/******************************************************************************
+ * Local Functions
+ *****************************************************************************/
+
+static void mymciirq()
+{
+ pUglyForIRQ->mci_MCIIRQHandler();
+}
+
+static void mydmairq()
+{
+ pUglyForIRQ->mci_DMAIRQHandler();
+}
+
+/******************************************************************************
+ * Public Functions
+ *****************************************************************************/
+
+MCIFileSystem::MCIFileSystem(const char* name, PinName cd) :
+ FATFileSystem(name)
+{
+ pUglyForIRQ = this;
+
+ _Stat = STA_NOINIT;
+ memset(&_sdCardInfo, 0, sizeof(SDMMC_CARD_T));
+ _eventReceived = false;
+ _eventSuccess = false;
+
+ initMCI();
+
+ if (cd == NC)
+ {
+ _cardDetect = NULL;
+ }
+ else
+ {
+ _cardDetect = new DigitalIn(cd);
+ _cardDetect->mode(PullUp);
+ }
+}
+
+MCIFileSystem::~MCIFileSystem()
+{
+ if (_cardDetect != NULL)
+ {
+ delete _cardDetect;
+ }
+}
+void MCIFileSystem::initMCI()
+{
+ // Pinsel for MCI
+ LPC_IOCON->P1_2 = 2; /* SD_CLK @ P1.2 */
+ LPC_IOCON->P1_3 = 2; /* SD_CMD @ P1.3 */
+ LPC_IOCON->P1_5 = 2 | (1<<7); /* SD_PWR @ P1.5 - digital mode */
+ LPC_IOCON->P1_6 = 2 | (1<<7); /* SD_DAT[0] @ P1.6 - digital mode */
+ LPC_IOCON->P1_7 = 2 | (1<<7); /* SD_DAT[1] @ P1.7 - digital mode */
+ LPC_IOCON->P1_11 = 2; /* SD_DAT[2] @ P1.11 */
+ LPC_IOCON->P1_12 = 2; /* SD_DAT[3] @ P1.12 */
+
+ LPC_SC->PCONP |= SYSCTL_CLOCK_SDC;
+ LPC_SC->RSTCON0 = (1<<28);
+ LPC_SC->RSTCON0 &= ~(1<<28);
+
+ /* Initialize GPDMA controller */
+ gpdma_init();
+
+ /* Initialize SDC peripheral */
+ LPC_SC->PCONP |= SYSCTL_CLOCK_SDC;
+
+ /* Disable SD_CLK */
+ mci_ClockControl(SDC_CLOCK_ENABLE, false);
+
+ /* Power-off */
+ mci_PowerControl(PowerOff, 0);
+ mci_WriteDelay();
+
+ /* Disable all interrupts */
+ LPC_MCI->MASK0 = 0;
+
+ /*Setting for timeout problem */
+ LPC_MCI->DATATMR = 0x1FFFFFFF;
+
+ LPC_MCI->COMMAND = 0;
+ mci_WriteDelay();
+
+ LPC_MCI->DATACTRL = 0;
+ mci_WriteDelay();
+
+ /* clear all pending interrupts */
+ LPC_MCI->CLEAR = SDC_CLEAR_ALL;
+
+ /* Power-up SDC Peripheral */
+ mci_PowerControl(PowerUp, 0);
+
+ /* delays for the supply output is stable*/
+ for (uint32_t i = 0; i < 0x80000; i++ ) {}
+
+ mci_SetClock(SDC_IDENT_CLOCK_RATE);
+ mci_ClockControl(SDC_CLOCK_ENABLE, true);
+
+ /* Power-on SDC Interface */
+ mci_PowerControl(PowerOn, 0);
+
+ NVIC_SetVector(MCI_IRQn, (uint32_t) mymciirq);
+ NVIC_EnableIRQ(MCI_IRQn);
+
+ NVIC_SetVector(DMA_IRQn, (uint32_t) mydmairq);
+ NVIC_EnableIRQ(DMA_IRQn);
+}
+
+int MCIFileSystem::disk_initialize() {
+
+ debug_if(MCI_DBG, "mcifs:disk_initialize(), _Stat = %#x\n", _Stat);
+
+ if (!cardInserted()) {
+ /* No card in the socket */
+ _Stat = STA_NODISK | STA_NOINIT;
+ }
+
+ if (_Stat != STA_NOINIT) {
+ return _Stat; /* card is already enumerated */
+ }
+
+ //rtc_init();
+
+ /* Initialize the Card Data Strucutre */
+ memset(&_sdCardInfo, 0, sizeof(SDMMC_CARD_T));
+
+ /* Reset */
+ _Stat = STA_NOINIT;
+
+ /* Enumerate the card once detected. Note this function may block for a little while. */
+ int ret = mci_Acquire();
+ if (ret != 1) {
+ debug("Card Acquire failed... got %d, but expected 1\r\n", ret);
+ return 1;//Stat;
+ }
+
+ _Stat &= ~STA_NOINIT;
+ return _Stat;
+}
+
+int MCIFileSystem::disk_write(const uint8_t *buffer, uint64_t block_number, uint8_t count) {
+ debug_if(MCI_DBG, "mcifs:disk_write(%#x, %llu, %u), _Stat = %#x\n", (uint32_t)buffer, block_number, count, _Stat);
+ if (_Stat & STA_NOINIT) {
+ // not ready
+ return 1;
+ }
+ if (mci_WriteBlocks((void*)buffer, block_number, count) == SDC_RET_OK) {
+ return 0;
+ }
+
+ return 1;
+}
+
+int MCIFileSystem::disk_read(uint8_t *buffer, uint64_t block_number, uint8_t count) {
+ debug_if(MCI_DBG, "mcifs:disk_read(%#x, %llu, %u), _Stat = %#x\n", (uint32_t)buffer, block_number, count, _Stat);
+ if (_Stat & STA_NOINIT) {
+ // not ready
+ return _Stat;
+ }
+ if (mci_ReadBlocks(buffer, block_number, count) == SDC_RET_OK) {
+ return 0;
+ }
+
+ return 1;
+}
+
+int MCIFileSystem::disk_status()
+{
+ debug_if(MCI_DBG, "mcifs:disk_status(), _Stat = %#x\n", _Stat);
+ return _Stat;
+}
+
+int MCIFileSystem::disk_sync()
+{
+ debug_if(MCI_DBG, "mcifs:disk_sync(), _Stat = %#x\n", _Stat);
+ uint32_t end = us_ticker_read() + 50*1000; // 50ms
+ while (us_ticker_read() < end)
+ {
+ if (mci_GetCardStatus() & R1_READY_FOR_DATA)
+ {
+ // card is ready
+ return 0;
+ }
+ }
+ // timeout while waiting for card to get ready
+ return 1;
+}
+
+uint64_t MCIFileSystem::disk_sectors()
+{
+ debug_if(MCI_DBG, "mcifs:disk_sectors(), _Stat = %#x, returning %llu\n", _Stat, _sdCardInfo.blocknr);
+ return _sdCardInfo.blocknr;
+}
+
+void MCIFileSystem::mci_MCIIRQHandler()
+{
+ int32_t Ret;
+
+ Ret = mci_IRQHandler(NULL, 0, NULL, 0);
+ if(Ret < 0) {
+ _eventSuccess = false;
+ _eventReceived = true;
+ }
+}
+
+void MCIFileSystem::mci_DMAIRQHandler()
+{
+ _eventSuccess = gpdma_interrupt(_eventDmaChannel);
+ _eventReceived = true;
+ NVIC_DisableIRQ(DMA_IRQn);
+}
+
+/******************************************************************************
+ * Private Functions
+ *****************************************************************************/
+
+bool MCIFileSystem::cardInserted() const
+{
+ // If no card detect pin is given, then assume that a card is inserted.
+ // If a pin is specified then use that to determing the presence of a card.
+ return ((_cardDetect == NULL) || (_cardDetect->read() == 0));
+}
+
+
+
+int32_t MCIFileSystem::mci_Acquire()
+{
+ int32_t Ret;
+
+ /* Initialize card info */
+ _sdCardInfo.speed = SDC_TRAN_CLOCK_RATE;
+ _sdCardInfo.card_type = 0;
+
+ /* During identification phase, the clock should be less than
+ 400Khz. Once we pass this phase, the normal clock can be set up
+ to 25Mhz on SD card and 20Mhz on MMC card. */
+ mci_SetClock(SDC_IDENT_CLOCK_RATE);
+
+ /* Clear Open Drain output control for SD */
+ mci_PowerControl(PowerOn, 0);
+
+ /* Card Reset */
+ Ret = mci_ExecuteCmd(SD_GO_IDLE_STATE, 0, NULL);
+ if (Ret != 0) {
+ return Ret;
+ }
+
+ wait(ACQUIRE_DELAY);
+
+ /* Send interface operation condiftion */
+ Ret = mci_SendIfCond();
+ if (Ret == SDC_RET_BAD_PARAMETERS) {
+ return Ret; /* Non-compatible voltage range or check pattern is not correct */
+
+ }
+ /* Get Card Type */
+ if (Ret == SDC_RET_OK) {/* Ver2.00 or later SD Memory Card*/
+ bool CCS;
+ uint32_t OCR = SDC_OCR_27_36;
+ _sdCardInfo.card_type |= CARD_TYPE_SD;
+ Ret = mci_SendAppOpCond(0, true, &OCR, &CCS);
+ if (CCS) { /* High Capacity or Extended Capacity SD Memory Card */
+ _sdCardInfo.card_type |= CARD_TYPE_HC;
+ }
+ }
+ else { /*Ver2.00 or later SD Memory Card(voltage mismatch) or Ver1.X SD Memory Card
+ or not SD Memory Card*/
+ bool CCS;
+ uint32_t OCR = SDC_OCR_27_36;
+ Ret = mci_SendAppOpCond(0, false, &OCR, &CCS);
+ if (Ret == SDC_RET_OK) {
+ _sdCardInfo.card_type |= CARD_TYPE_SD;
+ }
+ else if (Ret == SDC_RET_BAD_PARAMETERS) {
+ return Ret;
+ }
+ else { /* MMC Card setup */
+ uint32_t OCR;
+ /* Enter to Open Drain mode */
+ mci_PowerControl(PowerOn, SDC_PWR_OPENDRAIN);
+ wait(ACQUIRE_DELAY);
+ Ret = mci_SendOpCond(&OCR);
+ if (Ret != SDC_RET_OK) {
+ return Ret;
+ }
+
+ }
+ }
+
+ /* Read CID */
+ mci_GetCID(_sdCardInfo.cid);
+
+ /* RCA send, for SD get RCA */
+ if (_sdCardInfo.card_type & CARD_TYPE_SD) {
+ mci_GetAddr(&_sdCardInfo.rca);
+ }
+ else {
+ _sdCardInfo.rca = 1;
+ mci_SetAddr(_sdCardInfo.rca);
+ mci_PowerControl(PowerOn, 0); /* enter to push-pull mode */
+ }
+
+ /* Get CSD */
+ mci_GetCSD(_sdCardInfo.rca, _sdCardInfo.csd);
+
+ /* Compute card size, block size and no. of blocks based on CSD response recived. */
+ if (_sdCardInfo.cid[0]) {
+ mci_ProcessCSD();
+
+ if (mci_SetTranState(_sdCardInfo.rca) != SDC_RET_OK) {
+ return 0;
+ }
+
+ if (mci_GetCardState() != SDMMC_TRAN_ST) {
+ return 0;
+ }
+
+ if (mci_SetCardParams() != 0) {
+ return 0;
+ }
+ }
+
+ return (_sdCardInfo.cid[0]) ? 1 : 0;
+}
+
+uint32_t MCIFileSystem::mci_GetCardStatus() const
+{
+ uint32_t Status;
+ mci_GetStatus(_sdCardInfo.rca, &Status);
+ return Status;
+}
+
+MCIFileSystem::CardState MCIFileSystem::mci_GetCardState() const
+{
+ uint32_t Status;
+ volatile int32_t Ret;
+
+ /* get current state of the card */
+ Ret = mci_GetStatus(_sdCardInfo.rca, &Status);
+
+ /* check card state in response */
+ return (CardState) R1_CURRENT_STATE(Status);
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_StopTransmission(uint32_t rca) const
+{
+ uint32_t Status;
+ ReturnCode Ret = SDC_RET_FAILED;
+ response_t Response;
+ uint32_t RetryCnt = 20;
+
+ Ret = mci_GetStatus(rca, &Status);
+ if (Ret != SDC_RET_OK) {
+ return SDC_RET_ERR_STATE;
+ }
+
+ if (R1_CURRENT_STATE(Status) == SDMMC_TRAN_ST) {
+ return SDC_RET_OK;
+ }
+
+ if ((R1_CURRENT_STATE(Status) != SDMMC_DATA_ST) &&
+ (R1_CURRENT_STATE(Status) != SDMMC_RCV_ST)) {
+ return SDC_RET_ERR_STATE;
+ }
+
+ while (RetryCnt > 0) {
+ Ret = mci_ExecuteCmd(SD_CMD12_STOP_TRANSMISSION, 0, &Response);
+ if (Ret == SDC_RET_OK) {
+ if (mci_CheckR1Response(Response.Data[0], &Ret)) {
+ if (Ret != SDC_RET_OK) {
+ return Ret;
+ }
+ Ret = mci_GetStatus(rca, &Status);
+ if ((R1_CURRENT_STATE(Status) == SDMMC_TRAN_ST) || (R1_CURRENT_STATE(Status) == SDMMC_PRG_ST)) {
+ return SDC_RET_OK;
+ }
+ return SDC_RET_ERR_STATE;
+ }
+ }
+ RetryCnt--;
+ }
+ return Ret;
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_ReadBlocks(void *buffer, int32_t startBlock, int32_t blockNum)
+{
+ ReturnCode Ret = SDC_RET_FAILED;
+ uint8_t dmaChannel;
+ int32_t ByteNum = blockNum * MMC_SECTOR_SIZE;
+
+ do
+ {
+ /* if card is not acquired return immediately */
+ if (( startBlock < 0) || ( (startBlock + blockNum) > _sdCardInfo.blocknr) ) {
+ Ret = SDC_RET_NOT_READY;
+ break;
+ }
+
+ /* Put to tran state */
+ Ret = mci_SetTranState(_sdCardInfo.rca);
+ if (Ret != SDC_RET_OK) {
+ break;
+ }
+
+ LPC_MCI->MASK0 = SDC_MASK0_DATA | SDC_MASK0_RXDATAERR;
+
+ /* DMA Setup */
+ gpdma_getFreeChannel(&dmaChannel);
+ gpdma_transfer_from_mci(dmaChannel, (uint32_t)buffer, ByteNum);
+ mci_SetupEventWakeup(dmaChannel);
+
+ /* set transfer information */
+ mci_SetDataTransfer(blockNum, true, DATA_TIMER_VALUE_R);
+
+ Ret = _readBlocks(_sdCardInfo.card_type, startBlock, blockNum);
+ if (Ret == SDC_RET_OK) {
+ /* Wait for transfer Finish */
+ if (mci_WaitForEvent() != 0) {
+ Ret = SDC_RET_FAILED;
+ }
+ } else {
+ Ret = SDC_RET_FAILED;
+ }
+
+ gpdma_stop(dmaChannel);
+
+ if ((blockNum > 1) || (mci_GetCardState() == SDMMC_DATA_ST)) {
+ /* Send Stop transmission command */
+ mci_StopTransmission(_sdCardInfo.rca);
+ }
+
+ /* Wait for card to enter tran state */
+ while (mci_GetCardState() != SDMMC_TRAN_ST) {}
+
+ } while(false);
+
+ return Ret;
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_WriteBlocks(void *buffer, int32_t startBlock, int32_t blockNum)
+{
+ ReturnCode Ret = SDC_RET_FAILED;
+ uint8_t dmaChannel;
+
+ do
+ {
+ /* if card is not acquired return immediately */
+ if (( startBlock < 0) || ( (startBlock + blockNum) > _sdCardInfo.blocknr) ) {
+ Ret = SDC_RET_NOT_READY;
+ break;
+ }
+
+ /* Put to tran state */
+ Ret = mci_SetTranState(_sdCardInfo.rca);
+ if (Ret != SDC_RET_OK) {
+ break;
+ }
+
+ Ret = _writeBlocks(_sdCardInfo.card_type, startBlock, blockNum);
+ if (Ret != SDC_RET_OK) {
+ break;
+ }
+
+ /*Wait for card enter to rcv state*/
+ while (mci_GetCardState() != SDMMC_RCV_ST) {}
+
+ LPC_MCI->MASK0 = SDC_MASK0_DATA | SDC_MASK0_TXDATAERR;
+
+ /* DMA Setup */
+ gpdma_getFreeChannel(&dmaChannel);
+ gpdma_transfer_to_mci(dmaChannel, (uint32_t)buffer, blockNum*MMC_SECTOR_SIZE);
+ mci_SetupEventWakeup(dmaChannel);
+
+ /* set transfer information */
+ mci_SetDataTransfer(blockNum, false, DATA_TIMER_VALUE_W);
+
+ /* Wait for transfer done */
+ if (mci_WaitForEvent() != 0) {
+ Ret = SDC_RET_FAILED;
+ }
+ gpdma_stop(dmaChannel);
+
+ if ((blockNum > 1) || (mci_GetCardState() == SDMMC_RCV_ST)) {
+ /* Send Stop transmission command */
+ mci_StopTransmission(_sdCardInfo.rca);
+ }
+
+ /* Wait for card to enter tran state */
+ while (mci_GetCardState() != SDMMC_TRAN_ST) {}
+
+ } while (false);
+
+ return Ret;
+}
+
+void MCIFileSystem::mci_SetClock(uint32_t freq) const
+{
+ uint32_t PClk;
+ uint32_t ClkValue = 0;
+
+ PClk = PeripheralClock;
+
+ ClkValue = (PClk + 2 * freq - 1) / (2 * freq);
+ if (ClkValue > 0) {
+ ClkValue -= 1;
+ }
+ uint32_t temp;
+ temp = (LPC_MCI->CLOCK & (~SDC_CLOCK_CLKDIV_BITMASK));
+ LPC_MCI->CLOCK = temp | (SDC_CLOCK_CLKDIV(ClkValue));
+ mci_WriteDelay();
+}
+
+void MCIFileSystem::mci_ClockControl(ClockControl ctrlType, bool enable) const
+{
+ if (enable) {
+ LPC_MCI->CLOCK |= (1 << ctrlType);
+ }
+ else {
+ LPC_MCI->CLOCK &= (~(1 << ctrlType));
+ }
+ mci_WriteDelay();
+}
+
+void MCIFileSystem::mci_PowerControl(power_ctrl_t powerMode, uint32_t flag) const
+{
+ LPC_MCI->POWER = (powerMode & 0x3) | flag;
+ mci_WriteDelay();
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_ExecuteCmd(uint32_t Command, uint32_t Arg, response_t* pResp) const
+{
+ ReturnCode Ret = SDC_RET_FAILED;
+
+ /* Send Command to card */
+ Ret = mci_SendCmd(Command, Arg, CMD_TIMEOUT);
+ if (Ret != SDC_RET_OK) {
+ return Ret;
+ }
+
+ /* Get response (if any) */
+ if ((Command & SDC_COMMAND_RSP_BITMASK) != SDC_COMMAND_NO_RSP) {
+
+ mci_GetResp(pResp);
+
+ /* If the response is not R1, in the response field, the Expected Cmd data
+ won't be the same as the CMD data in SendCmd(). Below four cmds have
+ R2 or R3 response. We don't need to check if MCI_RESP_CMD is the same
+ as the Expected or not. */
+ if ((SDC_COMMAND_INDEX(Command) != MMC_SEND_OP_COND) &&
+ (SDC_COMMAND_INDEX(Command) != SD_APP_OP_COND) &&
+ (SDC_COMMAND_INDEX(Command) != MMC_ALL_SEND_CID) &&
+ (SDC_COMMAND_INDEX(Command) != MMC_SEND_CSD) &&
+ (pResp->CmdIndex != SDC_COMMAND_INDEX(Command))) {
+ return SDC_RET_CMD_FAILED;
+ }
+ }
+
+ return SDC_RET_OK;
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_SendIfCond() const
+{
+ ReturnCode Ret = SDC_RET_FAILED;
+ response_t Response;
+ uint32_t RetryCnt = 20;
+
+ while (RetryCnt > 0) {
+ Ret = mci_ExecuteCmd(SD_CMD8_SEND_IF_COND, (CMD8_VOLTAGESUPPLIED_27_36 | CMD8_CHECKPATTERN(
+ CMD8_DEF_PATTERN)), &Response);
+ if (Ret == SDC_RET_OK) {
+ if ((Response.Data[0] & CMDRESP_R7_VOLTAGE_ACCEPTED) &&
+ (CMDRESP_R7_CHECK_PATTERN(Response.Data[0]) == CMD8_DEF_PATTERN)) {
+ return SDC_RET_OK;
+ }
+ return SDC_RET_BAD_PARAMETERS;
+ }
+ RetryCnt--;
+ }
+ return Ret;
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_SendOpCond(uint32_t *pOCR) const
+{
+ ReturnCode Ret = SDC_RET_FAILED;
+ response_t Response;
+ uint32_t RetryCnt = 0x200;
+
+ while (RetryCnt > 0) {
+ Ret = mci_ExecuteCmd(SD_CMD1_SEND_OP_COND, SDC_OCR_27_36, &Response);
+ if (Ret == SDC_RET_OK) {
+ *pOCR = Response.Data[0];
+ if (*pOCR & SDC_OCR_IDLE) {
+ if ((Response.Data[0] & SDC_OCR_27_36) != SDC_OCR_27_36) {
+ return SDC_RET_BAD_PARAMETERS;
+ }
+ return SDC_RET_OK;
+ }
+ }
+ RetryCnt--;
+ }
+ return SDC_RET_FAILED;
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_SendAppOpCond(uint16_t rca, bool hcs, uint32_t *pOcr, bool *pCCS) const
+{
+ ReturnCode Ret = SDC_RET_FAILED;
+ response_t Response;
+ uint32_t Argument;
+ uint32_t RetryCnt = 0x2000; /* The host repeatedly issues ACMD41 for at least 1 second or
+ until the busy bit are set to 1 */
+
+ Argument = ACMD41_OCR(*pOcr);
+ if (hcs) {
+ Argument |= ACMD41_HCS;
+ }
+
+ while (RetryCnt > 0) {
+ Ret = mci_SendAppCmd(rca);
+ if (Ret == SDC_RET_OK) {
+ Ret = mci_ExecuteCmd(SD_ACMD41_SD_SEND_OP_COND, Argument, &Response);
+ if (Ret == SDC_RET_OK) {
+ if (Response.Data[0] & CMDRESP_R3_INIT_COMPLETE) {
+ if (*pOcr == 0) {
+ *pOcr = CMDRESP_R3_OCR_VAL(Response.Data[0]);
+ return SDC_RET_OK;
+ }
+ if ((CMDRESP_R3_OCR_VAL(Response.Data[0]) & *pOcr) != *pOcr) {
+ return SDC_RET_BAD_PARAMETERS;
+ }
+ *pCCS = (Response.Data[0] & CMDRESP_R3_HC_CCS) ? true : false;
+ return SDC_RET_OK;
+ }
+ }
+ }
+ else {
+ //If we abort here then some cards will go undetected, better to keep retrying
+ //return Ret;
+ }
+ RetryCnt--;
+ }
+ return SDC_RET_FAILED;
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_GetCID(uint32_t *pCID) const
+{
+ ReturnCode Ret = SDC_RET_FAILED;
+ response_t Response;
+ uint32_t RetryCnt = 20;
+
+ while (RetryCnt > 0) {
+ Ret = mci_ExecuteCmd(SD_CMD2_ALL_SEND_CID, 0, &Response);
+ if (Ret == SDC_RET_OK) {
+ pCID[3] = Response.Data[0];
+ pCID[2] = Response.Data[1];
+ pCID[1] = Response.Data[2];
+ pCID[0] = Response.Data[3];
+ return SDC_RET_OK;
+ }
+ RetryCnt--;
+ }
+ return Ret;
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_SetAddr(uint16_t addr) const
+{
+ ReturnCode Ret = SDC_RET_FAILED;
+ response_t Response;
+ uint32_t RetryCnt = 20;
+
+ while (RetryCnt > 0) {
+ Ret = mci_ExecuteCmd(SD_CMD3_SET_RELATIVE_ADDR, CMD3_RCA(addr), &Response);
+ if (Ret == SDC_RET_OK) {
+ if (mci_CheckR1Response(Response.Data[0], &Ret)) {
+ return Ret;
+ }
+ }
+ RetryCnt--;
+ }
+ return Ret;
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_GetAddr(uint16_t *pRCA) const
+{
+ ReturnCode Ret = SDC_RET_FAILED;
+ response_t Response;
+ uint32_t RetryCnt = 20;
+
+ *pRCA = 0;
+ while (RetryCnt > 0) {
+ Ret = mci_ExecuteCmd(SD_CMD3_SEND_RELATIVE_ADDR, 0, &Response);
+ if (Ret == SDC_RET_OK) {
+ if (!(CMDRESP_R6_CARD_STATUS(Response.Data[0]) & R1_READY_FOR_DATA)) {
+ Ret = SDC_RET_NOT_READY;
+ }
+ else if (R1_CURRENT_STATE(CMDRESP_R6_CARD_STATUS(Response.Data[0])) != SDMMC_STBY_ST) {
+ Ret = SDC_RET_ERR_STATE;
+ }
+ else {
+ *pRCA = CMDRESP_R6_RCA_VAL(Response.Data[0]);
+ return SDC_RET_OK;
+ }
+ }
+ RetryCnt--;
+ }
+ return Ret;
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_GetCSD(uint16_t rca, uint32_t *pCSD) const
+{
+ ReturnCode Ret = SDC_RET_FAILED;
+ response_t Response;
+ uint32_t RetryCnt = 20;
+
+ while (RetryCnt > 0) {
+ Ret = mci_ExecuteCmd(SD_CMD9_SEND_CSD, CMD9_RCA(rca), &Response);
+ if (Ret == SDC_RET_OK) {
+ pCSD[3] = Response.Data[0];
+ pCSD[2] = Response.Data[1];
+ pCSD[1] = Response.Data[2];
+ pCSD[0] = Response.Data[3];
+ return Ret;
+ }
+ RetryCnt--;
+ }
+ return Ret;
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_SelectCard(uint16_t addr) const
+{
+ ReturnCode Ret = SDC_RET_FAILED;
+ response_t Response;
+ uint32_t RetryCnt = 20;
+
+ while (RetryCnt > 0) {
+ Ret = mci_ExecuteCmd(SD_CMD7_SELECT_CARD, CMD7_RCA(addr), &Response);
+ if (Ret == SDC_RET_OK) {
+ if (mci_CheckR1Response(Response.Data[0], &Ret)) {
+ return Ret;
+ }
+ }
+ RetryCnt--;
+ }
+ return Ret;
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_GetStatus(uint16_t rca, uint32_t *pStatus) const
+{
+ ReturnCode Ret = SDC_RET_FAILED;
+ response_t Response;
+ uint32_t RetryCnt = 20;
+
+ *pStatus = (uint32_t) -1;
+ while (RetryCnt > 0) {
+ Ret = mci_ExecuteCmd(SD_CMD13_SEND_STATUS, CMD13_RCA(rca), &Response);
+ if (Ret == SDC_RET_OK) {
+ mci_CheckR1Response(Response.Data[0], &Ret);
+ *pStatus = Response.Data[0];
+ return Ret;
+ }
+ RetryCnt--;
+ }
+ return Ret;
+}
+
+void MCIFileSystem::mci_ProcessCSD()
+{
+ int32_t CSize = 0;
+ int32_t CSizeMult = 0;
+ int32_t Mult = 0;
+
+ /* compute block length based on CSD response */
+ _sdCardInfo.block_len = 1 << mci_GetBits(80, 83, _sdCardInfo.csd);
+
+ if ((_sdCardInfo.card_type & CARD_TYPE_HC) && (_sdCardInfo.card_type & CARD_TYPE_SD)) {
+ /* See section 5.3.3 CSD Register (CSD Version 2.0) of SD2.0 spec an explanation for the calculation of these values */
+ CSize = mci_GetBits(48, 63, (uint32_t *) _sdCardInfo.csd) + 1;
+ _sdCardInfo.blocknr = CSize << 10; /* 512 byte blocks */
+ }
+ else {
+ /* See section 5.3 of the 4.1 revision of the MMC specs for an explanation for the calculation of these values */
+ CSize = mci_GetBits(62, 73, (uint32_t *) _sdCardInfo.csd);
+ CSizeMult = mci_GetBits(47, 49, (uint32_t *) _sdCardInfo.csd);
+ Mult = 1 << (CSizeMult + 2);
+ _sdCardInfo.blocknr = (CSize + 1) * Mult;
+
+ /* adjust blocknr to 512/block */
+ if (_sdCardInfo.block_len > MMC_SECTOR_SIZE) {
+ _sdCardInfo.blocknr = _sdCardInfo.blocknr * (_sdCardInfo.block_len >> 9);
+ }
+ }
+
+ _sdCardInfo.device_size = _sdCardInfo.blocknr << 9; /* blocknr * 512 */
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_SetBusWidth(uint16_t rca, uint8_t width) const
+{
+ ReturnCode Ret = SDC_RET_FAILED;
+ response_t Response;
+ uint8_t RetryCnt = 0x20;
+
+ while (RetryCnt > 0) {
+ Ret = mci_SendAppCmd(rca);
+ if (Ret == SDC_RET_OK) {
+ Ret = mci_ExecuteCmd(SD_ACMD6_SET_BUS_WIDTH, ACMD6_BUS_WIDTH(width), &Response);
+ if (Ret == SDC_RET_OK) {
+ if (mci_CheckR1Response(Response.Data[0], &Ret)) {
+ return Ret;
+ }
+ }
+ }
+ RetryCnt--;
+ }
+ return SDC_RET_FAILED;
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_SetTranState(uint16_t rca) const
+{
+ ReturnCode Ret = SDC_RET_OK;
+ uint32_t status = 0;
+ SDMMC_STATE_T state;
+
+ /* get current state of the card */
+ Ret = mci_GetStatus(rca, &status);
+ if (Ret != SDC_RET_OK) {
+ /* unable to get the card state. So return immediatly. */
+ return Ret;
+ }
+
+ /* check card state in response */
+ state = (SDMMC_STATE_T) R1_CURRENT_STATE(status);
+ switch (state) {
+ case SDMMC_STBY_ST:
+ /* put card in 'Trans' state */
+ Ret = mci_SelectCard(rca);
+ if (Ret != SDC_RET_OK) {
+ /* unable to put the card in Trans state. So return immediatly. */
+ return Ret;
+ }
+ mci_GetStatus(rca, &status);
+ if (((SDMMC_STATE_T) R1_CURRENT_STATE(status)) != SDMMC_TRAN_ST) {
+ return SDC_RET_ERR_STATE;
+ }
+ break;
+
+ case SDMMC_TRAN_ST:
+ /*do nothing */
+ break;
+
+ default:
+ /* card shouldn't be in other states so return */
+ return SDC_RET_ERR_STATE;
+ }
+
+ return SDC_RET_OK;
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_SetBlockLength(uint32_t rca, uint32_t block_len) const
+{
+ ReturnCode Ret = SDC_RET_FAILED;
+ response_t Response;
+ uint8_t RetryCnt = 0x20;
+
+ while (RetryCnt > 0) {
+ Ret = mci_ExecuteCmd(SD_CMD16_SET_BLOCKLEN, block_len, &Response);
+ if (Ret == SDC_RET_OK) {
+ if (mci_CheckR1Response(Response.Data[0], &Ret)) {
+ return Ret;
+ }
+ }
+ RetryCnt--;
+ }
+ return SDC_RET_FAILED;
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_SetCardParams() const
+{
+ ReturnCode Ret;
+
+ mci_SetClock(SDC_TRAN_CLOCK_RATE);
+ if (_sdCardInfo.card_type & CARD_TYPE_SD) {
+ mci_ClockControl(SDC_CLOCK_WIDEBUS_MODE, true);
+ Ret = mci_SetBusWidth(_sdCardInfo.rca, ACMD6_BUS_WIDTH_4);
+ if (Ret != SDC_RET_OK) {
+ return Ret;
+ }
+ }
+ else {
+ mci_ClockControl(SDC_CLOCK_WIDEBUS_MODE, false);
+ }
+
+ /* set block length */
+ Ret = mci_SetBlockLength(_sdCardInfo.rca, MMC_SECTOR_SIZE);
+ return Ret;
+}
+
+bool MCIFileSystem::mci_CheckR1Response(uint32_t resp, ReturnCode* pCheckResult) const
+{
+ bool Ret = true;
+
+ if (!(resp & R1_READY_FOR_DATA)) {
+ *pCheckResult = SDC_RET_NOT_READY;
+ Ret = false;
+ }
+ else if (R1_STATUS(resp)) {
+ *pCheckResult = SDC_RET_FAILED;
+ }
+ else {
+ *pCheckResult = SDC_RET_OK;
+ }
+ return Ret;
+}
+
+void MCIFileSystem::mci_WriteDelay() const
+{
+// volatile uint8_t i;
+// for ( i = 0; i < 0x10; i++ ) { /* delay 3MCLK + 2PCLK */
+// }
+ wait(0.00001f); /* delay 10 us */
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_SendCmd(uint32_t Command, uint32_t Arg, uint32_t timeout) const
+{
+ ReturnCode ret = SDC_RET_TIMEOUT;
+ uint32_t Status;
+
+ /* Set Command Info */
+ mci_SetCommand(Command, Arg);
+
+ while (timeout) {
+
+ Status = LPC_MCI->STATUS;
+
+ /* check if command was sent */
+ if (((Command & SDC_COMMAND_RSP_BITMASK) == SDC_COMMAND_NO_RSP) && (Status & SDC_STATUS_CMDSENT)) {
+ ret = SDC_RET_OK;
+ break;
+ }
+ /* check if response was received */
+ if (Status & SDC_STATUS_CMDRESPEND) {
+ ret = SDC_RET_OK;
+ break;
+ }
+
+ /* check command sending status */
+ if (Status & SDC_STATUS_CMDERR) {
+ if (Status & SDC_STATUS_CMDCRCFAIL) {
+ if ((SDC_COMMAND_INDEX(Command) == MMC_SEND_OP_COND) ||
+ (SDC_COMMAND_INDEX(Command) == SD_APP_OP_COND) ||
+ (SDC_COMMAND_INDEX(Command) == MMC_STOP_TRANSMISSION)) {
+ ret = SDC_RET_OK; /* ignore CRC error if it's a resp for SEND_OP_COND or STOP_TRANSMISSION. */
+ break;
+ }
+ }
+ ret = SDC_RET_CMD_FAILED;
+ break;
+ }
+
+ timeout--;
+ }
+
+ mci_ResetCommand();
+
+ return ret;
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::mci_SendAppCmd(uint16_t rca) const
+{
+ ReturnCode Ret = SDC_RET_FAILED;
+ response_t Response;
+ uint32_t RetryCnt = 20;
+
+ while (RetryCnt > 0) {
+ Ret = mci_ExecuteCmd(SD_CMD55_APP_CMD, CMD55_RCA(rca), &Response);
+ if (Ret == SDC_RET_OK) {
+ if (mci_CheckR1Response(Response.Data[0], &Ret)) {
+ if (Ret != SDC_RET_OK) {
+ return Ret;
+ }
+ if (Response.Data[0] & R1_APP_CMD) {
+ return SDC_RET_OK;
+ }
+ else {
+ Ret = SDC_RET_FAILED;
+ }
+ }
+ }
+ RetryCnt--;
+ }
+ return SDC_RET_FAILED;
+}
+
+void MCIFileSystem::mci_SetDataTransfer(uint16_t BlockNum, bool DirFromCard, uint32_t Timeout) const
+{
+ uint32_t DataCtrl = 0;
+ LPC_MCI->DATATMR = Timeout;
+ LPC_MCI->DATALEN = BlockNum * 512;
+
+ DataCtrl = SDC_DATACTRL_ENABLE;
+ // DataCtrl mode=block, block size=512byte
+ DataCtrl |= (0x9 << 4);
+ if (DirFromCard) {
+ DataCtrl |= (0x1 << 1);
+ }
+ DataCtrl |= SDC_DATACTRL_DMA_ENABLE;
+ LPC_MCI->DATACTRL = DataCtrl;
+ mci_WriteDelay();
+}
+
+void MCIFileSystem::mci_GetResp(response_t* pResp) const
+{
+ pResp->CmdIndex = SDC_RESPCOMMAND_VAL(LPC_MCI->RESP_CMD);
+ pResp->Data[0] = LPC_MCI->RESP0;
+ if (CardStatusNumBytes == 4) {
+ pResp->Data[1] = LPC_MCI->RESP1;
+ pResp->Data[2] = LPC_MCI->RESP2;
+ pResp->Data[3] = LPC_MCI->RESP3;
+ }
+}
+
+uint32_t MCIFileSystem::mci_GetBits(int32_t start, int32_t end, uint32_t *data) const
+{
+ uint32_t v;
+ uint32_t i = end >> 5;
+ uint32_t j = start & 0x1f;
+
+ if (i == (start >> 5)) {
+ v = (data[i] >> j);
+ }
+ else {
+ v = ((data[i] << (32 - j)) | (data[start >> 5] >> j));
+ }
+
+ return v & ((1 << (end - start + 1)) - 1);
+}
+
+void MCIFileSystem::mci_SetCommand(uint32_t Cmd, uint32_t Arg) const
+{
+ /* Clear status register */
+ LPC_MCI->CLEAR = SDC_CLEAR_ALL;
+
+ /* Set the argument first, finally command */
+ LPC_MCI->ARGUMENT = Arg;
+
+ /* Write command value, enable the command */
+ LPC_MCI->COMMAND = Cmd | SDC_COMMAND_ENABLE;
+
+ mci_WriteDelay();
+}
+
+void MCIFileSystem::mci_ResetCommand() const
+{
+ LPC_MCI->CLEAR = SDC_CLEAR_ALL;
+
+ LPC_MCI->ARGUMENT = 0xFFFFFFFF;
+
+ LPC_MCI->COMMAND = 0;
+
+ mci_WriteDelay();
+}
+
+int32_t MCIFileSystem::mci_IRQHandler(uint8_t *txBuf, uint32_t *txCnt, uint8_t *rxBuf, uint32_t *rxCnt)
+{
+ uint32_t Status;
+
+ Status = LPC_MCI->STATUS;
+
+ if ( Status & SDC_STATUS_DATAERR) {
+ LPC_MCI->CLEAR = SDC_STATUS_DATAERR;
+ return -1; /* Data transfer error */
+ }
+
+ if ( Status & SDC_STATUS_DATAEND) {
+ LPC_MCI->CLEAR = SDC_STATUS_DATAEND;
+ LPC_MCI->MASK0 = 0;
+ return 0;
+ }
+
+ if ( Status & SDC_STATUS_DATABLOCKEND) {
+ LPC_MCI->CLEAR = SDC_STATUS_DATABLOCKEND;
+ return 1;
+ }
+
+ if (Status & SDC_STATUS_FIFO) {
+ return mci_FIFOIRQHandler(txBuf, txCnt, rxBuf, rxCnt);
+ }
+
+ return 1;
+}
+
+int32_t MCIFileSystem::mci_FIFOIRQHandler(uint8_t *txBuf, uint32_t *txCnt, uint8_t *rxBuf, uint32_t *rxCnt)
+{
+ uint32_t Status;
+ Status = LPC_MCI->STATUS;
+
+ if (txBuf) {
+ if (Status & SDC_STATUS_TXFIFOHALFEMPTY) {
+ if (*txCnt % 64) {
+ mci_WriteFIFO((uint32_t *) &txBuf[*txCnt], false);
+ }
+ else {
+ mci_WriteFIFO((uint32_t *) &txBuf[*txCnt], true);
+ }
+ *txCnt += 32;
+ }
+ }
+
+ if (rxBuf) {
+ if (Status & SDC_STATUS_RXFIFOHALFFULL) {
+ if (*rxCnt % 64) {
+ mci_ReadFIFO((uint32_t *) &rxBuf[*rxCnt], false);
+ }
+ else {
+ mci_ReadFIFO((uint32_t *) &rxBuf[*rxCnt], true);
+ }
+ *rxCnt += 32;
+ }
+ }
+
+ LPC_MCI->CLEAR = SDC_STATUS_FIFO;
+
+ return 1;
+}
+
+void MCIFileSystem::mci_ReadFIFO(uint32_t *pDst, bool bFirstHalf) const
+{
+ uint8_t start = 0, end = 7;
+
+ if (!bFirstHalf) {
+ start += 8;
+ end += 8;
+ }
+ for (; start <= end; start++) {
+ *pDst = LPC_MCI->FIFO[start];
+ pDst++;
+ }
+}
+
+void MCIFileSystem::mci_WriteFIFO(uint32_t *pSrc, bool bFirstHalf) const
+{
+ uint8_t start = 0, end = 7;
+ if (!bFirstHalf) {
+ start += 8;
+ end += 8;
+ }
+ for (; start <= end; start++) {
+ LPC_MCI->FIFO[start] = *pSrc;
+ pSrc++;
+ }
+}
+
+void MCIFileSystem::mci_SetupEventWakeup(uint8_t dmaChannel)
+{
+ /* Wait for IRQ - for an RTOS, you would pend on an event here with a IRQ based wakeup. */
+ NVIC_ClearPendingIRQ(DMA_IRQn);
+
+ _eventDmaChannel = dmaChannel;
+ _eventReceived = false;
+ _eventSuccess = false;
+
+ NVIC_EnableIRQ(DMA_IRQn);
+}
+
+uint32_t MCIFileSystem::mci_WaitForEvent() const
+{
+ /* Wait for the event (DMA or MCI interrupt) for a maximum of 2 seconds */
+ uint32_t end = us_ticker_read() + 2*1000*1000;
+ while ((us_ticker_read() < end) && (!_eventReceived))
+ {
+ // If the driver is having problems reading the card, adding a delay here
+ // might help.
+ //wait(0.01);
+ }
+
+ if (_eventReceived && _eventSuccess) {
+ return 0;
+ }
+
+ return 1;
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::_readBlocks(uint32_t card_type, uint32_t startBlock, uint32_t blockNum) const
+{
+ ReturnCode Ret = SDC_RET_FAILED;
+ response_t Response;
+ uint32_t Command, Argument;
+ uint8_t RetryCnt = 0x20;
+
+ if (blockNum == 1) {
+ Command = SD_CMD17_READ_SINGLE_BLOCK;
+ }
+ else {
+ Command = SD_CMD18_READ_MULTIPLE_BLOCK;
+ }
+
+ /* Select single or multiple read based on number of blocks */
+ /* if high capacity card use block indexing */
+ if (card_type & CARD_TYPE_HC) {
+ Argument = startBlock;
+ }
+ else { /*fix at 512 bytes*/
+ Argument = startBlock << 9;
+ }
+
+ while (RetryCnt > 0) {
+ Ret = mci_ExecuteCmd(Command, Argument, &Response);
+ if (Ret == SDC_RET_OK) {
+ if (mci_CheckR1Response(Response.Data[0], &Ret)) {
+ return Ret;
+ }
+ }
+ RetryCnt--;
+ }
+ return Ret;
+}
+
+MCIFileSystem::ReturnCode MCIFileSystem::_writeBlocks(uint32_t card_type, uint32_t startBlock, uint32_t blockNum) const
+{
+ ReturnCode Ret = SDC_RET_FAILED;
+ response_t Response;
+ uint32_t Command, Argument;
+ uint8_t RetryCnt = 0x20;
+
+ if (blockNum == 1) {
+ Command = SD_CMD24_WRITE_BLOCK;
+ }
+ else {
+ Command = SD_CMD25_WRITE_MULTIPLE_BLOCK;
+ }
+
+ /* if high capacity card use block indexing */
+ if (card_type & CARD_TYPE_HC) {
+ Argument = startBlock;
+ }
+ else { /*fix at 512 bytes*/
+ Argument = startBlock << 9;
+
+ }
+
+ while (RetryCnt > 0) {
+ Ret = mci_ExecuteCmd(Command, Argument, &Response);
+ if (Ret == SDC_RET_OK) {
+ if (mci_CheckR1Response(Response.Data[0], &Ret)) {
+ return Ret;
+ }
+ }
+ RetryCnt--;
+ }
+ return Ret;
+}
+
