sd_spi.c
Go to the documentation of this file.
00001
00038 #include "hw/hw_sd.h"
00039 #include "cfg/cfg_sd.h"
00040
00041 #include <io/kfile.h>
00042 #include <io/kblock.h>
00043
00044 #include <drv/sd.h>
00045 #include <drv/timer.h>
00046
00047 #include <fs/fat.h>
00048
00049 #define LOG_LEVEL  SD_LOG_LEVEL
00050 #define LOG_FORMAT SD_LOG_FORMAT
00051 #include <cfg/log.h>
00052 #include <cpu/power.h>
00053
00054 #include <string.h> /* memset */
00055
00056
00057 struct SdHardware
00058 {
00059     uint16_t tranfer_len;
00060 };
00061
00062
00063 #define SD_IN_IDLE    0x01
00064 #define SD_STARTTOKEN 0xFE
00065 
00066 #define TIMEOUT_NAC   16384
00067 #define SD_BUSY_TIMEOUT ms_to_ticks(200)
00068 
00069 static bool sd_select(Sd *sd, bool state)
00070 {
00071     KFile *fd = sd->ch;
00072
00073     if (state)
00074     {
00075         SD_CS_ON();
00076
00077         ticks_t start = timer_clock();
00078         do
00079         {
00080             if (kfile_getc(fd) == 0xff)
00081                 return true;
00082
00083             cpu_relax();
00084         }
00085         while (timer_clock() - start < SD_BUSY_TIMEOUT);
00086
00087         SD_CS_OFF();
00088         LOG_ERR("sd_select timeout\n");
00089         return false;
00090     }
00091     else
00092     {
00093         kfile_putc(0xff, fd);
00094         kfile_flush(fd);
00095         SD_CS_OFF();
00096         return true;
00097     }
00098 }
00099
00100 static int16_t sd_waitR1(Sd *sd)
00101 {
00102     uint8_t datain;
00103
00104     for (int i = 0; i < TIMEOUT_NAC; i++)
00105     {
00106         datain = kfile_getc(sd->ch);
00107         if (datain != 0xff)
00108             return (int16_t)datain;
00109     }
00110     LOG_ERR("Timeout waiting R1\n");
00111     return EOF;
00112 }
00113
00114 static int16_t sd_sendCommand(Sd *sd, uint8_t cmd, uint32_t param, uint8_t crc)
00115 {
00116     KFile *fd = sd->ch;
00117     /* The 7th bit of command must be a 1 */
00118     kfile_putc(cmd | 0x40, fd);
00119
00120     /* send parameter */
00121     kfile_putc((param >> 24) & 0xFF, fd);
00122     kfile_putc((param >> 16) & 0xFF, fd);
00123     kfile_putc((param >> 8) & 0xFF, fd);
00124     kfile_putc((param) & 0xFF, fd);
00125
00126     kfile_putc(crc, fd);
00127
00128     return sd_waitR1(sd);
00129 }
00130
00131 static bool sd_getBlock(Sd *sd, void *buf, size_t len)
00132 {
00133     uint8_t token;
00134     uint16_t crc;
00135
00136     KFile *fd = sd->ch;
00137
00138     for (int i = 0; i < TIMEOUT_NAC; i++)
00139     {
00140         token = kfile_getc(fd);
00141         if (token != 0xff)
00142         {
00143             if (token == SD_STARTTOKEN)
00144             {
00145                 if (kfile_read(fd, buf, len) == len)
00146                 {
00147                     if (kfile_read(fd, &crc, sizeof(crc)) == sizeof(crc))
00148                         /* check CRC here if needed */
00149                         return true;
00150                     else
00151                         LOG_ERR("get_block error getting crc\n");
00152                 }
00153                 else
00154                     LOG_ERR("get_block len error: %d\n", (int)len);
00155             }
00156             else
00157                 LOG_ERR("get_block token error: %02X\n", token);
00158
00159             return false;
00160         }
00161     }
00162
00163     LOG_ERR("get_block timeout waiting token\n");
00164     return false;
00165 }
00166
00167 #define SD_SELECT(sd) \
00168 do \
00169 { \
00170     if (!sd_select((sd), true)) \
00171     { \
00172         LOG_ERR("%s failed, card busy\n", __func__); \
00173         return EOF; \
00174     } \
00175 } \
00176 while (0)
00177 
00178 #define SD_SETBLOCKLEN 0x50
00179 
00180 static int16_t sd_setBlockLen(Sd *sd, uint32_t newlen)
00181 {
00182     SD_SELECT(sd);
00183
00184     sd->status = sd_sendCommand(sd, SD_SETBLOCKLEN, newlen, 0);
00185
00186     sd_select(sd, false);
00187     return sd->status;
00188 }
00189
00190 #define SD_SEND_CSD 0x49
00191 
00192 static int16_t sd_getCSD(Sd *sd, SdCSD *csd)
00193 {
00194     SD_SELECT(sd);
00195
00196     int16_t r1 = sd_sendCommand(sd, SD_SEND_CSD, 0, 0);
00197
00198     if (r1)
00199     {
00200         LOG_ERR("send_csd failed: %08lX\n", sd->status);
00201         sd_select(sd, false);
00202         return r1;
00203     }
00204
00205     uint8_t buf[16];
00206     bool res = sd_getBlock(sd, buf, sizeof(buf));
00207     sd_select(sd, false);
00208
00209     if (res)
00210     {
00211         #if LOG_LEVEL >= LOG_LVL_INFO
00212             LOG_INFO("CSD: [");
00213             for (int i = 0; i < 16; i++)
00214                 kprintf("%02X ", buf[i]);
00215             kprintf("]\n");
00216         #endif
00217 
00218         uint16_t mult = (1L << ((((buf[9] & 0x03) << 1) | ((buf[10] & 0x80) >> 7)) + 2));
00219         uint16_t c_size = (((uint16_t)(buf[6] & 0x03)) << 10) | (((uint16_t)buf[7]) << 2) |
00220                   (((uint16_t)(buf[8] & 0xC0)) >> 6);
00221
00222         csd->block_len = (1L << (buf[5] & 0x0F));
00223         csd->block_num = (c_size + 1) * mult;
00224         csd->capacity = (csd->block_len * csd->block_num) >> 20; // in MB
00225
00226         LOG_INFO("block_len %d bytes, block_num %ld, total capacity %dMB\n", csd->block_len, csd->block_num, csd->capacity);
00227         return 0;
00228     }
00229     else
00230         return EOF;
00231 }
00232
00233 #define SD_START_DELAY  10
00234 #define SD_INIT_TIMEOUT ms_to_ticks(2000)
00235 #define SD_IDLE_RETRIES 4
00236 #define SD_READ_SINGLEBLOCK 0x51
00237 
00238 static size_t sd_SpiReadDirect(struct KBlock *b, block_idx_t idx, void *buf, size_t offset, size_t size)
00239 {
00240
00241     Sd *sd = SD_CAST(b);
00242     LOG_INFO("reading from block %ld, offset %d, size %d\n", idx, offset, size);
00243
00244     if (sd->hw->tranfer_len != size)
00245     {
00246         if ((sd->status = sd_setBlockLen(sd, size)))
00247         {
00248             LOG_ERR("setBlockLen failed: %08lX\n", sd->status);
00249             return 0;
00250         }
00251         sd->hw->tranfer_len = size;
00252     }
00253
00254     SD_SELECT(sd);
00255
00256     sd->status = sd_sendCommand(sd, SD_READ_SINGLEBLOCK, idx * SD_DEFAULT_BLOCKLEN + offset, 0);
00257
00258     if (sd->status)
00259     {
00260         LOG_ERR("read single block failed: %08lX\n", sd->status);
00261         sd_select(sd, false);
00262         return 0;
00263     }
00264
00265     bool res = sd_getBlock(sd, buf, size);
00266     sd_select(sd, false);
00267     if (!res)
00268     {
00269         LOG_ERR("read single block failed reading data\n");
00270         return 0;
00271     }
00272     else
00273         return size;
00274 }
00275
00276 #define SD_WRITE_SINGLEBLOCK 0x58
00277 #define SD_DATA_ACCEPTED     0x05
00278 
00279 static size_t sd_SpiWriteDirect(KBlock *b, block_idx_t idx, const void *buf, size_t offset, size_t size)
00280 {
00281     Sd *sd = SD_CAST(b);
00282     KFile *fd = sd->ch;
00283     ASSERT(offset == 0);
00284     ASSERT(size == SD_DEFAULT_BLOCKLEN);
00285
00286     LOG_INFO("writing block %ld\n", idx);
00287     if (sd->hw->tranfer_len != SD_DEFAULT_BLOCKLEN)
00288     {
00289         if ((sd->status = sd_setBlockLen(sd, SD_DEFAULT_BLOCKLEN)))
00290         {
00291             LOG_ERR("setBlockLen failed: %08lX\n", sd->status);
00292             return 0;
00293         }
00294         sd->hw->tranfer_len = SD_DEFAULT_BLOCKLEN;
00295     }
00296
00297     SD_SELECT(sd);
00298
00299     sd->status = sd_sendCommand(sd, SD_WRITE_SINGLEBLOCK, idx * SD_DEFAULT_BLOCKLEN, 0);
00300
00301     if (sd->status)
00302     {
00303         LOG_ERR("write single block failed: %08lX\n", sd->status);
00304         sd_select(sd, false);
00305         return 0;
00306     }
00307
00308     kfile_putc(SD_STARTTOKEN, fd);
00309     kfile_write(fd, buf, SD_DEFAULT_BLOCKLEN);
00310     /* send fake crc */
00311     kfile_putc(0, fd);
00312     kfile_putc(0, fd);
00313
00314     uint8_t dataresp = kfile_getc(fd);
00315     sd_select(sd, false);
00316
00317     if ((dataresp & 0x1f) != SD_DATA_ACCEPTED)
00318     {
00319         LOG_ERR("write block %ld failed: %02X\n", idx, dataresp);
00320         return EOF;
00321     }
00322
00323     return SD_DEFAULT_BLOCKLEN;
00324 }
00325
00326 static int sd_SpiError(KBlock *b)
00327 {
00328     Sd *sd = SD_CAST(b);
00329     return sd->status;
00330 }
00331
00332 static void sd_SpiClearerr(KBlock *b)
00333 {
00334     Sd *sd = SD_CAST(b);
00335     sd->status = 0;
00336 }
00337
00338
00339
00340 #define SD_GO_IDLE_STATE     0x40
00341 #define SD_GO_IDLE_STATE_CRC 0x95
00342 #define SD_SEND_OP_COND      0x41
00343 #define SD_SEND_OP_COND_CRC  0xF9
00344 
00345 static bool sd_blockInit(Sd *sd, KFile *ch)
00346 {
00347     ASSERT(sd);
00348     ASSERT(ch);
00349     memset(sd, 0, sizeof(*sd));
00350     DB(sd->b.priv.type = KBT_SD);
00351
00352     sd->ch = ch;
00353
00354     SD_CS_INIT();
00355     SD_CS_OFF();
00356
00357     /* Wait a few moments for supply voltage to stabilize */
00358     timer_delay(SD_START_DELAY);
00359
00360     /* Give 80 clk pulses to wake up the card */
00361     for (int i = 0; i < 10; i++)
00362         kfile_putc(0xff, ch);
00363     kfile_flush(ch);
00364
00365     for (int i = 0; i < SD_IDLE_RETRIES; i++)
00366     {
00367         SD_SELECT(sd);
00368         sd->status = sd_sendCommand(sd, SD_GO_IDLE_STATE, 0, SD_GO_IDLE_STATE_CRC);
00369         sd_select(sd, false);
00370
00371         if (sd->status == SD_IN_IDLE)
00372             break;
00373     }
00374
00375     if (sd->status != SD_IN_IDLE)
00376     {
00377         LOG_ERR("go_idle_state failed: %08lX\n", sd->status);
00378         return false;
00379     }
00380
00381     ticks_t start = timer_clock();
00382
00383     /* Wait for card to start */
00384     do
00385     {
00386         SD_SELECT(sd);
00387         sd->status = sd_sendCommand(sd, SD_SEND_OP_COND, 0, SD_SEND_OP_COND_CRC);
00388         sd_select(sd, false);
00389         cpu_relax();
00390     }
00391     while (sd->status != 0 && timer_clock() - start < SD_INIT_TIMEOUT);
00392
00393     if (sd->status)
00394     {
00395         LOG_ERR("send_op_cond failed: %08lX\n", sd->status);
00396         return false;
00397     }
00398
00399     sd->status = sd_setBlockLen(sd, SD_DEFAULT_BLOCKLEN);
00400     sd->hw->tranfer_len = SD_DEFAULT_BLOCKLEN;
00401
00402     if (sd->status)
00403     {
00404         LOG_ERR("setBlockLen failed: %08lX\n", sd->status);
00405         return false;
00406     }
00407
00408     /* Avoid warning for uninitialized csd use (gcc bug?) */
00409     SdCSD csd = csd;
00410
00411     sd->status = sd_getCSD(sd, &csd);
00412
00413     if (sd->status)
00414     {
00415         LOG_ERR("getCSD failed: %08lX\n", sd->status);
00416         return false;
00417     }
00418
00419     sd->b.blk_size = SD_DEFAULT_BLOCKLEN;
00420     sd->b.blk_cnt = csd.block_num * (csd.block_len / SD_DEFAULT_BLOCKLEN);
00421     LOG_INFO("blk_size %d, blk_cnt %ld\n", sd->b.blk_size, sd->b.blk_cnt);
00422
00423 #if CONFIG_SD_AUTOASSIGN_FAT
00424     disk_assignDrive(&sd->b, 0);
00425 #endif
00426 
00427     return true;
00428 }
00429
00430 static const KBlockVTable sd_unbuffered_vt =
00431 {
00432     .readDirect = sd_SpiReadDirect,
00433     .writeDirect = sd_SpiWriteDirect,
00434
00435     .error = sd_SpiError,
00436     .clearerr = sd_SpiClearerr,
00437 };
00438
00439 static const KBlockVTable sd_buffered_vt =
00440 {
00441     .readDirect = sd_SpiReadDirect,
00442     .writeDirect = sd_SpiWriteDirect,
00443
00444     .readBuf = kblock_swReadBuf,
00445     .writeBuf = kblock_swWriteBuf,
00446     .load = kblock_swLoad,
00447     .store = kblock_swStore,
00448
00449     .error = sd_SpiError,
00450     .clearerr = sd_SpiClearerr,
00451 };
00452
00453 struct SdHardware sd_spi_hw;
00454
00455 bool sd_spi_initUnbuf(Sd *sd, KFile *ch)
00456 {
00457     if (sd_blockInit(sd, ch))
00458     {
00459         sd->b.priv.vt = &sd_unbuffered_vt;
00460         sd->hw = &sd_spi_hw;
00461         return true;
00462     }
00463     else
00464         return false;
00465 }
00466
00467 static uint8_t sd_buf[SD_DEFAULT_BLOCKLEN];
00468
00469 bool sd_spi_initBuf(Sd *sd, KFile *ch)
00470 {
00471     if (sd_blockInit(sd, ch))
00472     {
00473         sd->b.priv.buf = sd_buf;
00474         sd->b.priv.flags |= KB_BUFFERED | KB_PARTIAL_WRITE;
00475         sd->b.priv.vt = &sd_buffered_vt;
00476         sd->b.priv.vt->load(&sd->b, 0);
00477         sd->hw = &sd_spi_hw;
00478         return true;
00479     }
00480     else
00481         return false;
00482 }
00483
00484