aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal
diff options
context:
space:
mode:
authorareviu <areviu.info@gmail.com>2018-01-11 21:41:51 +0000
committerareviu <areviu.info@gmail.com>2018-01-11 21:41:51 +0000
commitbae22ff5bf8185b7ed2b6d26fb0d8f2c42253cfb (patch)
treeb0a58599435c67e3fe3c40929d316a5ce79185ab /os/hal
parentc0cea335bc590cd86fb385f587e61449e6071c9e (diff)
downloadChibiOS-bae22ff5bf8185b7ed2b6d26fb0d8f2c42253cfb.tar.gz
ChibiOS-bae22ff5bf8185b7ed2b6d26fb0d8f2c42253cfb.tar.bz2
ChibiOS-bae22ff5bf8185b7ed2b6d26fb0d8f2c42253cfb.zip
update SDMMC driver and added test hal project
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11264 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal')
-rw-r--r--os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c22
-rw-r--r--os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.h3
-rw-r--r--os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c229
-rw-r--r--os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.h68
-rw-r--r--os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c102
-rw-r--r--os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.h9
-rw-r--r--os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_ff.c307
-rw-r--r--os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c8
-rw-r--r--os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_pmc.c3
-rw-r--r--os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sama5d2.h2
-rw-r--r--os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c408
-rw-r--r--os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.h13
-rw-r--r--os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_tc.c3
-rw-r--r--os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_trace.h75
-rw-r--r--os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk5
-rw-r--r--os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_conf.h7
-rw-r--r--os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c80
-rw-r--r--os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.h12
-rw-r--r--os/hal/ports/SAMA/SAMA5D2x/platform.mk1
19 files changed, 1202 insertions, 155 deletions
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c
index 04f2a619e..c47c520af 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c
@@ -95,7 +95,8 @@ void SdMmcUpdateInformation(SdmmcDriver *drv, bool csd, bool extData)
uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry)
{
uint64_t mem_size;
- uint32_t freq, drv_err, status;
+ //uint32_t freq;
+ uint32_t drv_err, status;
uint8_t error;
bool flag;
sSdCard *pSd = &drv->card;
@@ -153,7 +154,7 @@ uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry)
if (error)
return error;
else {
- TRACE_1("RCA=%u\n\r",drv->card.wAddress );
+ TRACE_DEBUG_1("RCA=%u\n\r",drv->card.wAddress );
}
/* SEND_CSD (CMD9) to obtain the Card Specific Data (CSD register),
@@ -250,12 +251,14 @@ uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry)
}
else {
drv->card.wBlockSize = 512;
- mem_size = SD_CSD_TOTAL_SIZE(pSd);
+ mem_size = SD_CSD_TOTAL_SIZE(pSd->CSD);
drv->card.dwNbBlocks = (uint32_t)(mem_size >> 9);
drv->card.dwTotalSize = mem_size >> 32 ? 0xFFFFFFFF
: (uint32_t)mem_size;
}
+//TO BE DONE
+#if 0
/* Automatically select the max device clock frequency */
/* Calculate transfer speed */
freq = SdmmcGetMaxFreq(drv);
@@ -266,10 +269,10 @@ uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry)
error = HwSetClock(drv, &freq);
drv->card.dwCurrSpeed = freq;
if (error != SDMMC_OK && error != SDMMC_CHANGED) {
- TRACE_1("clk %s\n\r", SD_StringifyRetCode(error));
+ TRACE_ERROR_1("clk %s\n\r", SD_StringifyRetCode(error));
return error;
}
-
+#endif
/* Check device status and eat past exceptions, which would otherwise
* prevent upcoming data transaction routines from reliably checking
* fresh exceptions. */
@@ -277,8 +280,11 @@ uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry)
if (error)
return error;
status = status & ~STATUS_STATE & ~STATUS_READY_FOR_DATA & ~STATUS_APP_CMD;
- //if (status)
- // trace_warning("st %lx\n\r", status);
+
+ //warning
+ if (status) {
+ TRACE_WARNING_1("st %lx\n\r", status);
+ }
return SDMMC_OK;
}
@@ -457,7 +463,7 @@ uint8_t SdMmcSelect(SdmmcDriver *drv, uint16_t address, uint8_t statCheck)
if (currState == targetState)
return 0;
if (currState != srcState) {
- TRACE_1("st %lx\n\r", currState);
+ TRACE_ERROR_1("st %lx\n\r", currState);
return SDMMC_ERR;
}
break;
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.h b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.h
index 8b03a8bb8..f675996e4 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.h
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.h
@@ -171,8 +171,7 @@ extern const uint16_t sdmmcTransUnits[8];
extern const uint8_t sdTransMultipliers[16];
extern const uint8_t mmcTransMultipliers[16];
extern void SdParamReset(sSdCard * pSd);
-extern uint32_t SdmmcDecodeTransSpeed(uint32_t code,
- const uint16_t * unitCodes, const uint8_t * multiCodes);
+extern uint32_t SdmmcDecodeTransSpeed(uint32_t code,const uint16_t * unitCodes, const uint8_t * multiCodes);
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c
index 246a9f1ab..2a9b8a529 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c
@@ -186,7 +186,7 @@ uint8_t Cmd1(SdmmcDriver *drv, bool * hc)
ocr & SD_OCR_VDD_34_35 ? 'X' : '.',
ocr & SD_OCR_VDD_35_36 ? 'X' : '.');
#endif
- TRACE_1("Device access 0x%lx\n\r", ocr >> 29 & 0x3ul);
+ TRACE_INFO_1("Device access 0x%lx\n\r", ocr >> 29 & 0x3ul);
*hc = (ocr & MMC_OCR_ACCESS_MODE) == MMC_OCR_ACCESS_SECTOR? true : false;
@@ -415,6 +415,30 @@ uint8_t Cmd11(SdmmcDriver *drv, uint32_t * pStatus)
}
/**
+ * Forces the card to stop transmission
+ * \param pSd Pointer to a SD card driver instance.
+ * \param pStatus Pointer to a status variable.
+ */
+uint8_t Cmd12(SdmmcDriver *drv, uint32_t * pStatus)
+{
+ sSdmmcCommand *pCmd = &drv->cmd;
+ uint8_t bRc;
+
+ _ResetCmd(pCmd);
+
+ /* Fill command */
+ pCmd->bCmd = 12;
+ pCmd->cmdOp.wVal = SDMMC_CMD_CSTOP | SDMMC_CMD_bmBUSY;
+ pCmd->pResp = pStatus;
+
+ drv->timeout_elapsed = -1;
+ /* Send command */
+ bRc = sdmmcSendCmd(drv);
+ return bRc;
+}
+
+
+/**
* Addressed card sends its status register.
* Returns the command transfer result (see SendMciCommand).
* \param drv Pointer to \ref SdmmcDriver instance.
@@ -466,6 +490,47 @@ uint8_t Cmd14(SdmmcDriver *drv, uint8_t * pData, uint8_t len, uint32_t * pStatus
bRc = sdmmcSendCmd(drv);
return bRc;
}
+
+/**
+ * Continously transfers datablocks from card to host until interrupted by a
+ * STOP_TRANSMISSION command.
+ * \param pSd Pointer to a SD card driver instance.
+ * \param nbBlocks Number of blocks to send.
+ * \param pData Pointer to the buffer to be filled.
+ * The buffer shall follow the peripheral and DMA alignment requirements.
+ * \param address Data Address on SD/MMC card.
+ * \param pStatus Pointer to the response status.
+ * \param fCallback Pointer to optional callback invoked on command end.
+ * NULL: Function return until command finished.
+ * Pointer: Return immediately and invoke callback at end.
+ * Callback argument is fixed to a pointer to sSdCard instance.
+ */
+uint8_t Cmd18(SdmmcDriver *drv,
+ uint16_t * nbBlock,
+ uint8_t * pData,
+ uint32_t address, uint32_t * pStatus)
+{
+ sSdmmcCommand *pCmd = &drv->cmd;
+ uint8_t bRc;
+
+ _ResetCmd(pCmd);
+
+ /* Fill command */
+ pCmd->cmdOp.wVal = SDMMC_CMD_CDATARX(1);
+ pCmd->bCmd = 18;
+ pCmd->dwArg = address;
+ pCmd->pResp = pStatus;
+ pCmd->wBlockSize = drv->card.wCurrBlockLen;
+ pCmd->wNbBlocks = *nbBlock;
+ pCmd->pData = pData;
+ drv->timeout_elapsed = -1;
+ /* Send command */
+ bRc = sdmmcSendCmd(drv);
+ if (bRc == SDMMC_CHANGED)
+ *nbBlock = pCmd->wNbBlocks;
+ return bRc;
+}
+
/**
* A host sends the bus test data pattern to a card.
* \param drv Pointer to \ref SdmmcDriver instance.
@@ -513,6 +578,152 @@ uint8_t Cmd16(SdmmcDriver *drv, uint16_t blkLen)
return bRc;
}
+
+/**
+ * Read single block command
+ * \param pSd Pointer to a SD card driver instance.
+ * \param pData Pointer to the buffer to be filled.
+ * The buffer shall follow the peripheral and DMA alignment requirements.
+ * \param address Data Address on SD/MMC card.
+ * \param pStatus Pointer response buffer as status return.
+ * \param fCallback Pointer to optional callback invoked on command end.
+ * NULL: Function return until command finished.
+ * Pointer: Return immediately and invoke callback at end.
+ * Callback argument is fixed to a pointer to sSdCard instance.
+ */
+uint8_t Cmd17(SdmmcDriver *drv,
+ uint8_t * pData,
+ uint32_t address, uint32_t * pStatus)
+{
+ sSdmmcCommand *pCmd = &drv->cmd;
+ uint8_t bRc;
+
+ _ResetCmd(pCmd);
+
+ /* Fill command */
+ pCmd->cmdOp.wVal = SDMMC_CMD_CDATARX(1);
+ pCmd->bCmd = 17;
+ pCmd->dwArg = address;
+ pCmd->pResp = pStatus;
+ pCmd->wBlockSize =drv->card.wCurrBlockLen;
+ pCmd->wNbBlocks = 1;
+ pCmd->pData = pData;
+
+
+ drv->timeout_elapsed = -1;
+ /* Send command */
+ bRc = sdmmcSendCmd(drv);
+ return bRc;
+}
+
+
+/**
+ * Defines the number of blocks (read/write) and the reliable writer parameter
+ * (write) for a block read or write command
+ * data (CSD) on the CMD line.
+ * Returns the command transfer result (see SendMciCommand).
+ * \param pSd Pointer to a SD card driver instance.
+ * \param write Write Request parameter.
+ * \param blocks number of blocks.
+ */
+uint8_t Cmd23(SdmmcDriver *drv, uint8_t write, uint32_t blocks, uint32_t * pStatus)
+{
+ sSdmmcCommand *pCmd = &drv->cmd;
+ uint8_t bRc;
+
+ _ResetCmd(pCmd);
+
+ /* Fill command */
+ pCmd->cmdOp.wVal = SDMMC_CMD_CNODATA(1);
+ pCmd->bCmd = 23;
+ pCmd->wNbBlocks = 0;
+ pCmd->dwArg = write << 31 | blocks;
+ pCmd->pResp = pStatus;
+
+ drv->timeout_elapsed = -1;
+ /* Send command */
+ bRc = sdmmcSendCmd(drv);
+ return bRc;
+}
+
+/**
+ * Write single block command
+ * \param pSd Pointer to a SD card driver instance.
+ * \param blockSize Block size (shall be set to 512 in case of high capacity).
+ * \param pData Pointer to the buffer to be filled.
+ * The buffer shall follow the peripheral and DMA alignment requirements.
+ * \param address Data Address on SD/MMC card.
+ * \param pStatus Pointer to response buffer as status.
+ * \param fCallback Pointer to optional callback invoked on command end.
+ * NULL: Function return until command finished.
+ * Pointer: Return immediately and invoke callback at end.
+ * Callback argument is fixed to a pointer to sSdCard instance.
+ */
+uint8_t Cmd24(SdmmcDriver *drv,
+ uint8_t * pData,
+ uint32_t address, uint32_t * pStatus)
+{
+ sSdmmcCommand *pCmd = &drv->cmd;
+ uint8_t bRc;
+
+ _ResetCmd(pCmd);
+
+ /* Fill command */
+ pCmd->cmdOp.wVal = SDMMC_CMD_CDATATX(1);
+ pCmd->bCmd = 24;
+ pCmd->dwArg = address;
+ pCmd->pResp = pStatus;
+ pCmd->wBlockSize =drv->card.wCurrBlockLen;
+ pCmd->wNbBlocks = 1;
+ pCmd->pData = pData;
+ drv->timeout_elapsed = -1;
+ /* Send command */
+ bRc = sdmmcSendCmd(drv);
+ return bRc;
+}
+
+/**
+ * Write multiple block command
+ * \param pSd Pointer to a SD card driver instance.
+ * \param blockSize Block size (shall be set to 512 in case of high capacity).
+ * \param nbBlock Number of blocks to send.
+ * \param pData Pointer to the buffer to be filled.
+ * The buffer shall follow the peripheral and DMA alignment requirements.
+ * \param address Data Address on SD/MMC card.
+ * \param pStatus Pointer to the response buffer as status.
+ * \param fCallback Pointer to optional callback invoked on command end.
+ * NULL: Function return until command finished.
+ * Pointer: Return immediately and invoke callback at end.
+ * Callback argument is fixed to a pointer to sSdCard instance.
+ */
+uint8_t Cmd25(SdmmcDriver *drv,
+ uint16_t * nbBlock,
+ uint8_t * pData,
+ uint32_t address, uint32_t * pStatus)
+{
+ sSdmmcCommand *pCmd = &drv->cmd;
+ uint8_t bRc;
+
+ _ResetCmd(pCmd);
+
+ /* Fill command */
+ pCmd->cmdOp.wVal = SDMMC_CMD_CDATATX(1);
+ pCmd->bCmd = 25;
+ pCmd->dwArg = address;
+ pCmd->pResp = pStatus;
+ pCmd->wBlockSize =drv->card.wCurrBlockLen;
+ pCmd->wNbBlocks = *nbBlock;
+ pCmd->pData = pData;
+
+ drv->timeout_elapsed = -1;
+ /* Send command */
+ bRc = sdmmcSendCmd(drv);
+ if (bRc == SDMMC_CHANGED)
+ *nbBlock = pCmd->wNbBlocks;
+ return bRc;
+}
+
+
/**
* SDIO IO_RW_DIRECT command, response R5.
* \return the command transfer result (see SendMciCommand).
@@ -588,7 +799,7 @@ uint8_t Acmd6(SdmmcDriver *drv, uint8_t busWidth)
sSdmmcCommand *pCmd = &drv->cmd;
uint8_t error;
- TRACE_1("Acmd%u\n\r", 6);
+ TRACE_INFO_1("Acmd%u\n\r", 6);
error = Cmd55(drv, drv->card.wAddress);
@@ -603,7 +814,7 @@ uint8_t Acmd6(SdmmcDriver *drv, uint8_t busWidth)
}
else {
if (error) {
- TRACE_2("Acmd%u %s\n\r", 6, SD_StringifyRetCode(error));
+ TRACE_ERROR_2("Acmd%u %s\n\r", 6, SD_StringifyRetCode(error));
}
}
return error;
@@ -626,7 +837,7 @@ uint8_t Acmd13(SdmmcDriver *drv, uint8_t * pSSR, uint32_t * pResp)
//assert(pSd);
- TRACE_1("Acmd%u\n\r", 13);
+ TRACE_INFO_1("Acmd%u\n\r", 13);
error = Cmd55(drv, drv->card.wAddress);
@@ -647,7 +858,7 @@ uint8_t Acmd13(SdmmcDriver *drv, uint8_t * pSSR, uint32_t * pResp)
} else {
if (error) {
- TRACE_2("Acmd%u %s\n\r", 13, SD_StringifyRetCode(error));
+ TRACE_ERROR_2("Acmd%u %s\n\r", 13, SD_StringifyRetCode(error));
}
}
return error;
@@ -713,7 +924,7 @@ uint8_t Acmd41(SdmmcDriver *drv, bool * low_sig_lvl, bool * hc)
/* Supply voltage range is incompatible */
rc = SDMMC_BUSY;
if (rc != SDMMC_OK) {
- TRACE_2("Acmd%u %s\n\r", 41, SD_StringifyRetCode(rc));
+ TRACE_ERROR_2("Acmd%u %s\n\r", 41, SD_StringifyRetCode(rc));
}
else {
#if 0
@@ -761,7 +972,7 @@ uint8_t Acmd51(SdmmcDriver *drv, uint8_t * pSCR, uint32_t * pResp)
uint8_t error;
- TRACE_1("Acmd%u\n\r", 51);
+ TRACE_INFO_1("Acmd%u\n\r", 51);
error = Cmd55(drv, drv->card.wAddress);
@@ -783,7 +994,7 @@ uint8_t Acmd51(SdmmcDriver *drv, uint8_t * pSCR, uint32_t * pResp)
} else {
if (error) {
- TRACE_2("Acmd%u %s\n\r", 51, SD_StringifyRetCode(error));
+ TRACE_ERROR_2("Acmd%u %s\n\r", 51, SD_StringifyRetCode(error));
}
}
return error;
@@ -833,7 +1044,7 @@ uint8_t MmcCmd6(SdmmcDriver *drv, const void *pSwitchArg, uint32_t * pResp)
bRc = sdmmcSendCmd(drv);
if (!bRc && pResp && *pResp & STATUS_MMC_SWITCH) {
- TRACE_1("st %lx\n\r", *pResp);
+ TRACE_INFO_1("st %lx\n\r", *pResp);
}
return bRc;
}
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.h b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.h
index 014986e22..6de912fe8 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.h
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.h
@@ -103,6 +103,60 @@ typedef struct _SdioCmd52Arg {
#define STATUS_ADDRESS_MISALIGN (1UL << 30)
#define STATUS_ADDR_OUT_OR_RANGE (1UL << 31)
+#define STATUS_STOP ((uint32_t)( STATUS_CARD_IS_LOCKED \
+ | STATUS_COM_CRC_ERROR \
+ | STATUS_ILLEGAL_COMMAND \
+ | STATUS_CC_ERROR \
+ | STATUS_ERROR \
+ | STATUS_STATE \
+ | STATUS_READY_FOR_DATA ))
+
+#define STATUS_WRITE ((uint32_t)( STATUS_ADDR_OUT_OR_RANGE \
+ | STATUS_ADDRESS_MISALIGN \
+ | STATUS_BLOCK_LEN_ERROR \
+ | STATUS_WP_VIOLATION \
+ | STATUS_CARD_IS_LOCKED \
+ | STATUS_COM_CRC_ERROR \
+ | STATUS_ILLEGAL_COMMAND \
+ | STATUS_CC_ERROR \
+ | STATUS_ERROR \
+ | STATUS_ERASE_RESET \
+ | STATUS_STATE \
+ | STATUS_READY_FOR_DATA ))
+
+#define STATUS_READ ((uint32_t)( STATUS_ADDR_OUT_OR_RANGE \
+ | STATUS_ADDRESS_MISALIGN \
+ | STATUS_BLOCK_LEN_ERROR \
+ | STATUS_CARD_IS_LOCKED \
+ | STATUS_COM_CRC_ERROR \
+ | STATUS_ILLEGAL_COMMAND \
+ | STATUS_CARD_ECC_FAILED \
+ | STATUS_CC_ERROR \
+ | STATUS_ERROR \
+ | STATUS_ERASE_RESET \
+ | STATUS_STATE \
+ | STATUS_READY_FOR_DATA ))
+
+#define STATUS_SD_SWITCH ((uint32_t)( STATUS_ADDR_OUT_OR_RANGE \
+ | STATUS_CARD_IS_LOCKED \
+ | STATUS_COM_CRC_ERROR \
+ | STATUS_ILLEGAL_COMMAND \
+ | STATUS_CARD_ECC_FAILED \
+ | STATUS_CC_ERROR \
+ | STATUS_ERROR \
+ | STATUS_UNERRUN \
+ | STATUS_OVERRUN \
+ /*| STATUS_STATE*/))
+
+#define STATUS_MMC_SWITCH ((uint32_t)( STATUS_CARD_IS_LOCKED \
+ | STATUS_COM_CRC_ERROR \
+ | STATUS_ILLEGAL_COMMAND \
+ | STATUS_CC_ERROR \
+ | STATUS_ERROR \
+ | STATUS_ERASE_RESET \
+ /*| STATUS_STATE*/ \
+ /*| STATUS_READY_FOR_DATA*/ \
+ | STATUS_SWITCH_ERROR ))
#define SD_OCR_S18A (1ul << 24) /**< Switching to 1.8V signaling level Accepted */
#define SDIO_OCR_MP (0x1ul << 27) /**< SDIO: Memory present */
@@ -190,12 +244,24 @@ extern uint8_t Cmd5(SdmmcDriver *drv, uint32_t * pIo);
extern uint8_t Cmd7(SdmmcDriver *drv, uint16_t address);
extern uint8_t Cmd9(SdmmcDriver *drv);
extern uint8_t Cmd11(SdmmcDriver *drv, uint32_t * pStatus);
+extern uint8_t Cmd12(SdmmcDriver *drv, uint32_t * pStatus);
extern uint8_t Cmd13(SdmmcDriver *drv, uint32_t * pStatus);
extern uint8_t Cmd14(SdmmcDriver *drv, uint8_t * pData, uint8_t len, uint32_t * pStatus);
extern uint8_t Cmd16(SdmmcDriver *drv, uint16_t blkLen);
+extern uint8_t Cmd17(SdmmcDriver *drv,
+ uint8_t * pData,
+ uint32_t address, uint32_t * pStatus);
+extern uint8_t Cmd18(SdmmcDriver *drv,uint16_t * nbBlock,uint8_t * pData,uint32_t address, uint32_t * pStatus);
extern uint8_t Cmd19(SdmmcDriver *drv, uint8_t * pData, uint8_t len, uint32_t * pStatus);
-
+extern uint8_t Cmd23(SdmmcDriver *drv, uint8_t write, uint32_t blocks, uint32_t * pStatus);
+extern uint8_t Cmd24(SdmmcDriver *drv,
+ uint8_t * pData,
+ uint32_t address, uint32_t * pStatus);
+extern uint8_t Cmd25(SdmmcDriver *drv,
+ uint16_t * nbBlock,
+ uint8_t * pData,
+ uint32_t address, uint32_t * pStatus);
extern uint8_t Cmd52(SdmmcDriver *drv,uint8_t wrFlag,uint8_t funcNb, uint8_t rdAfterWr, uint32_t addr, uint32_t * pIoData);
extern uint8_t Cmd55(SdmmcDriver *drv, uint16_t cardAddr);
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c
index ca28cc051..8c05bf133 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c
@@ -66,13 +66,13 @@ uint8_t sdmmc_device_lowlevelcfg(SdmmcDriver *driver)
pmc_set_main_oscillator_freq(BOARD_MAIN_CLOCK_EXT_OSC);
- TRACE_1("Processor clock: %u MHz\r\n", ((unsigned)(pmc_get_processor_clock() / 1000000) ));
- TRACE_1("Master clock: %u MHz\r\n", ((unsigned)(pmc_get_master_clock() / 1000000)) );
-
+ TRACE_INFO_1("Processor clock: %u MHz\r\n", ((unsigned)(pmc_get_processor_clock() / 1000000) ));
+ TRACE_INFO_1("Master clock: %u MHz\r\n", ((unsigned)(pmc_get_master_clock() / 1000000)) );
+#if SDMMC_USE_TC == 1
driver->tctimer_id = get_tc_id_from_addr(driver->config->tctimer,driver->config->tc_chan);
pmc_configure_peripheral(driver->tctimer_id, NULL, true);
-
+#endif
if (driver->config->slot_id == SDMMC_SLOT0) {
@@ -180,18 +180,17 @@ uint8_t sdmmc_device_lowlevelcfg(SdmmcDriver *driver)
if (res) {
//check res
res = IS_CACHE_ALIGNED(driver->config->data_buf);
- TRACE_2("check data buf %d %08x\r\n", res, driver->config->data_buf);
+ TRACE_DEBUG_2("check data buf %d %08x\r\n", res, driver->config->data_buf);
res &= IS_CACHE_ALIGNED(driver->config->data_buf_size);
- TRACE_2("check data_buf_size %d %08x\r\n", res,
+ TRACE_DEBUG_2("check data_buf_size %d %08x\r\n", res,
driver->config->data_buf_size);
res &= IS_CACHE_ALIGNED(driver->card.EXT);
- TRACE_2("check libExt %d %08x\r\n", res, driver->card.EXT);
+ TRACE_DEBUG_2("check libExt %d %08x\r\n", res, driver->card.EXT);
//res &= IS_CACHE_ALIGNED(sizeof(driver->card.EXT));
//TRACE_2("check size libExt %d %08x\r\n",rc,sizeof(driver->card.EXT));
if (!res) {
- TRACE(
- "WARNING: buffers are not aligned on data cache lines. Please fix this before enabling DMA.\n\r");
+ TRACE_WARNING("WARNING: buffers are not aligned on data cache lines. Please fix this before enabling DMA.\n\r");
driver->use_polling = true;
} else {
driver->use_polling = false;
@@ -217,13 +216,11 @@ bool sdmmc_device_initialize(SdmmcDriver *driver)
driver->blk_size = (val <= 0x2 ? (512 << val) : 512);
//Configure the TC Timer
-
+#if SDMMC_USE_TC == 1
pmc_configure_peripheral(driver->tctimer_id, NULL, true);
-
tc_configure(driver->config->tctimer, driver->config->tc_chan, TC_CMR_WAVE | TC_CMR_WAVSEL_UP | TC_CMR_CPCDIS | TC_CMR_BURST_NONE | TC_CMR_TCCLKS_TIMER_CLOCK2);
-
driver->config->tctimer->TC_CHANNEL[driver->config->tc_chan].TC_EMR |= TC_EMR_NODIVCLK;
-
+#endif
/* Perform the initial I/O calibration sequence, manually.
* Allow tSTARTUP = 2 usec for the analog circuitry to start up.
* CNTVAL = fHCLOCK / (4 * (1 / tSTARTUP)) */
@@ -257,7 +254,7 @@ bool sdmmc_device_initialize(SdmmcDriver *driver)
driver->regs->SDMMC_TCR = (driver->regs->SDMMC_TCR & ~SDMMC_TCR_DTCVAL_Msk) | SDMMC_TCR_DTCVAL(exp);
- TRACE_1("Set DAT line timeout to %lu ms\n\r", (10UL << (exp + 13UL))/ (base_freq / 100UL));
+ TRACE_DEBUG_1("Set DAT line timeout to %lu ms\n\r", (10UL << (exp + 13UL))/ (base_freq / 100UL));
/* Reset the peripheral. This will reset almost all registers.
* It doesn't affect I/O calibration however. */
@@ -334,7 +331,7 @@ uint8_t sdmmc_device_identify(SdmmcDriver *drv)
if (drv->state != MCID_IDLE )
return SDMMC_STATE;
- do {
+ Retry:
/* After power-on or CMD0, all cards?
* CMD lines are in input mode, waiting for start bit of the next command.
* The cards are initialized with a default relative card address
@@ -343,7 +340,7 @@ uint8_t sdmmc_device_identify(SdmmcDriver *drv)
error = SdMmcIdentify(drv);
if (error) {
- TRACE_1("Identify %s\n\r", SD_StringifyRetCode(error));
+ TRACE_ERROR_1("Identify %s\n\r", SD_StringifyRetCode(error));
return error;
}
@@ -366,12 +363,10 @@ uint8_t sdmmc_device_identify(SdmmcDriver *drv)
if (!error) {
drv->card.bSpeedMode = SDMMC_TIM_SD_SDR12;
- //goto Retry;
+ goto Retry;
}
}
}
-
-
#ifndef SDMMC_TRIM_SDIO
else if (drv->card.bCardType & CARD_TYPE_bmSDIO)
error = SdioInit(drv);
@@ -381,15 +376,14 @@ uint8_t sdmmc_device_identify(SdmmcDriver *drv)
error = MmcInit(drv);
#endif
else {
- TRACE_1("Identify %s\n\r", "failed");
+ TRACE_ERROR_1("Identify %s\n\r", "failed");
return SDMMC_NOT_INITIALIZED;
}
if (error) {
- TRACE_1("Init %s\n\r", SD_StringifyRetCode(error));
+ TRACE_ERROR_1("Init %s\n\r", SD_StringifyRetCode(error));
return error;
}
- } while (retry==1);
drv->card.bStatus = SDMMC_OK;
@@ -428,21 +422,32 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
Fetch:
/* Fetch normal events */
events = regs->SDMMC_NISTR;
+#if SDMMC_USE_TC == 1
if (driver->use_polling) {
- if (driver->expect_auto_end
-
+ if (
+ driver->expect_auto_end
&& !(driver->config->tctimer->TC_CHANNEL[driver->config->tc_chan].TC_SR & TC_SR_CLKSTA)
-
)
events |= SDMMC_NISTR_CUSTOM_EVT;
+
+
} else {
if (driver->expect_auto_end) {
while (driver->config->tctimer->TC_CHANNEL[driver->config->tc_chan].TC_SR & TC_SR_CLKSTA);
-
events |= SDMMC_NISTR_CUSTOM_EVT;
}
}
+#else
+
+ if (driver->expect_auto_end)
+ {
+ while ( chSysIsCounterWithinX(chSysGetRealtimeCounterX(),driver->start_cycles ,driver->start_cycles+driver->timeout_cycles) );
+ events |= SDMMC_NISTR_CUSTOM_EVT;
+ }
+
+
+#endif
if (!events)
return;
//TRACE_1("events %08x\n\r",events);
@@ -661,9 +666,9 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
* Counter for this purpose. */
if (has_data && (cmd->bCmd == 18 || cmd->bCmd == 25)
&& !driver->use_set_blk_cnt) {
-
+#if SDMMC_USE_TC == 1
driver->config->tctimer->TC_CHANNEL[driver->config->tc_chan].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG;
-
+#endif
driver->expect_auto_end = true;
//#ifndef NDEBUG
// if (!set->cmd_line_released)
@@ -734,10 +739,12 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
&& cmd->dwArg & 1ul << 31 && !cmd->cmdOp.bmBits.checkBsy)) {
/* Currently in the function switching period, wait for the
* delay preconfigured in sdmmc_send_command(). */
-
+#if SDMMC_USE_TC == 1
driver->config->tctimer->TC_CHANNEL[driver->config->tc_chan].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG;
while (driver->config->tctimer->TC_CHANNEL[driver->config->tc_chan].TC_SR & TC_SR_CLKSTA) ;
-
+#else
+ while ( chSysIsCounterWithinX(chSysGetRealtimeCounterX(),driver->start_cycles ,driver->start_cycles+driver->timeout_cycles) );
+#endif
}
/* Release this command */
@@ -878,14 +885,16 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
uint32_t eister;
uint32_t mask;
uint32_t len;
+#if SDMMC_USE_TC == 1
uint32_t cycles;
+#endif
uint16_t cr;
uint16_t tmr;
uint8_t mc1r;
uint8_t rc = SDMMC_OK;
- //TRACE_1("[command] start %d\r\n",driver->cmd.bCmd);
+ TRACE_DEBUG_1("[command] start %d\r\n",driver->cmd.bCmd);
if (driver->state == MCID_OFF)
return SDMMC_STATE;
@@ -962,7 +971,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
driver->dat_lines_released = false;
driver->expect_auto_end = false;
driver->cmd.bStatus = rc;
- //TRACE_1("command set status %d\r\n",driver->cmd.bStatus);
+ TRACE_DEBUG_1("command set status %d\r\n",driver->cmd.bStatus);
tmr = (regs->SDMMC_TMR & ~SDMMC_TMR_MSBSEL & ~SDMMC_TMR_DTDSEL
& ~SDMMC_TMR_ACMDEN_Msk & ~SDMMC_TMR_BCEN & ~SDMMC_TMR_DMAEN)
@@ -1101,12 +1110,16 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
* bits, hence 48 device clock cycles.
* The sum of the above timings is the maximum time CMD12 will
* take to complete. */
-
+#if SDMMC_USE_TC == 1
cycles = pmc_get_peripheral_clock(driver->tctimer_id) / (driver->dev_freq / (2ul + 64ul + 48ul));
- //TRACE_1("[command] has_data wait %d cycles\r\n",cycles);
+ TRACE_DEBUG_1("[command] has_data wait %d cycles\r\n",cycles);
/* The Timer operates with RC >= 1 */
driver->config->tctimer->TC_CHANNEL[driver->config->tc_chan].TC_RC = max_u32(cycles, 1);
+#else
+ driver->timeout_cycles = 2+64+48;
+ driver->start_cycles = chSysGetRealtimeCounterX();
+#endif
}
/* With SD devices, the 8-cycle function switching period will apply,
@@ -1114,18 +1127,21 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
* Note that MMC devices don't require this fixed delay, but regarding
* GO_IDLE_STATE we have no mean to filter the MMC requests out. */
else if (wait_switch) {
-
+#if SDMMC_USE_TC == 1
cycles = pmc_get_peripheral_clock(driver->tctimer_id) / (driver->dev_freq / 8ul);
- //TRACE_1("[command] wait_switch %d cycles\r\n",cycles);
+ TRACE_DEBUG_1("[command] wait_switch %d cycles\r\n",cycles);
driver->config->tctimer->TC_CHANNEL[driver->config->tc_chan].TC_RC = max_u32(cycles, 1);
-
+#else
+ driver->timeout_ticks = 8;
+ driver->start_cycles = chSysGetRealtimeCounterX();
+#endif
}
if (!driver->use_polling) {
regs->SDMMC_NISIER |= SDMMC_NISIER_BRDRDY | SDMMC_NISIER_BWRRDY | SDMMC_NISIER_TRFC | SDMMC_NISIER_CMDC | SDMMC_NISIER_CINT;
regs->SDMMC_EISIER = eister;
}
- //TRACE_1("[command] finish %d OK\r\n",driver->cmd.bCmd);
+ TRACE_DEBUG_1("[command] finish %d OK\r\n",driver->cmd.bCmd);
return SDMMC_OK;
}
@@ -1150,7 +1166,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
//#if TRACE_LEVEL >= TRACE_LEVEL_DEBUG
if (bCtl != SDMMC_IOCTL_BUSY_CHECK && bCtl != SDMMC_IOCTL_GET_DEVICE) {
- TRACE_2("SDMMC_IOCTL_%s(%lu)\n\r", SD_StringifyIOCtrl(bCtl),driver->control_param );
+ TRACE_DEBUG_2("SDMMC_IOCTL_%s(%lu)\n\r", SD_StringifyIOCtrl(bCtl),driver->control_param );
}
//#endif
@@ -1217,7 +1233,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
if (driver->control_param > 0xff)
return SDMMC_PARAM;
rc = sdmmc_set_bus_width(driver, driver->control_param);
- TRACE_1("Using a %u-bit data bus\n\r", sdmmc_get_bus_width(driver));
+ TRACE_DEBUG_1("Using a %u-bit data bus\n\r", sdmmc_get_bus_width(driver));
break;
case SDMMC_IOCTL_GET_HSMODE:
@@ -1283,7 +1299,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
sdmmc_set_device_clock(driver, driver->control_param);
- TRACE_1("Clocking the device at %lu Hz\n\r", driver->dev_freq);
+ TRACE_DEBUG_1("Clocking the device at %lu Hz\n\r", driver->dev_freq);
if (driver->dev_freq > 95000000ul
&& (driver->tim_mode == SDMMC_TIM_MMC_HS200
|| driver->tim_mode == SDMMC_TIM_SD_SDR104
@@ -1345,7 +1361,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
//#if TRACE_LEVEL >= TRACE_LEVEL_ERROR
if (rc != SDMMC_OK && rc != SDMMC_CHANGED
&& bCtl != SDMMC_IOCTL_BUSY_CHECK) {
- TRACE_2("SDMMC_IOCTL_%s ended with %s\n\r",SD_StringifyIOCtrl(bCtl), SD_StringifyRetCode(rc));
+ TRACE_ERROR_2("SDMMC_IOCTL_%s ended with %s\n\r",SD_StringifyIOCtrl(bCtl), SD_StringifyRetCode(rc));
}
//#endif
return rc;
@@ -1988,7 +2004,7 @@ static uint8_t sdmmc_set_bus_width(SdmmcDriver *driver, uint8_t bits)
*pIoValClk = drv->control_param;
- TRACE_1("Device clk %lu kHz\n\r", drv->control_param / 1000UL);
+ TRACE_DEBUG_1("Device clk %lu kHz\n\r", drv->control_param / 1000UL);
}
return rc;
}
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.h b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.h
index ebe0da07d..340feb172 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.h
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.h
@@ -350,15 +350,6 @@ or not by mechanical write protect switch */
-#define STATUS_MMC_SWITCH ((uint32_t)( STATUS_CARD_IS_LOCKED \
- | STATUS_COM_CRC_ERROR \
- | STATUS_ILLEGAL_COMMAND \
- | STATUS_CC_ERROR \
- | STATUS_ERROR \
- | STATUS_ERASE_RESET \
- /*| STATUS_STATE*/ \
- /*| STATUS_READY_FOR_DATA*/ \
- | STATUS_SWITCH_ERROR ))
#define t_usleep(d,t) sdmmc_device_sleep(d,t,2)
#define t_msleep(d,t) sdmmc_device_sleep(d,t,1)
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_ff.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_ff.c
new file mode 100644
index 000000000..49b667bd7
--- /dev/null
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_ff.c
@@ -0,0 +1,307 @@
+/* ----------------------------------------------------------------------------
+ * SAM Software Package License
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2015, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+/* ----------------------------------------------------------------------------
+ * This file is based on the template source file named diskio.c,
+ * part of the FatFs Module R0.10b:
+ * Low level disk I/O module skeleton for FatFs (C)ChaN, 2014
+ * If a working storage control module is available, it should be
+ * attached to the FatFs via a glue function rather than modifying it.
+ * This is an example of glue functions to attach various existing
+ * storage control modules to the FatFs module with a defined API.
+ * ----------------------------------------------------------------------------
+ */
+
+#include "hal.h"
+#include "ccportab.h"
+#include "ffconf.h"
+#include "diskio.h"
+
+#include <string.h>
+#include "sama_sdmmc_lld.h"
+#include "ch_sdmmc_device.h"
+#include "ch_sdmmc_sd.h"
+#include "ch_sdmmc_sdio.h"
+#include "ch_sdmmc_trace.h"
+/*----------------------------------------------------------------------------
+ * Definitions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Access the SD/MMC Library instances owned by the application.
+ * Used upon calls from the FatFs Module.
+ *
+ * Shall be implemented by the application.
+ */
+extern bool CC_WEAK sdmmcGetInstance(uint8_t index, SdmmcDriver **sdmmcp) ;
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Initialize a Drive.
+ * \param slot Physical drive number (0..).
+ * \return Drive status flags; STA_NOINIT if the specified drive does not exist.
+ */
+DSTATUS disk_initialize(BYTE slot)
+{
+ SdmmcDriver *sdmmcp = NULL;
+ uint8_t rc;
+
+ if (!sdmmcGetInstance(slot, &sdmmcp))
+ return STA_NOINIT;
+
+
+ rc = SD_GetStatus(sdmmcp);
+
+ if (rc == SDMMC_NOT_SUPPORTED)
+ return STA_NODISK | STA_NOINIT;
+#if 0
+ if (sdmmcp->state != MCID_IDLE )
+ sdmmc_device_deInit(sdmmcp);
+
+ /* FIXME a delay with the bus held off may be required by the device */
+ rc = sdmmc_device_start(sdmmcp);
+
+ if (rc == SDMMC_OK) {
+ rc = sdmmc_device_identify(sdmmcp);
+ }
+#endif
+
+ return rc == SDMMC_OK ? 0 : STA_NOINIT;
+}
+
+/**
+ * \brief Get Drive Status.
+ * \param slot Physical drive number (0..).
+ * \return Drive status flags; STA_NODISK if there is currently no device in
+ * the specified slot.
+ */
+DSTATUS disk_status(BYTE slot)
+{
+ SdmmcDriver *sdmmcp = NULL;
+ uint8_t rc;
+
+ if (!sdmmcGetInstance(slot, &sdmmcp))
+ return STA_NODISK | STA_NOINIT;
+
+ rc = SD_GetStatus(sdmmcp);
+
+ if (rc == SDMMC_NOT_SUPPORTED)
+ return STA_NODISK | STA_NOINIT;
+ else if (rc != SDMMC_OK)
+ return STA_NOINIT;
+ /* Well, no restriction on this drive */
+ return 0;
+}
+
+/**
+ * \brief Read Sector(s).
+ * \param slot Physical drive number (0..).
+ * \param buff Data buffer to store read data.
+ * \param sector Sector address in LBA.
+ * \param count Number of sectors to read.
+ * \return Result code; RES_OK if successful.
+ */
+DRESULT disk_read(BYTE slot, BYTE* buff, DWORD sector, UINT count)
+{
+ SdmmcDriver *sdmmcp = NULL;
+ DRESULT res;
+ uint32_t blk_size, addr = sector, len = count;
+ uint8_t rc;
+
+ if (!sdmmcGetInstance(slot, &sdmmcp))
+ return RES_PARERR;
+
+ blk_size = sdmmcp->card.wBlockSize;
+
+ if (blk_size == 0)
+ return RES_NOTRDY;
+
+ if (blk_size < FF_MIN_SS) {
+ if (FF_MIN_SS % blk_size)
+ return RES_PARERR;
+ addr = sector * (FF_MIN_SS / blk_size);
+ len = count * (FF_MIN_SS / blk_size);
+ }
+
+ if (count <= 1)
+ rc = SD_ReadBlocks(sdmmcp, addr, buff, len);
+ else
+ rc = SD_Read(sdmmcp, addr, buff, len);
+
+ if (rc == SDMMC_OK || rc == SDMMC_CHANGED)
+ res = RES_OK;
+ else if (rc == SDMMC_ERR_IO || rc == SDMMC_ERR_RESP || rc == SDMMC_ERR)
+ res = RES_ERROR;
+ else if (rc == SDMMC_NO_RESPONSE || rc == SDMMC_BUSY
+ || rc == SDMMC_NOT_INITIALIZED || rc == SDMMC_LOCKED
+ || rc == SDMMC_STATE || rc == SDMMC_USER_CANCEL)
+ res = RES_NOTRDY;
+ else if (rc == SDMMC_PARAM || rc == SDMMC_NOT_SUPPORTED)
+ res = RES_PARERR;
+ else
+ res = RES_ERROR;
+
+ return res;
+}
+
+#if !FF_FS_READONLY
+/**
+ * \brief Write Sector(s).
+ *
+ * \param slot Physical drive number (0..).
+ * \param buff Data to be written.
+ * \param sector Sector address in LBA.
+ * \param count Number of sectors to write.
+ * \return Result code; RES_OK if successful.
+ *
+ * \note The FatFs module will issue multiple sector transfer request
+ * (count > 1) to the disk I/O layer. The disk function should process
+ * the multiple sector transfer properly. Do not translate it into
+ * multiple single sector transfers to the media, or the data read/write
+ * performance may be drastically decreased.
+ */
+DRESULT disk_write(BYTE slot, const BYTE* buff, DWORD sector, UINT count)
+{
+ SdmmcDriver *sdmmcp = NULL;
+ DRESULT res;
+ uint32_t blk_size, addr = sector, len = count;
+ uint8_t rc;
+
+ if (!sdmmcGetInstance(slot, &sdmmcp))
+ return RES_PARERR;
+
+ blk_size = sdmmcp->card.wBlockSize;
+
+ if (blk_size < FF_MIN_SS) {
+ if (FF_MIN_SS % blk_size)
+ return RES_PARERR;
+ addr = sector * (FF_MIN_SS / blk_size);
+ len = count * (FF_MIN_SS / blk_size);
+ }
+ if (count <= 1)
+ rc = SD_WriteBlocks(sdmmcp, addr, buff, len);
+ else
+ rc = SD_Write(sdmmcp, addr, buff, len);
+
+ if (rc == SDMMC_OK || rc == SDMMC_CHANGED)
+ res = RES_OK;
+ else if (rc == SDMMC_ERR_IO || rc == SDMMC_ERR_RESP || rc == SDMMC_ERR)
+ res = RES_ERROR;
+ else if (rc == SDMMC_NO_RESPONSE || rc == SDMMC_BUSY
+ || rc == SDMMC_NOT_INITIALIZED || rc == SDMMC_LOCKED
+ || rc == SDMMC_STATE || rc == SDMMC_USER_CANCEL)
+ res = RES_NOTRDY;
+ else if (rc == SDMMC_PARAM || rc == SDMMC_NOT_SUPPORTED)
+ res = RES_PARERR;
+ else
+ res = RES_ERROR;
+ return res;
+}
+#endif /* _FS_READONLY */
+
+/**
+ * \brief Miscellaneous Functions.
+ * \param slot Physical drive number (0..).
+ * \param cmd Control code.
+ * \param buff Buffer to send/receive control data.
+ * \return Result code; RES_OK if successful.
+ */
+DRESULT disk_ioctl(BYTE slot, BYTE cmd, void* buff)
+{
+ SdmmcDriver *sdmmcp = NULL;
+ DRESULT res;
+ DWORD *param_u32 = (DWORD *)buff;
+ WORD *param_u16 = (WORD *)buff;
+ uint32_t blk_size, blk_count;
+
+ if (!sdmmcGetInstance(slot, &sdmmcp))
+ return RES_PARERR;
+
+ switch (cmd)
+ {
+ case CTRL_SYNC:
+ /* SD/MMC devices do not seem to cache data beyond completion
+ * of the write commands. Note that if _FS_READONLY is enabled,
+ * this command is not needed. */
+ res = RES_OK;
+ break;
+
+ case GET_SECTOR_COUNT:
+ if (!buff)
+ return RES_PARERR;
+ blk_size = sdmmcp->card.wBlockSize;
+ blk_count = sdmmcp->card.dwNbBlocks;
+
+ if (blk_size < FF_MIN_SS)
+ {
+ if (FF_MIN_SS % blk_size)
+ return RES_PARERR;
+ *param_u32 = blk_count / (FF_MIN_SS / blk_size);
+ }
+ else
+ *param_u32 = blk_count;
+ res = RES_OK;
+ break;
+
+ case GET_SECTOR_SIZE:
+ /* Note that if _MAX_SS equals _MIN_SS i.e. the drive does not
+ * have to support several sector sizes, this command is not
+ * needed. */
+ if (!buff)
+ return RES_PARERR;
+ blk_size = sdmmcp->card.wBlockSize;
+ *param_u16 = blk_size >= FF_MIN_SS ? blk_size : FF_MIN_SS;
+ res = RES_OK;
+ break;
+
+ case GET_BLOCK_SIZE:
+ if (!buff)
+ return RES_PARERR;
+ /* On SD/MMC devices, erase block size is the same as write
+ * block size.
+ * Hence, erasing as little as one sector is allowed. */
+ *param_u32 = 1;
+ res = RES_OK;
+ break;
+
+ case CTRL_TRIM:
+ /* This TRIM-like command is not implemented.
+ * It would be required if _USE_TRIM was enabled. */
+ res = RES_PARERR;
+ break;
+
+ default:
+ res = RES_PARERR;
+ break;
+ }
+ return res;
+}
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c
index a6206854e..601c95f2a 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c
@@ -238,7 +238,7 @@ uint8_t MmcInit(SdmmcDriver *driver)
error = error == SDMMC_CHANGED ? SDMMC_OK : error;
}
if (error != SDMMC_OK) {
- TRACE_1("HS %s\n\r", SD_StringifyRetCode(error));
+ TRACE_ERROR_1("HS %s\n\r", SD_StringifyRetCode(error));
return error;
}
}
@@ -271,7 +271,7 @@ uint8_t MmcInit(SdmmcDriver *driver)
&& tim_mode == SDMMC_TIM_MMC_HS_DDR)
driver->card.bSpeedMode = tim_mode;
else if (error) {
- TRACE_1("Width/DDR %s\n\r",
+ TRACE_ERROR_1("Width/DDR %s\n\r",
SD_StringifyRetCode(error));
return error;
}
@@ -306,7 +306,7 @@ uint8_t MmcInit(SdmmcDriver *driver)
error = error == SDMMC_CHANGED ? SDMMC_OK : error;
}
if (error != SDMMC_OK) {
- TRACE_1("HS200 %s\n\r", SD_StringifyRetCode(error));
+ TRACE_ERROR_1("HS200 %s\n\r", SD_StringifyRetCode(error));
return error;
}
}
@@ -367,7 +367,7 @@ uint8_t MmcInit(SdmmcDriver *driver)
return error;
status = status & ~STATUS_STATE & ~STATUS_READY_FOR_DATA & ~STATUS_APP_CMD;
if (status) {
- TRACE_1("st %lx\n\r", status);
+ TRACE_WARNING_1("st %lx\n\r", status);
}
return SDMMC_OK;
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_pmc.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_pmc.c
index 2f866296a..8a75a8656 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_pmc.c
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_pmc.c
@@ -3,7 +3,6 @@
#include "ch_sdmmc_pmc.h"
-
struct _pmc_main_osc {
uint32_t rc_freq;
uint32_t crystal_freq;
@@ -828,3 +827,5 @@ void pmc_disable_internal_osc(void)
#endif
}
+
+
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sama5d2.h b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sama5d2.h
index 34a137b91..ae05cee2f 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sama5d2.h
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sama5d2.h
@@ -8,6 +8,8 @@
#define SB1_SIZE 64
#define SB2_SIZE 8
+#define SDMMC_BUFFER_SIZE (EXT_SIZE + SSR_SIZE + SCR_SIZE + SB1_SIZE + SB2_SIZE)
+
/** Frequency of the board main clock oscillator */
#define BOARD_MAIN_CLOCK_EXT_OSC 12000000
#define MAIN_CLOCK_INT_OSC 12000000
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c
index 2f5e80a09..6363a0fac 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c
@@ -6,7 +6,10 @@
#include "ch_sdmmc_sd.h"
#include "ch_sdmmc_sdio.h"
-
+static uint8_t PerformSingleTransfer(SdmmcDriver *driver,uint32_t address, uint8_t * pData, uint8_t isRead);
+static uint8_t MoveToTransferState(SdmmcDriver *driver,uint32_t address,uint16_t * nbBlocks, uint8_t * pData, uint8_t isRead);
+static uint8_t _StopCmd(SdmmcDriver *driver);
+static uint8_t _WaitUntilReady(SdmmcDriver *driver, uint32_t last_dev_status);
static uint8_t SdGetTimingFunction(uint8_t mode);
static void SdSelectSlowerTiming(bool high_sig, uint8_t * mode);
@@ -78,6 +81,154 @@ const char * SD_StringifyIOCtrl(uint32_t dwCtrl)
}
#endif
+
+/**
+ * Read Blocks of data in a buffer pointed by pData. The buffer size must be at
+ * least 512 byte long. This function checks the SD card status register and
+ * address the card if required before sending the read command.
+ * \return 0 if successful; otherwise returns an \ref sdmmc_rc "error code".
+ * \param pSd Pointer to a SD card driver instance.
+ * \param address Address of the block to read.
+ * \param pData Data buffer whose size is at least the block size. It shall
+ * follow the peripheral and DMA alignment requirements.
+ * \param length Number of blocks to be read.
+ * \param pCallback Pointer to callback function that invoked when read done.
+ * 0 to start a blocked read.
+ * \param pArgs Pointer to callback function arguments.
+ */
+uint8_t SD_Read(SdmmcDriver *driver,uint32_t address,void *pData, uint32_t length)
+{
+ uint8_t *out = NULL;
+ uint32_t remaining, blk_no;
+ uint16_t limited;
+ uint8_t error = SDMMC_OK;
+
+
+ for (blk_no = address, remaining = length, out = (uint8_t *)pData;
+ remaining != 0 && error == SDMMC_OK;
+ blk_no += limited, remaining -= limited,
+ out += (uint32_t)limited * (uint32_t)driver->card.wCurrBlockLen)
+ {
+ limited = (uint16_t)min_u32(remaining, 65535);
+ error = MoveToTransferState(driver, blk_no, &limited, out, 1);
+ }
+ //debug
+ TRACE_DEBUG_3("SDrd(%lu,%lu) %s\n\r", address, length, SD_StringifyRetCode(error));
+ return error;
+}
+
+/**
+ * Write Blocks of data in a buffer pointed by pData. The buffer size must be at
+ * least 512 byte long. This function checks the SD card status register and
+ * address the card if required before sending the read command.
+ * \return 0 if successful; otherwise returns an \ref sdmmc_rc "error code".
+ * \param pSd Pointer to a SD card driver instance.
+ * \param address Address of the block to write.
+ * \param pData Data buffer whose size is at least the block size. It shall
+ * follow the peripheral and DMA alignment requirements.
+ * \param length Number of blocks to be write.
+ * \param pCallback Pointer to callback function that invoked when write done.
+ * 0 to start a blocked write.
+ * \param pArgs Pointer to callback function arguments.
+ */
+uint8_t SD_Write(SdmmcDriver *driver,uint32_t address,const void *pData,uint32_t length)
+{
+ uint8_t *in = NULL;
+ uint32_t remaining, blk_no;
+ uint16_t limited;
+ uint8_t error = SDMMC_OK;
+
+// assert(pSd != NULL);
+// assert(pData != NULL);
+
+ for (blk_no = address, remaining = length, in = (uint8_t *)pData;
+ remaining != 0 && error == SDMMC_OK;
+ blk_no += limited, remaining -= limited,
+ in += (uint32_t)limited * (uint32_t)driver->card.wCurrBlockLen) {
+ limited = (uint16_t)min_u32(remaining, 65535);
+ error = MoveToTransferState(driver, blk_no, &limited, in, 0);
+ }
+ //debug
+ TRACE_DEBUG_3("SDwr(%lu,%lu) %s\n\r", address, length, SD_StringifyRetCode(error));
+ return error;
+}
+
+/**
+ * Read Blocks of data in a buffer pointed by pData. The buffer size must be at
+ * least 512 byte long. This function checks the SD card status register and
+ * address the card if required before sending the read command.
+ * \return 0 if successful; otherwise returns an \ref sdmmc_rc "error code".
+ * \param pSd Pointer to a SD card driver instance.
+ * \param address Address of the block to read.
+ * \param nbBlocks Number of blocks to be read.
+ * \param pData Data buffer whose size is at least the block size. It shall
+ * follow the peripheral and DMA alignment requirements.
+ */
+uint8_t SD_ReadBlocks(SdmmcDriver *driver, uint32_t address, void *pData, uint32_t nbBlocks)
+{
+ uint8_t error = 0;
+ uint8_t *pBytes = (uint8_t *) pData;
+
+
+ //debug
+ TRACE_DEBUG_2("RdBlks(%lu,%lu)\n\r", address, nbBlocks);
+
+ while (nbBlocks--) {
+ error = PerformSingleTransfer(driver, address, pBytes, 1);
+ if (error)
+ break;
+ address += 1;
+ pBytes = &pBytes[512];
+ }
+ return error;
+}
+
+/**
+ * Write Block of data pointed by pData. The buffer size must be at
+ * least 512 byte long. This function checks the SD card status register and
+ * address the card if required before sending the read command.
+ * \return 0 if successful; otherwise returns an \ref sdmmc_rc "error code".
+ * \param pSd Pointer to a SD card driver instance.
+ * \param address Address of block to write.
+ * \param nbBlocks Number of blocks to be read
+ * \param pData Data buffer whose size is at least the block size. It shall
+ * follow the peripheral and DMA alignment requirements.
+ */
+uint8_t SD_WriteBlocks(SdmmcDriver *driver, uint32_t address, const void *pData, uint32_t nbBlocks)
+{
+ uint8_t error = 0;
+ uint8_t *pB = (uint8_t *) pData;
+
+
+ //debug
+ TRACE_DEBUG_2("WrBlks(%lu,%lu)\n\r", address, nbBlocks);
+
+ while (nbBlocks--) {
+ error = PerformSingleTransfer(driver, address, pB, 0);
+ if (error)
+ break;
+ address += 1;
+ pB = &pB[512];
+ }
+ return error;
+}
+
+uint8_t SD_GetStatus(SdmmcDriver *driver)
+{
+ uint32_t rc;
+
+ const sSdCard * pSd = &driver->card;
+
+ driver->control_param = 0;
+
+ rc = sdmmc_device_control(driver,SDMMC_IOCTL_GET_DEVICE);
+
+ if (rc != SDMMC_OK || !driver->control_param)
+ return SDMMC_NOT_SUPPORTED;
+
+ return pSd->bStatus == SDMMC_NOT_SUPPORTED ? SDMMC_ERR : pSd->bStatus;
+}
+
uint8_t SdDecideBuswidth(SdmmcDriver *drv)
{
uint8_t error, busWidth = 1;
@@ -155,7 +306,7 @@ uint8_t SdEnableHighSpeed(SdmmcDriver *drv)
return SDMMC_ERR;
sfs_v1 = SD_SWITCH_ST_DATA_STRUCT_VER(drv->card.sandbox1) >= 0x01;
mode_mask = SD_SWITCH_ST_FUN_GRP1_INFO(drv->card.sandbox1);
- TRACE_1("Device timing functions: 0x%04x\n\r", mode_mask);
+ TRACE_DEBUG_1("Device timing functions: 0x%04x\n\r", mode_mask);
if (has_io && mode == SDMMC_TIM_SD_HS
&& !(mode_mask & 1 << SD_SWITCH_ST_ACC_HS))
return SDMMC_NOT_SUPPORTED;
@@ -181,7 +332,7 @@ uint8_t SdEnableHighSpeed(SdmmcDriver *drv)
return SDMMC_STATE;
/* Check the electrical power requirements of this device */
val = SD_SWITCH_ST_FUN_GRP4_INFO(drv->card.sandbox1);
- TRACE_2("Device pwr & strength functions: 0x%04x & 0x%04x\n\r", val,
+ TRACE_DEBUG_2("Device pwr & strength functions: 0x%04x & 0x%04x\n\r", val,
SD_SWITCH_ST_FUN_GRP3_INFO(drv->card.sandbox1));
if (!(val & 1 << SD_SWITCH_ST_MAX_PWR_1_44W))
pwr_func = SD_SWITCH_ST_MAX_PWR_0_72W;
@@ -192,7 +343,7 @@ uint8_t SdEnableHighSpeed(SdmmcDriver *drv)
if (error || status & STATUS_SWITCH_ERROR)
return SDMMC_ERR;
val = SD_SWITCH_ST_MAX_CURR_CONSUMPTION(drv->card.sandbox1);
- TRACE_1("Device max current: %u mA\n\r", val);
+ TRACE_DEBUG_1("Device max current: %u mA\n\r", val);
if (val == 0 || val > (1440 * 10) / 36)
SdSelectSlowerTiming(drv->card.bCardSigLevel != 0, &mode);
else if (sfs_v1) {
@@ -257,7 +408,7 @@ Switch:
val = SD_SWITCH_ST_FUN_GRP4_RC(drv->card.sandbox1);
if (val != pwr_func) {
- TRACE_1("Device power limit 0x%x\n\r", val);
+ TRACE_DEBUG_1("Device power limit 0x%x\n\r", val);
}
Apply:
@@ -280,7 +431,7 @@ void SdGetExtInformation(SdmmcDriver *drv)
if (error == SDMMC_OK) {
card_status &= ~STATUS_READY_FOR_DATA;
if (card_status != (STATUS_APP_CMD | STATUS_TRAN)) {
- TRACE_1("SCR st %lx\n\r", card_status);
+ TRACE_DEBUG_1("SCR st %lx\n\r", card_status);
}
}
@@ -289,7 +440,7 @@ void SdGetExtInformation(SdmmcDriver *drv)
if (error == SDMMC_OK) {
card_status &= ~STATUS_READY_FOR_DATA;
if (card_status != (STATUS_APP_CMD | STATUS_TRAN)) {
- TRACE_1("SSR st %lx\n\r", card_status);
+ TRACE_DEBUG_1("SSR st %lx\n\r", card_status);
}
}
}
@@ -529,10 +680,10 @@ void SD_DumpStatus(const sSdCard *pSd)
strcat(mode, "104");
}
- TRACE_4("%s, %u-bit data, in %s mode at %lu kHz\n\r", text, pSd->bBusMode, mode, (pSd->dwCurrSpeed / 1000UL) );
+ TRACE_DEBUG_4("%s, %u-bit data, in %s mode at %lu kHz\n\r", text, pSd->bBusMode, mode, (pSd->dwCurrSpeed / 1000UL) );
if (pSd->bCardType & CARD_TYPE_bmSDMMC) {
- TRACE_3("Device memory size: %lu MiB, %lu * %uB\n\r", SD_GetTotalSizeKB(pSd) / 1024ul, pSd->dwNbBlocks,pSd->wBlockSize);
+ TRACE_DEBUG_3("Device memory size: %lu MiB, %lu * %uB\n\r", SD_GetTotalSizeKB(pSd) / 1024ul, pSd->dwNbBlocks,pSd->wBlockSize);
}
@@ -779,3 +930,242 @@ void SD_DumpExtCSD(const uint8_t *pExtCSD)
_PrintField("ER_GRP_DEF 0x%X\r\n", MMC_EXT_ERASE_GROUP_DEF(pExtCSD));
}
+
+
+/**
+ * Transfer a single data block.
+ * The device shall be in its Transfer State already.
+ * \param pSd Pointer to a SD card driver instance.
+ * \param address Address of the block to transfer.
+ * \param pData Data buffer, whose size is at least one block size.
+ * \param isRead Either 1 to read data from the device or 0 to write data.
+ * \return a \ref sdmmc_rc result code.
+ */
+static uint8_t PerformSingleTransfer(SdmmcDriver *driver,uint32_t address, uint8_t * pData, uint8_t isRead)
+{
+ uint8_t result = SDMMC_OK, error;
+ uint32_t sdmmc_address, status;
+
+ /* Convert block address into device-expected unit */
+ if (driver->card.bCardType & CARD_TYPE_bmHC)
+ sdmmc_address = address;
+ else if (address <= 0xfffffffful / driver->card.wCurrBlockLen)
+ sdmmc_address = address * driver->card.wCurrBlockLen;
+ else
+ return SDMMC_PARAM;
+
+ if (isRead)
+ /* Read a single data block */
+ error = Cmd17(driver, pData, sdmmc_address, &status);
+ else
+ /* Write a single data block */
+ error = Cmd24(driver, pData, sdmmc_address, &status);
+
+ if (!error) {
+ status = status & (isRead ? STATUS_READ : STATUS_WRITE)
+ & ~STATUS_READY_FOR_DATA & ~STATUS_STATE;
+ if (status) {
+ //error
+ TRACE_1("st %lx\n\r", status);
+ error = SDMMC_ERR;
+ }
+ }
+ if (error) {
+ //error
+ TRACE_ERROR_3("Cmd%u(0x%lx) %s\n\r", isRead ? 17 : 24,sdmmc_address, SD_StringifyRetCode(error));
+ result = error;
+ error = Cmd13(driver, &status);
+ if (error) {
+ driver->card.bStatus = error;
+ return result;
+ }
+ error = _WaitUntilReady(driver, status);
+ if (error) {
+ driver->card.bStatus = error;
+ return result;
+ }
+ }
+ return result;
+}
+
+/**
+ * Move SD card to transfer state. The buffer size must be at
+ * least 512 byte long. This function checks the SD card status register and
+ * address the card if required before sending the transfer command.
+ * Returns 0 if successful; otherwise returns an code describing the error.
+ * \param pSd Pointer to a SD card driver instance.
+ * \param address Address of the block to transfer.
+ * \param nbBlocks Pointer to count of blocks to transfer. Pointer to 0
+ * for infinite transfer. Upon return, points to the count of blocks actually
+ * transferred.
+ * \param pData Data buffer whose size is at least the block size.
+ * \param isRead 1 for read data and 0 for write data.
+ */
+static uint8_t MoveToTransferState(SdmmcDriver *driver,uint32_t address,uint16_t * nbBlocks, uint8_t * pData, uint8_t isRead)
+{
+ uint8_t result = SDMMC_OK, error;
+ uint32_t sdmmc_address, state, status;
+
+ /* Convert block address into device-expected unit */
+ if (driver->card.bCardType & CARD_TYPE_bmHC)
+ sdmmc_address = address;
+ else if (address <= 0xfffffffful / driver->card.wCurrBlockLen)
+ sdmmc_address = address * driver->card.wCurrBlockLen;
+ else
+ return SDMMC_PARAM;
+
+ if (driver->card.bSetBlkCnt) {
+ error = Cmd23(driver, 0, *nbBlocks, &status);
+ if (error)
+ return error;
+ }
+
+ if (isRead)
+ /* Move to Receiving data state */
+ error = Cmd18(driver, nbBlocks, pData, sdmmc_address, &status);
+ else
+ /* Move to Sending data state */
+ error = Cmd25(driver, nbBlocks, pData, sdmmc_address, &status);
+
+ if (error == SDMMC_CHANGED)
+ error = SDMMC_OK;
+
+ if (!error) {
+ status = status & (isRead ? STATUS_READ : STATUS_WRITE)
+ & ~STATUS_READY_FOR_DATA & ~STATUS_STATE;
+
+ if (driver->card.bStopMultXfer)
+ error = _StopCmd(driver);
+
+ if (status) {
+ //error
+ TRACE_DEBUG_1("st %lx\n\r", status);
+ /* TODO ignore STATUS_ADDR_OUT_OR_RANGE if the read
+ * operation is for the last block of memory area. */
+ error = SDMMC_ERR;
+ }
+ /* FIXME when not using the STOP_TRANSMISSION command (using the
+ * SET_BLOCK_COUNT command instead), we should issue the
+ * SEND_STATUS command, eat and handle any Execution Mode
+ * exception. */
+ }
+ if (error) {
+ //error
+ TRACE_ERROR_4("Cmd%u(0x%lx, %u) %s\n\r", isRead ? 18 : 25,sdmmc_address, *nbBlocks, SD_StringifyRetCode(error));
+ result = error;
+ error = Cmd13(driver, &status);
+
+ if (error) {
+ driver->card.bStatus = error;
+ return result;
+ }
+
+ state = status & STATUS_STATE;
+
+ if (state == STATUS_DATA || state == STATUS_RCV) {
+
+ error = Cmd12(driver, &status);
+
+ if (error == SDMMC_OK) {
+ //info
+ TRACE_INFO_1("st %lx\n\r", status);
+
+ if (status & (STATUS_ERASE_SEQ_ERROR
+ | STATUS_ERASE_PARAM | STATUS_UN_LOCK_FAILED
+ | STATUS_ILLEGAL_COMMAND
+ | STATUS_CIDCSD_OVERWRITE
+ | STATUS_ERASE_RESET | STATUS_SWITCH_ERROR))
+ result = SDMMC_STATE;
+ else if (status & (STATUS_COM_CRC_ERROR
+ | STATUS_CARD_ECC_FAILED | STATUS_ERROR))
+ result = SDMMC_ERR_IO;
+ else if (status & (STATUS_ADDR_OUT_OR_RANGE
+ | STATUS_ADDRESS_MISALIGN
+ | STATUS_BLOCK_LEN_ERROR
+ | STATUS_WP_VIOLATION
+ | STATUS_WP_ERASE_SKIP))
+ result = SDMMC_PARAM;
+ else if (status & STATUS_CC_ERROR)
+ result = SDMMC_ERR;
+ }
+ else if (error == SDMMC_NO_RESPONSE)
+ error = Cmd13(driver, &status);
+ if (error) {
+ driver->card.bStatus = error;
+ return result;
+ }
+ }
+ error = _WaitUntilReady(driver, status);
+
+ if (error) {
+ driver->card.bStatus = error;
+ return result;
+ }
+ }
+ return result;
+}
+
+/**
+ * Stop TX/RX
+ */
+static uint8_t _StopCmd(SdmmcDriver *driver)
+{
+ uint32_t status, state = STATUS_RCV;
+ uint32_t i;
+ uint8_t err, count;
+ /* When stopping a write operation, allow retrying several times */
+ for (i = 0; i < 9 && state == STATUS_RCV; i++) {
+ err = Cmd12(driver, &status);
+ if (err)
+ return err;
+ /* TODO handle any exception, raised in status; report that
+ * the data transfer has failed. */
+
+ /* Wait until ready. Allow 30 ms. */
+ for (count = 0; count < 6; count++) {
+ /* Wait for about 5 ms - which equals 5 system ticks */
+ t_msleep(driver,5);
+ err = Cmd13(driver, &status);
+ if (err)
+ return err;
+ state = status & STATUS_STATE;
+
+ /* Invalid state */
+ if (state == STATUS_IDLE || state == STATUS_READY
+ || state == STATUS_IDENT || state == STATUS_STBY
+ || state == STATUS_DIS)
+ return SDMMC_NOT_INITIALIZED;
+
+ /* Ready? */
+ if ((status & STATUS_READY_FOR_DATA) ==
+ STATUS_READY_FOR_DATA && state == STATUS_TRAN)
+ return SDMMC_OK;
+ }
+ }
+ return SDMMC_STATE;
+}
+
+static uint8_t _WaitUntilReady(SdmmcDriver *driver, uint32_t last_dev_status)
+{
+ uint32_t state, status = last_dev_status;
+ uint8_t err, count;
+
+ for (count = 0; count < 51; count++) {
+ state = status & STATUS_STATE;
+ if (state == STATUS_TRAN && status & STATUS_READY_FOR_DATA)
+ return SDMMC_OK;
+ /* Sending-data and Receive-data states may be encountered
+ * temporarily further to single-block data transfers. */
+ /* FIXME state 15 "reserved for I/O mode" may be allowed */
+ if (state != STATUS_TRAN && state != STATUS_PRG
+ && state != STATUS_DATA && state != STATUS_RCV)
+ return SDMMC_NOT_INITIALIZED;
+ /* Wait for about 10 ms - which equals 10 system ticks */
+ t_msleep(driver,10);
+ err = Cmd13(driver, &status);
+ if (err)
+ return err;
+ }
+ return SDMMC_BUSY;
+}
+
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.h b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.h
index d08778219..7708a88f1 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.h
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.h
@@ -75,10 +75,6 @@
#define SD_SWITCH_ST_FUN_GRP_FUN_BUSY(funNdx) (1 << (funNdx))
/** @}*/
-
-
-
-
/** We support 2.7 ~ 3.3V cards */
#define SD_HOST_VOLTAGE_RANGE (SD_OCR_VDD_27_28 +\
SD_OCR_VDD_28_29 +\
@@ -91,6 +87,10 @@
SD_OCR_VDD_35_36 )
+
+/** @}*/
+
+extern uint8_t SD_GetStatus(SdmmcDriver *driver);
extern uint8_t SdDecideBuswidth(SdmmcDriver *drv);
extern uint8_t SdEnableHighSpeed(SdmmcDriver *drv);
extern uint32_t SD_GetField(const uint8_t *reg, uint16_t reg_len, uint16_t field_start,
@@ -107,5 +107,10 @@ extern void SD_DumpSSR(const uint8_t *pSSR);
extern const char * SD_StringifyRetCode(uint32_t dwRCode);
extern const char * SD_StringifyIOCtrl(uint32_t dwCtrl);
+extern uint8_t SD_Read(SdmmcDriver *driver,uint32_t address,void *pData, uint32_t length);
+extern uint8_t SD_Write(SdmmcDriver *driver,uint32_t address,const void *pData,uint32_t length);
+extern uint8_t SD_ReadBlocks(SdmmcDriver *driver, uint32_t address, void *pData, uint32_t nbBlocks);
+extern uint8_t SD_WriteBlocks(SdmmcDriver *driver, uint32_t address, const void *pData, uint32_t nbBlocks);
+extern uint8_t SD_ReadBlocks(SdmmcDriver *driver, uint32_t address, void *pData, uint32_t nbBlocks);
#endif /* CH_SDMMC_SD_H_ */
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_tc.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_tc.c
index b8898acb5..9b66742c7 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_tc.c
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_tc.c
@@ -3,6 +3,8 @@
#include "ch_sdmmc_pmc.h"
#include "ch_sdmmc_tc.h"
+#if SDMMC_USE_TC == 1
+
/*------------------------------------------------------------------------------
* Global functions
*------------------------------------------------------------------------------*/
@@ -249,3 +251,4 @@ uint32_t tc_get_cv(Tc* tc, uint32_t channel)
return ch->TC_CV;
}
+#endif
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_trace.h b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_trace.h
index 1bb9ad15f..20ea20f50 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_trace.h
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_trace.h
@@ -23,7 +23,80 @@ extern BaseSequentialStream * ts;
#define TRACE_4(s,v1,v2,v3,v4)
#define TRACE_5(s,v1,v2,v3,v4,v5)
#define TRACE_6(s,v1,v2,v3,v4,v5,v6)
-#define TRACE_LEV_1(s,v1)
+#endif
+
+#if SAMA_SDMMC_TRACE_LEVEL >= 1
+#define TRACE_INFO(s) TRACE(s)
+#define TRACE_INFO_1(s,v1) TRACE_1(s,v1)
+#define TRACE_INFO_2(s,v1,v2) TRACE_2(s,v1,v2)
+#define TRACE_INFO_3(s,v1,v2,v3) TRACE_3(s,v1,v2,v3)
+#define TRACE_INFO_4(s,v1,v2,v3,v4) TRACE_4(s,v1,v2,v3,v4)
+#define TRACE_INFO_5(s,v1,v2,v3,v4,v5) TRACE_5(s,v1,v2,v3,v4,v5)
+#define TRACE_INFO_6(s,v1,v2,v3,v4,v5,v6) TRACE_6(s,v1,v2,v3,v4,v5,v6)
+#else
+#define TRACE_INFO(s)
+#define TRACE_INFO_1(s,v1)
+#define TRACE_INFO_2(s,v1,v2)
+#define TRACE_INFO_3(s,v1,v2,v3)
+#define TRACE_INFO_4(s,v1,v2,v3,v4)
+#define TRACE_INFO_5(s,v1,v2,v3,v4,v5)
+#define TRACE_INFO_6(s,v1,v2,v3,v4,v5,v6)
+#endif
+
+
+#if SAMA_SDMMC_TRACE_LEVEL >= 2
+#define TRACE_WARNING(s) TRACE(s)
+#define TRACE_WARNING_1(s,v1) TRACE_1(s,v1)
+#define TRACE_WARNING_2(s,v1,v2) TRACE_2(s,v1,v2)
+#define TRACE_WARNING_3(s,v1,v2,v3) TRACE_3(s,v1,v2,v3)
+#define TRACE_WARNING_4(s,v1,v2,v3,v4) TRACE_4(s,v1,v2,v3,v4)
+#define TRACE_WARNING_5(s,v1,v2,v3,v4,v5) TRACE_5(s,v1,v2,v3,v4,v5)
+#define TRACE_WARNING_6(s,v1,v2,v3,v4,v5,v6) TRACE_6(s,v1,v2,v3,v4,v5,v6)
+#else
+#define TRACE_WARNING(s)
+#define TRACE_WARNING_1(s,v1)
+#define TRACE_WARNING_2(s,v1,v2)
+#define TRACE_WARNING_3(s,v1,v2,v3)
+#define TRACE_WARNING_4(s,v1,v2,v3,v4)
+#define TRACE_WARNING_5(s,v1,v2,v3,v4,v5)
+#define TRACE_WARNING_6(s,v1,v2,v3,v4,v5,v6)
+#endif
+
+
+#if SAMA_SDMMC_TRACE_LEVEL >= 3
+#define TRACE_ERROR(s) TRACE(s)
+#define TRACE_ERROR_1(s,v1) TRACE_1(s,v1)
+#define TRACE_ERROR_2(s,v1,v2) TRACE_2(s,v1,v2)
+#define TRACE_ERROR_3(s,v1,v2,v3) TRACE_3(s,v1,v2,v3)
+#define TRACE_ERROR_4(s,v1,v2,v3,v4) TRACE_4(s,v1,v2,v3,v4)
+#define TRACE_ERROR_5(s,v1,v2,v3,v4,v5) TRACE_5(s,v1,v2,v3,v4,v5)
+#define TRACE_ERROR_6(s,v1,v2,v3,v4,v5,v6) TRACE_6(s,v1,v2,v3,v4,v5,v6)
+#else
+#define TRACE_ERROR(s)
+#define TRACE_ERROR_1(s,v1)
+#define TRACE_ERROR_2(s,v1,v2)
+#define TRACE_ERROR_3(s,v1,v2,v3)
+#define TRACE_ERROR_4(s,v1,v2,v3,v4)
+#define TRACE_ERROR_5(s,v1,v2,v3,v4,v5)
+#define TRACE_ERROR_6(s,v1,v2,v3,v4,v5,v6)
+#endif
+
+#if SAMA_SDMMC_TRACE_LEVEL >= 4
+#define TRACE_DEBUG(s) TRACE(s)
+#define TRACE_DEBUG_1(s,v1) TRACE_1(s,v1)
+#define TRACE_DEBUG_2(s,v1,v2) TRACE_2(s,v1,v2)
+#define TRACE_DEBUG_3(s,v1,v2,v3) TRACE_3(s,v1,v2,v3)
+#define TRACE_DEBUG_4(s,v1,v2,v3,v4) TRACE_4(s,v1,v2,v3,v4)
+#define TRACE_DEBUG_5(s,v1,v2,v3,v4,v5) TRACE_5(s,v1,v2,v3,v4,v5)
+#define TRACE_DEBUG_6(s,v1,v2,v3,v4,v5,v6) TRACE_6(s,v1,v2,v3,v4,v5,v6)
+#else
+#define TRACE_DEBUG(s)
+#define TRACE_DEBUG_1(s,v1)
+#define TRACE_DEBUG_2(s,v1,v2)
+#define TRACE_DEBUG_3(s,v1,v2,v3)
+#define TRACE_DEBUG_4(s,v1,v2,v3,v4)
+#define TRACE_DEBUG_5(s,v1,v2,v3,v4,v5)
+#define TRACE_DEBUG_6(s,v1,v2,v3,v4,v5,v6)
#endif
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk b/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk
index ae2e9f16a..13494bdc2 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk
@@ -1,12 +1,13 @@
PLATFORMSRC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c \
$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c \
$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sdio.c \
- $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_pmc.c \
$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c \
$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_tc.c \
$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c \
$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c \
- $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c
+ $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c \
+ $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_ff.c \
+ $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_pmc.c
PLATFORMINC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_conf.h b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_conf.h
index 560fcb1c7..0fb377549 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_conf.h
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_conf.h
@@ -14,12 +14,19 @@ typedef FATFS CH_SDMMC_FAT;
#define SAMA_SDMMC_TRACE 0
#endif
+#ifndef SAMA_SDMMC_TRACE_LEVEL
+#define SAMA_SDMMC_TRACE_LEVEL 0
+#endif
/** Default block size for SD/MMC access */
#ifndef SDMMC_BLOCK_SIZE
#define SDMMC_BLOCK_SIZE 512
#endif
+#ifndef SDMMC_USE_TC
+#define SDMMC_USE_TC 0
+#endif
+
#endif //SAMA_SDMMC_CONF_H
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c
index 105e18036..7aed656dc 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c
@@ -23,7 +23,7 @@
*/
#include "hal.h"
-
+#include "ccportab.h"
#if (HAL_USE_SDMMC == TRUE) || defined(__DOXYGEN__)
#include <string.h>
#include "sama_sdmmc_lld.h"
@@ -129,11 +129,9 @@ void sdmmcStart(SdmmcDriver *sdmmcp, const SamaSDMMCConfig *config)
}
- TRACE_LEV_1("[%s] Cannot init board for MMC\r\n","ERROR");
+ TRACE_ERROR("Cannot init board for MMC\r\n");
sdmmcp->state = MCID_INIT_ERROR;
-
-
}
/**
@@ -177,7 +175,7 @@ uint8_t sdmmcSendCmd(SdmmcDriver *sdmmcp)
uint8_t bRc;
if (sdmmcp->cmd.bCmd != 55) {
- TRACE_2("Cmd%u(%lx)\n\r", sdmmcp->cmd.bCmd, sdmmcp->cmd.dwArg);
+ TRACE_INFO_2("Cmd%u(%lx)\n\r", sdmmcp->cmd.bCmd, sdmmcp->cmd.dwArg);
}
bRc = sdmmc_device_command(sdmmcp);
@@ -198,6 +196,7 @@ uint8_t sdmmcSendCmd(SdmmcDriver *sdmmcp)
sdmmcp->control_param = 1;
sdmmcp->timeout_elapsed = 0;
+ sdmmcp->timeout_ticks = 30*1000;
sdmmc_device_startTimeCount(sdmmcp);
do
@@ -221,18 +220,17 @@ uint8_t sdmmcSendCmd(SdmmcDriver *sdmmcp)
}
bRc = sdmmcp->cmd.bStatus;
- //TRACE_1("post cmd bRc = %d\r\n",bRc);
+
if (bRc == SDMMC_CHANGED) {
- //TRACE_2("Changed Cmd%u %s\n\r", sdmmcp->cmd.bCmd,SD_StringifyRetCode(bRc));
+ TRACE_DEBUG_2("Changed Cmd%u %s\n\r", sdmmcp->cmd.bCmd,SD_StringifyRetCode(bRc));
}
else if (bRc != SDMMC_OK) {
- //TRACE_2("OK Cmd%u %s\n\r", sdmmcp->cmd.bCmd,SD_StringifyRetCode(bRc));
+ TRACE_DEBUG_2("OK Cmd%u %s\n\r", sdmmcp->cmd.bCmd,SD_StringifyRetCode(bRc));
}
else if (sdmmcp->cmd.cmdOp.bmBits.respType == 1 && sdmmcp->cmd.pResp) {
- //TRACE_2("Resp Cmd%u st %lx\n\r", sdmmcp->cmd.bCmd, *sdmmcp->cmd.pResp);
+ TRACE_DEBUG_2("Resp Cmd%u st %lx\n\r", sdmmcp->cmd.bCmd, *sdmmcp->cmd.pResp);
}
- //TRACE_1("[ret sending cmd] %d\r\n",bRc);
return bRc;
}
@@ -252,14 +250,14 @@ bool sdmmcOpenDevice(SdmmcDriver *sdmmcp)
rc = sdmmc_device_start(sdmmcp);
if (rc != SDMMC_OK) {
- TRACE_1("SD/MMC device initialization failed: %d\n\r", rc);
+ TRACE_INFO_1("SD/MMC device initialization failed: %d\n\r", rc);
return false;
}
- if (sdmmc_device_identify(sdmmcp) == SDMMC_OK) {
+ if (sdmmc_device_identify(sdmmcp) != SDMMC_OK) {
return false;
}
- TRACE("SD/MMC device initialization successful\n\r");
+ TRACE_INFO("SD/MMC device initialization successful\n\r");
return true;
}
@@ -272,13 +270,13 @@ bool sdmmcCloseDevice(SdmmcDriver *sdmmcp)
bool sdmmcShowDeviceInfo(SdmmcDriver *sdmmcp)
{
sSdCard *pSd =&sdmmcp->card;
- TRACE("Show Device Info:\n\r");
+ TRACE_INFO("Show Device Info:\n\r");
#ifndef SDMMC_TRIM_INFO
const uint8_t card_type = sdmmcp->card.bCardType;
- TRACE_1("Card Type: %d\n\r", card_type);
+ TRACE_INFO_1("Card Type: %d\n\r", card_type);
#endif
- TRACE("Dumping Status ... \n\r");
+ TRACE_INFO("Dumping Status ... \n\r");
SD_DumpStatus(pSd);
#ifndef SDMMC_TRIM_INFO
if (card_type & CARD_TYPE_bmSDMMC)
@@ -304,58 +302,24 @@ bool sdmmcShowDeviceInfo(SdmmcDriver *sdmmcp)
bool sdmmcMountVolume(SdmmcDriver *sdmmcp, CH_SDMMC_FAT *fs)
{
-#if 0
- //TODO to be done
- const TCHAR drive_path[] = { '0' + sdmmcp->config->slot_id, ':', '\0' };
- DIR dir = { .sect = 0 };
- FILINFO fno = { 0 };
FRESULT res;
- bool is_dir, rc = true;
+ const TCHAR drive_path[] = { '0' + sdmmcp->config->slot_id, ':', '\0' };
(void)sdmmcp;
memset(fs, 0, sizeof(CH_SDMMC_FAT));
res = f_mount(fs, drive_path, 1);
if (res != FR_OK) {
- TRACE_1("Failed to mount FAT file system, error %d\n\r", res);
+ TRACE_INFO_1("Failed to mount FAT file system, error %d\n\r", res);
return false;
}
- res = f_opendir(&dir, drive_path);
- if (res != FR_OK) {
- TRACE_1("Failed to change to root directory, error %d\n\r", res);
- return false;
- } TRACE("Listing the files present in the root directory:\n\r");
- for (;;) {
- res = f_readdir(&dir, &fno);
- if (res != FR_OK) {
- TRACE_1("Error (%d) while listing files\n\r", res);
- rc = false;
- break;
- }
- if (fno.fname[0] == '\0')
- break;
- is_dir = fno.fattrib & AM_DIR ? true : false;
- TRACE_3(" %s%s%c\n\r", is_dir ? "[" : "", fno.fname,is_dir ? ']' : ' ');
- }
- res = f_closedir(&dir);
- if (res != FR_OK) {
- TRACE_1("Failed to close directory, error %d\n\r", res);
- rc = false;
- }
- return rc;
-#else
- (void)sdmmcp;
- (void)fs;
- return 0;
-#endif
+ return true;
}
bool sdmmcUnmountVolume(SdmmcDriver *sdmmcp)
{
- #if 0
- //TODO to be done
const TCHAR drive_path[] = { '0' + sdmmcp->config->slot_id, ':', '\0' };
FRESULT res;
bool rc = true;
@@ -365,13 +329,15 @@ bool sdmmcUnmountVolume(SdmmcDriver *sdmmcp)
rc = false;
return rc;
-#else
- (void)sdmmcp;
- return 0;
-#endif
}
+bool CC_WEAK sdmmcGetInstance(uint8_t index, SdmmcDriver **sdmmcp)
+{
+ (void)index;
+ (void)sdmmcp;
+ return false;
+}
#endif /* HAL_USE_SDMMC == TRUE */
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.h b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.h
index 9b672c642..7093dd9b3 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.h
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.h
@@ -78,21 +78,18 @@ typedef struct {
struct _pmc_periph_cfg pmccfg;
bool use_fastest_clock;
-
+#if SDMMC_USE_TC == 1
Tc * tctimer;
-
uint8_t tc_chan;
+#endif
uint8_t * bp;
uint8_t * data_buf;
uint32_t data_buf_size;
-
-
uint32_t * dma_table;
uint32_t dma_table_size;
-
} SamaSDMMCConfig;
@@ -132,6 +129,11 @@ struct SamaSDMMCDriver
uint32_t timeout_ticks;
int8_t timeout_elapsed;
systime_t time,now;
+#if SDMMC_USE_TC == 0
+ rtcnt_t timeout_cycles;
+ rtcnt_t start_cycles;
+#endif
+
};
typedef sSdCard sdmmclib;
typedef struct SamaSDMMCDriver SdmmcDriver;
diff --git a/os/hal/ports/SAMA/SAMA5D2x/platform.mk b/os/hal/ports/SAMA/SAMA5D2x/platform.mk
index 3f8b171ed..2c1f6e15b 100644
--- a/os/hal/ports/SAMA/SAMA5D2x/platform.mk
+++ b/os/hal/ports/SAMA/SAMA5D2x/platform.mk
@@ -33,6 +33,7 @@ include $(CHIBIOS)/os/hal/ports/SAMA/LLD/SPIv1/driver.mk
include $(CHIBIOS)/os/hal/ports/SAMA/LLD/RTCv1/driver.mk
include $(CHIBIOS)/os/hal/ports/SAMA/LLD/USARTv1/driver.mk
include $(CHIBIOS)/os/hal/ports/SAMA/LLD/CRYPTOv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk
# Shared variables
ALLCSRC += $(PLATFORMSRC)