microsd.c
Go to the documentation of this file.00001
00019 #include "diskio.h"
00020 #include "microsd.h"
00021 #include "em_cmu.h"
00022 #include "em_usart.h"
00023
00024
00030 static uint32_t timeOut, xfersPrMsec;
00031
00032
00036 static uint8_t WaitReady(void)
00037 {
00038 uint8_t res;
00039 uint32_t retryCount;
00040
00041
00042 retryCount = 500 * xfersPrMsec;
00043 do
00044 res = MICROSD_XferSpi(0xff);
00045 while ((res != 0xFF) && --retryCount);
00046
00047 return res;
00048 }
00051
00056 void MICROSD_Init(void)
00057 {
00058 USART_InitSync_TypeDef init = USART_INITSYNC_DEFAULT;
00059
00060
00061 CMU_ClockEnable(MICROSD_CMUCLOCK, true);
00062 CMU_ClockEnable(cmuClock_GPIO, true);
00063
00064
00065 xfersPrMsec = MICROSD_LO_SPI_FREQ / 8000;
00066 init.baudrate = MICROSD_LO_SPI_FREQ;
00067 init.msbf = true;
00068 USART_InitSync(MICROSD_USART, &init);
00069
00070
00071 MICROSD_USART->ROUTE = USART_ROUTE_TXPEN | USART_ROUTE_RXPEN |
00072 USART_ROUTE_CLKPEN | MICROSD_LOC;
00073
00074 #if defined( USART_CTRL_SMSDELAY )
00075
00076 MICROSD_USART->CTRL |= USART_CTRL_SMSDELAY;
00077 #endif
00078
00079
00080 GPIO_PinModeSet(MICROSD_GPIOPORT, MICROSD_MOSIPIN, gpioModePushPull, 0);
00081 GPIO_PinModeSet(MICROSD_GPIOPORT, MICROSD_MISOPIN, gpioModeInputPull, 1);
00082 GPIO_PinModeSet(MICROSD_GPIOPORT, MICROSD_CSPIN, gpioModePushPull, 1);
00083 GPIO_PinModeSet(MICROSD_GPIOPORT, MICROSD_CLKPIN, gpioModePushPull, 0);
00084 }
00085
00086
00091 void MICROSD_Deinit(void)
00092 {
00093 USART_Reset(MICROSD_USART);
00094
00095
00096 GPIO_PinModeSet(MICROSD_GPIOPORT, MICROSD_MOSIPIN, gpioModeDisabled, 0);
00097 GPIO_PinModeSet(MICROSD_GPIOPORT, MICROSD_MISOPIN, gpioModeDisabled, 0);
00098 GPIO_PinModeSet(MICROSD_GPIOPORT, MICROSD_CSPIN, gpioModeDisabled, 0);
00099 GPIO_PinModeSet(MICROSD_GPIOPORT, MICROSD_CLKPIN, gpioModeDisabled, 0);
00100 }
00101
00102
00112 uint8_t MICROSD_XferSpi(uint8_t data)
00113 {
00114 if ( timeOut )
00115 {
00116 timeOut--;
00117 }
00118
00119 return USART_SpiTransfer(MICROSD_USART, data);
00120 }
00121
00122
00125 void MICROSD_Deselect(void)
00126 {
00127 GPIO->P[ MICROSD_GPIOPORT ].DOUTSET = 1 << MICROSD_CSPIN;
00128 MICROSD_XferSpi(0xff);
00129 }
00130
00131
00135 int MICROSD_Select(void)
00136 {
00137 GPIO->P[ MICROSD_GPIOPORT ].DOUTCLR = 1 << MICROSD_CSPIN;
00138 if (WaitReady() != 0xFF)
00139 {
00140 MICROSD_Deselect();
00141 return 0;
00142 }
00143 return 1;
00144 }
00145
00146
00150 void MICROSD_PowerOn(void)
00151 {
00152
00153 CMU_ClockEnable(MICROSD_CMUCLOCK, true);
00154 }
00155
00156
00160 void MICROSD_PowerOff(void)
00161 {
00162
00163 MICROSD_Select();
00164 MICROSD_Deselect();
00165
00166 CMU_ClockEnable(MICROSD_CMUCLOCK, false);
00167 }
00168
00169
00178 int MICROSD_BlockRx(uint8_t *buff, uint32_t btr)
00179 {
00180 uint8_t token;
00181 uint16_t val;
00182 uint32_t retryCount, framectrl, ctrl;
00183
00184
00185 retryCount = 100 * xfersPrMsec;
00186 do
00187 {
00188 token = MICROSD_XferSpi(0xff);
00189 } while ((token == 0xFF) && --retryCount);
00190
00191 if (token != 0xFE)
00192 {
00193
00194 return 0;
00195 }
00196
00197
00198 framectrl = MICROSD_USART->FRAME;
00199 ctrl = MICROSD_USART->CTRL;
00200
00201
00202 MICROSD_USART->FRAME = (MICROSD_USART->FRAME & (~_USART_FRAME_DATABITS_MASK))
00203 | USART_FRAME_DATABITS_SIXTEEN;
00204 MICROSD_USART->CTRL |= USART_CTRL_BYTESWAP;
00205
00206
00207 MICROSD_USART->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
00208
00209 if ( timeOut >= btr + 2 )
00210 {
00211 timeOut -= btr + 2;
00212 }
00213 else
00214 {
00215 timeOut = 0;
00216 }
00217
00218
00219
00220
00221 MICROSD_USART->TXDOUBLE = 0xffff;
00222 do
00223 {
00224 MICROSD_USART->TXDOUBLE = 0xffff;
00225
00226 while (!(MICROSD_USART->STATUS & USART_STATUS_RXDATAV));
00227
00228 val = MICROSD_USART->RXDOUBLE;
00229 *buff++ = val;
00230 *buff++ = val >> 8;
00231
00232 btr -= 2;
00233 } while (btr);
00234
00235
00236 while (!(MICROSD_USART->STATUS & USART_STATUS_RXDATAV));
00237 MICROSD_USART->RXDOUBLE;
00238
00239
00240 MICROSD_USART->FRAME = framectrl;
00241 MICROSD_USART->CTRL = ctrl;
00242
00243 return 1;
00244 }
00245
00246
00252 #if _READONLY == 0
00253 int MICROSD_BlockTx(const uint8_t *buff, uint8_t token)
00254 {
00255 uint8_t resp;
00256 uint16_t val;
00257 uint32_t bc = 512;
00258 uint32_t framectrl, ctrl;
00259
00260 if (WaitReady() != 0xFF)
00261 {
00262 return 0;
00263 }
00264
00265 MICROSD_XferSpi(token);
00266
00267 if (token == 0xFD)
00268 {
00269
00270 return 1;
00271 }
00272
00273
00274 framectrl = MICROSD_USART->FRAME;
00275 ctrl = MICROSD_USART->CTRL;
00276
00277
00278 MICROSD_USART->FRAME = (MICROSD_USART->FRAME & (~_USART_FRAME_DATABITS_MASK))
00279 | USART_FRAME_DATABITS_SIXTEEN;
00280 MICROSD_USART->CTRL |= USART_CTRL_BYTESWAP;
00281
00282
00283 MICROSD_USART->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
00284
00285 if ( timeOut >= bc + 2 )
00286 {
00287 timeOut -= bc + 2;
00288 }
00289 else
00290 {
00291 timeOut = 0;
00292 }
00293
00294 do
00295 {
00296
00297
00298 val = *buff++;
00299 val |= *buff++ << 8;
00300 bc -= 2;
00301
00302 while (!(MICROSD_USART->STATUS & USART_STATUS_TXBL));
00303
00304 MICROSD_USART->TXDOUBLE = val;
00305 } while (bc);
00306
00307 while (!(MICROSD_USART->STATUS & USART_STATUS_TXBL));
00308
00309
00310 MICROSD_USART->TXDOUBLE = 0xFFFF;
00311
00312 while (!(MICROSD_USART->STATUS & USART_STATUS_TXC));
00313
00314
00315 MICROSD_USART->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
00316
00317
00318 MICROSD_USART->FRAME = framectrl;
00319 MICROSD_USART->CTRL = ctrl;
00320
00321 resp = MICROSD_XferSpi(0xff);
00322
00323 if ((resp & 0x1F) != 0x05)
00324 {
00325 return 0;
00326 }
00327
00328 return 1;
00329 }
00330 #endif
00331
00332
00342 uint8_t MICROSD_SendCmd(uint8_t cmd, DWORD arg)
00343 {
00344 uint8_t n, res;
00345 uint32_t retryCount;
00346
00347 if (cmd & 0x80)
00348 {
00349 cmd &= 0x7F;
00350 res = MICROSD_SendCmd(CMD55, 0);
00351 if (res > 1)
00352 {
00353 return res;
00354 }
00355 }
00356
00357
00358 MICROSD_Deselect();
00359 if (!MICROSD_Select())
00360 {
00361 return 0xFF;
00362 }
00363
00364
00365 MICROSD_XferSpi(0x40 | cmd);
00366 MICROSD_XferSpi((uint8_t)(arg >> 24));
00367 MICROSD_XferSpi((uint8_t)(arg >> 16));
00368 MICROSD_XferSpi((uint8_t)(arg >> 8));
00369 MICROSD_XferSpi((uint8_t) arg);
00370 n = 0x01;
00371 if (cmd == CMD0)
00372 {
00373 n = 0x95;
00374 }
00375 if (cmd == CMD8)
00376 {
00377 n = 0x87;
00378 }
00379 MICROSD_XferSpi(n);
00380
00381
00382 if (cmd == CMD12)
00383 {
00384 MICROSD_XferSpi(0xff);
00385 }
00386 retryCount = 10;
00387 do
00388 {
00389 res = MICROSD_XferSpi(0xff);
00390 } while ((res & 0x80) && --retryCount);
00391
00392 return res;
00393 }
00394
00395
00399 void MICROSD_SpiClkSlow(void)
00400 {
00401 USART_BaudrateSyncSet(MICROSD_USART, 0, MICROSD_LO_SPI_FREQ);
00402 xfersPrMsec = MICROSD_LO_SPI_FREQ / 8000;
00403 }
00404
00405
00408 void MICROSD_SpiClkFast(void)
00409 {
00410 USART_BaudrateSyncSet(MICROSD_USART, 0, MICROSD_HI_SPI_FREQ);
00411 xfersPrMsec = MICROSD_HI_SPI_FREQ / 8000;
00412 }
00413
00414
00422 void MICROSD_TimeOutSet(uint32_t msec)
00423 {
00424 timeOut = xfersPrMsec * msec;
00425 }
00426
00427
00433 bool MICROSD_TimeOutElapsed(void)
00434 {
00435 return timeOut == 0;
00436 }