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