microsd.c
Go to the documentation of this file.00001
00037 #include "diskio.h"
00038 #include "microsd.h"
00039 #include "em_cmu.h"
00040 #include "em_usart.h"
00041
00042
00048 static uint32_t timeOut, xfersPrMsec;
00049
00050
00054 static uint8_t WaitReady(void)
00055 {
00056 uint8_t res;
00057 uint32_t retryCount;
00058
00059
00060 retryCount = 500 * xfersPrMsec;
00061 do
00062 res = MICROSD_XferSpi(0xff);
00063 while ((res != 0xFF) && --retryCount);
00064
00065 return res;
00066 }
00069
00074 void MICROSD_Init(void)
00075 {
00076 USART_InitSync_TypeDef init = USART_INITSYNC_DEFAULT;
00077
00078
00079 CMU_ClockEnable(MICROSD_CMUCLOCK, true);
00080 CMU_ClockEnable(cmuClock_GPIO, true);
00081
00082
00083 xfersPrMsec = MICROSD_LO_SPI_FREQ / 8000;
00084 init.baudrate = MICROSD_LO_SPI_FREQ;
00085 init.msbf = true;
00086 USART_InitSync(MICROSD_USART, &init);
00087
00088
00089 MICROSD_USART->ROUTE = USART_ROUTE_TXPEN | USART_ROUTE_RXPEN |
00090 USART_ROUTE_CLKPEN | MICROSD_LOC;
00091
00092
00093 GPIO_PinModeSet(MICROSD_GPIOPORT, MICROSD_MOSIPIN, gpioModePushPull, 0);
00094 GPIO_PinModeSet(MICROSD_GPIOPORT, MICROSD_MISOPIN, gpioModeInputPull, 1);
00095 GPIO_PinModeSet(MICROSD_GPIOPORT, MICROSD_CSPIN, gpioModePushPull, 1);
00096 GPIO_PinModeSet(MICROSD_GPIOPORT, MICROSD_CLKPIN, gpioModePushPull, 0);
00097 }
00098
00099
00104 void MICROSD_Deinit(void)
00105 {
00106 USART_Reset(MICROSD_USART);
00107
00108
00109 GPIO_PinModeSet(MICROSD_GPIOPORT, MICROSD_MOSIPIN, gpioModeDisabled, 0);
00110 GPIO_PinModeSet(MICROSD_GPIOPORT, MICROSD_MISOPIN, gpioModeDisabled, 0);
00111 GPIO_PinModeSet(MICROSD_GPIOPORT, MICROSD_CSPIN, gpioModeDisabled, 0);
00112 GPIO_PinModeSet(MICROSD_GPIOPORT, MICROSD_CLKPIN, gpioModeDisabled, 0);
00113 }
00114
00115
00125 uint8_t MICROSD_XferSpi(uint8_t data)
00126 {
00127 if ( timeOut )
00128 timeOut--;
00129
00130 return USART_SpiTransfer(MICROSD_USART, data);
00131 }
00132
00133
00136 void MICROSD_Deselect(void)
00137 {
00138 GPIO->P[ MICROSD_GPIOPORT ].DOUTSET = 1 << MICROSD_CSPIN;
00139 MICROSD_XferSpi(0xff);
00140 }
00141
00142
00146 int MICROSD_Select(void)
00147 {
00148 GPIO->P[ MICROSD_GPIOPORT ].DOUTCLR = 1 << MICROSD_CSPIN;
00149 if (WaitReady() != 0xFF)
00150 {
00151 MICROSD_Deselect();
00152 return 0;
00153 }
00154 return 1;
00155 }
00156
00157
00161 void MICROSD_PowerOn(void)
00162 {
00163
00164 CMU_ClockEnable(MICROSD_CMUCLOCK, true);
00165 }
00166
00167
00171 void MICROSD_PowerOff(void)
00172 {
00173
00174 MICROSD_Select();
00175 MICROSD_Deselect();
00176
00177 CMU_ClockEnable(MICROSD_CMUCLOCK, false);
00178 }
00179
00180
00189 int MICROSD_BlockRx(uint8_t *buff, uint32_t btr)
00190 {
00191 uint8_t token;
00192 uint32_t retryCount, framectrl, ctrl;
00193 uint16_t *buff_16 = (uint16_t *) buff;
00194
00195
00196 retryCount = 100 * xfersPrMsec;
00197 do
00198 token = MICROSD_XferSpi(0xff);
00199 while ((token == 0xFF) && --retryCount);
00200
00201 if (token != 0xFE)
00202
00203 return 0;
00204
00205
00206 framectrl = MICROSD_USART->FRAME;
00207 ctrl = MICROSD_USART->CTRL;
00208
00209
00210
00211 MICROSD_USART->FRAME = (MICROSD_USART->FRAME & (~_USART_FRAME_DATABITS_MASK))
00212 | USART_FRAME_DATABITS_SIXTEEN;
00213 MICROSD_USART->CTRL |= USART_CTRL_BYTESWAP;
00214
00215
00216 MICROSD_USART->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
00217
00218 if ( timeOut >= btr + 2 )
00219 timeOut -= btr + 2;
00220 else
00221 timeOut = 0;
00222
00223
00224
00225
00226 MICROSD_USART->TXDOUBLE = 0xffff;
00227 do
00228 {
00229 MICROSD_USART->TXDOUBLE = 0xffff;
00230
00231 while (!(MICROSD_USART->STATUS & USART_STATUS_RXDATAV));
00232 *buff_16++ = (uint16_t) MICROSD_USART->RXDOUBLE;
00233
00234 btr -= 2;
00235 } while (btr);
00236
00237
00238 while (!(MICROSD_USART->STATUS & USART_STATUS_RXDATAV));
00239 MICROSD_USART->RXDOUBLE;
00240
00241
00242 MICROSD_USART->FRAME = framectrl;
00243 MICROSD_USART->CTRL = ctrl;
00244
00245 return 1;
00246 }
00247
00248
00254 #if _READONLY == 0
00255 int MICROSD_BlockTx(const uint8_t *buff, uint8_t token)
00256 {
00257 uint8_t resp;
00258 uint32_t bc = 512;
00259
00260 if (WaitReady() != 0xFF)
00261 return 0;
00262
00263 MICROSD_XferSpi(token);
00264 if (token != 0xFD)
00265 {
00266 do
00267 {
00268
00269 MICROSD_XferSpi(*buff++);
00270 MICROSD_XferSpi(*buff++);
00271 MICROSD_XferSpi(*buff++);
00272 MICROSD_XferSpi(*buff++);
00273 bc -= 4;
00274 } while (bc);
00275
00276 MICROSD_XferSpi(0xFF);
00277 MICROSD_XferSpi(0xFF);
00278 resp = MICROSD_XferSpi(0xff);
00279 if ((resp & 0x1F) != 0x05)
00280 return 0;
00281 }
00282 return 1;
00283 }
00284 #endif
00285
00286
00296 uint8_t MICROSD_SendCmd(uint8_t cmd, DWORD arg)
00297 {
00298 uint8_t n, res;
00299 uint32_t retryCount;
00300
00301 if (cmd & 0x80)
00302 {
00303 cmd &= 0x7F;
00304 res = MICROSD_SendCmd(CMD55, 0);
00305 if (res > 1) return res;
00306 }
00307
00308
00309 MICROSD_Deselect();
00310 if (!MICROSD_Select())
00311 return 0xFF;
00312
00313
00314 MICROSD_XferSpi(0x40 | cmd);
00315 MICROSD_XferSpi((uint8_t)(arg >> 24));
00316 MICROSD_XferSpi((uint8_t)(arg >> 16));
00317 MICROSD_XferSpi((uint8_t)(arg >> 8));
00318 MICROSD_XferSpi((uint8_t) arg);
00319 n = 0x01;
00320 if (cmd == CMD0)
00321 n = 0x95;
00322 if (cmd == CMD8)
00323 n = 0x87;
00324 MICROSD_XferSpi(n);
00325
00326
00327 if (cmd == CMD12)
00328 MICROSD_XferSpi(0xff);
00329 retryCount = 10;
00330 do
00331 res = MICROSD_XferSpi(0xff);
00332 while ((res & 0x80) && --retryCount);
00333
00334 return res;
00335 }
00336
00337
00341 void MICROSD_SpiClkSlow(void)
00342 {
00343 USART_BaudrateSyncSet(MICROSD_USART, 0, MICROSD_LO_SPI_FREQ);
00344 xfersPrMsec = MICROSD_LO_SPI_FREQ / 8000;
00345 }
00346
00347
00350 void MICROSD_SpiClkFast(void)
00351 {
00352 USART_BaudrateSyncSet(MICROSD_USART, 0, MICROSD_HI_SPI_FREQ);
00353 xfersPrMsec = MICROSD_HI_SPI_FREQ / 8000;
00354 }
00355
00356
00364 void MICROSD_TimeOutSet(uint32_t msec)
00365 {
00366 timeOut = xfersPrMsec * msec;
00367 }
00368
00369
00375 bool MICROSD_TimeOutElapsed(void)
00376 {
00377 return timeOut == 0;
00378 }