6 #include "FsDriveSdio.hpp"
7 #include "LibEndian.hpp"
11 FsDriveSdio* FsDriveSdio::sInstances[1];
13 FsDriveSdio::FsDriveSdio() :
18 FsDriveSdio::~FsDriveSdio() {
22 bool FsDriveSdio::init() {
23 NVIC ->IP[SDIO_IRQn] = RTOS_INT_PRI;
24 NVIC_EnableIRQ(SDIO_IRQn);
27 SDIO ->CLKCR = (DRV_CFG_PCLK1_FREQ / 400000) - 2;
28 SDIO ->POWER = SDIO_POWER_PWRCTRL;
29 SDIO ->CLKCR |= SDIO_CLKCR_CLKEN;
30 sendCmd(0, CMD_GO_IDLE_STATE | SDIO_CMD_CPSMEN );
31 if (sendCmd(SD_CHECK_PATTERN, SDIO_SEND_IF_COND | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_7)) {
32 mFlags.bits.isSdhc =
true;
35 sendCmd(0, CMD_APP_CMD | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1);
38 if (sendCmd(0, CMD_APP_CMD | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1)) {
40 sendCmd(0, CMD_APP_CMD | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1);
41 if (mFlags.bits.isSdhc) {
42 sendCmd(0xC0100000, CMD_SD_APP_OP_COND | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1);
45 sendCmd(0x80100000, CMD_SD_APP_OP_COND | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1);
48 status.value = SDIO ->RESP1;
49 if (status.bits.outOfRange) {
50 if (status.bits.addressError) {
51 mFlags.bits.isSdhc = 1;
54 mFlags.bits.isSdhc = 0;
63 if (!sendCmd(0, CMD_ALL_SEND_CID | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_1 | SDIO_CMD_WAITRESP_0, RESP_2)) {
66 mCid.values[0] = SDIO ->RESP4;
67 mCid.values[1] = SDIO ->RESP3;
68 mCid.values[2] = SDIO ->RESP2;
69 mCid.values[3] = SDIO ->RESP1;
71 if (!sendCmd(0, CMD_SET_REL_ADDR | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_6)) {
75 mRca.value = SDIO ->RESP1;
76 if (mRca.value & RESP_RCA_STATUS_ERROR_BITS) {
80 if (!sendCmd(mRca.bits.newRca << 16, CMD_SEND_CSD | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_1 | SDIO_CMD_WAITRESP_0, RESP_2)) {
83 mCsd.values[0] = SDIO ->RESP4;
84 mCsd.values[1] = SDIO ->RESP3;
85 mCsd.values[2] = SDIO ->RESP2;
86 mCsd.values[3] = SDIO ->RESP1;
89 if (mCsd.bitsV1.csdStruct == 0) {
90 mSectorsCount = ((((uint32_t) mCsd.bitsV1.cSizeHi) << 2) + mCsd.bitsV1.cSizeLo) + 1;
91 mSectorsCount *= ((uint32_t) 2) << (((uint32_t) mCsd.bitsV1.cSizeMult) + 2);
92 uint32_t blocklen = ((uint32_t) 2) << mCsd.bitsV1.readBlLen;
93 mSectorsCount = (mSectorsCount / 512) * blocklen;
95 else if (mCsd.bitsV2.csdStruct == 1) {
96 mSectorsCount = (((uint32_t) mCsd.bitsV2.cSizeHi) << 16) + (uint32_t) mCsd.bitsV2.cSizeLo + 1;
97 mSectorsCount *= 1024;
104 SDIO ->CLKCR &= ~SDIO_CLKCR_CLKDIV;
107 if (!sendCmd(mRca.bits.newRca << 16, CMD_SEL_DESEL_CARD | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1)) {
111 if (!sendCmd(8, CMD_SET_BLOCKLEN | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1)) {
115 if (!sendCmd(mRca.bits.newRca << 16, CMD_APP_CMD | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1)) {
119 dataTransferConfig(0xFFFFFFFF, 8, SDIO_DCTRL_DBLOCKSIZE_0 | SDIO_DCTRL_DBLOCKSIZE_1 | SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTEN );
121 if (!sendCmd(0, CMD_SD_APP_SEND_SCR | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1)) {
125 for (
int i = 0; i < 2 && !(SDIO ->STA & (SDIO_STA_RXOVERR | SDIO_STA_DCRCFAIL | SDIO_STA_DTIMEOUT | SDIO_STA_DBCKEND | SDIO_STA_STBITERR ));) {
129 if (SDIO ->STA & SDIO_STA_RXDAVL ) {
130 mScr.value[i] = LibEndian::beToHw(SDIO ->FIFO);
135 if (SDIO ->STA & (SDIO_STA_DTIMEOUT | SDIO_STA_DCRCFAIL | SDIO_STA_RXOVERR | SDIO_STA_STBITERR )) {
138 SDIO ->ICR = SDIO_STATIC_FLAGS;
140 if (!(mScr.bits.datBusWidthSupport & 0b0100)) {
144 if (!sendCmd(mRca.bits.newRca << 16, CMD_APP_CMD | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1)) {
148 if (!sendCmd(2, CMD_APP_SD_SET_BUSWIDTH | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1)) {
152 SDIO ->CLKCR |= SDIO_CLKCR_WIDBUS_0;
154 if (!sendCmd(512, CMD_SET_BLOCKLEN | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1)) {
157 mBytesPerSector = 512;
162 bool FsDriveSdio::readBlocks(FsDefs::SECTOR* buffer,
unsigned int blockNumber,
unsigned int blockCount) {
165 while (retries-- > 0) {
167 int timeout = 100000;
170 if (getState(&state)) {
171 if (state == SD_STATE_TRAN) {
180 DMA2 ->LIFCR = 0x0F000000;
181 DMA2_Stream3 ->CR = 0;
182 DMA2_Stream3 ->FCR = DMA_SxFCR_FTH | DMA_SxFCR_DMDIS;
183 DMA2_Stream3 ->M0AR = (uint32_t) buffer;
184 DMA2_Stream3 ->NDTR = 0;
185 DMA2_Stream3 ->PAR = (uint32_t) &SDIO ->FIFO;
186 DMA2_Stream3 ->CR = DMA_SxCR_CHSEL_2 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_1 | DMA_SxCR_MSIZE_1 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1 | DMA_SxCR_MBURST_0
187 | DMA_SxCR_PBURST_0 | DMA_SxCR_PFCTRL | DMA_SxCR_EN;
189 if (!sendCmd(blockNumber, CMD_READ_MULT_BLOCK | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1)) {
193 SDIO ->MASK |= SDIO_STA_DATAEND | SDIO_STA_DCRCFAIL;
194 dataTransferConfig(0xFFFFFFFF, blockCount * 512,
195 SDIO_DCTRL_DBLOCKSIZE_0 | SDIO_DCTRL_DMAEN | SDIO_DCTRL_DBLOCKSIZE_3 | SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTEN );
199 if (waitInterrupt(&status)) {
200 if (status & SDIO_STA_DCRCFAIL ) {
203 else if (status & SDIO_STA_DATAEND ) {
208 sendCmd(0, CMD_STOP_TRANSMISSION | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1);
218 bool FsDriveSdio::writeBlocks(
const FsDefs::SECTOR* buffer,
unsigned int blockNumber,
unsigned int blockCount) {
221 while (retries-- > 0) {
223 int timeout = 100000;
226 if (getState(&state)) {
227 if (state == SD_STATE_TRAN) {
236 DMA2 ->LIFCR = 0x0F000000;
237 DMA2_Stream3 ->CR = 0;
238 DMA2_Stream3 ->FCR = DMA_SxFCR_FTH | DMA_SxFCR_DMDIS;
239 DMA2_Stream3 ->M0AR = (uint32_t) buffer;
240 DMA2_Stream3 ->NDTR = 0;
241 DMA2_Stream3 ->PAR = (uint32_t) &SDIO ->FIFO;
242 DMA2_Stream3 ->CR = DMA_SxCR_CHSEL_2 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_1 | DMA_SxCR_MSIZE_1 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1 | DMA_SxCR_MBURST_0
243 | DMA_SxCR_PBURST_0 | DMA_SxCR_PFCTRL | DMA_SxCR_EN | DMA_SxCR_DIR_0;
245 if (!sendCmd(mRca.bits.newRca << 16, CMD_APP_CMD | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1)) {
249 if (!sendCmd(blockCount, CMD_SET_BLOCK_COUNT | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1)) {
253 if (!sendCmd(blockNumber, CMD_WRITE_MULT_BLOCK | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1)) {
257 SDIO ->MASK |= SDIO_STA_DATAEND | SDIO_STA_DCRCFAIL;
258 dataTransferConfig(0xFFFFFFFF, blockCount * 512, SDIO_DCTRL_DBLOCKSIZE_0 | SDIO_DCTRL_DMAEN | SDIO_DCTRL_DBLOCKSIZE_3 | SDIO_DCTRL_DTEN );
262 if (waitInterrupt(&status)) {
263 if (status & SDIO_STA_DCRCFAIL ) {
266 else if (status & SDIO_STA_DATAEND ) {
271 sendCmd(0, CMD_STOP_TRANSMISSION | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1);
281 bool FsDriveSdio::waitInterrupt(uint32_t* status) {
284 SDIO->ICR = SDIO_STATIC_FLAGS;
288 bool FsDriveSdio::sendCmd(uint32_t arg, uint32_t cmd, RESPONSE response) {
290 if (cmd & SDIO_CMD_WAITRESP_0 ) {
291 SDIO ->MASK |= SDIO_STA_CMDREND | SDIO_STA_CCRCFAIL | SDIO_STA_CTIMEOUT;
296 if (SDIO ->STA & SDIO_STA_CMDREND ) {
297 SDIO ->ICR = SDIO_STATIC_FLAGS;
302 if ((SDIO ->RESPCMD & 0b11111) != (cmd & 0b11111)) {
306 status.value = SDIO ->RESP1;
307 if (status.value & RESP_STATUS_ERROR_BITS) {
321 if ((SDIO ->RESPCMD & 0b11111) != (cmd & 0b11111)) {
331 if (SDIO ->STA & SDIO_STA_CCRCFAIL ) {
332 SDIO ->ICR = SDIO_STA_CCRCFAIL;
335 if (SDIO ->STA & SDIO_STA_CTIMEOUT ) {
336 SDIO ->ICR = SDIO_STA_CTIMEOUT;
341 SDIO ->MASK |= SDIO_STA_CMDSENT;
346 SDIO ->ICR = SDIO_STATIC_FLAGS;
352 bool FsDriveSdio::getState(SD_STATE* state) {
353 if (!sendCmd(mRca.bits.newRca << 16, CMD_SEND_STATUS | SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0, RESP_1)) {
356 *state = ((RESP_STATUS*) (&SDIO ->RESP1))->bits.currentState;
360 void FsDriveSdio::dataTransferConfig(uint32_t timer, uint32_t datalen, uint32_t ctrlFlags) {
361 SDIO ->DTIMER = timer;
362 SDIO ->DLEN = datalen;
363 SDIO ->DCTRL = ctrlFlags;
366 void FsDriveSdio::onIntSdio() {
367 mSemaInt.giveFromInt();
368 SDIO ->MASK &= ~SDIO_STATIC_FLAGS;
371 extern "C" void RtosInterrupt::IRQ_SDIO() {
372 FsDriveSdio::sInstances[0]->onIntSdio();