Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2009, Swedish Institute of Computer Science 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * This file is part of the Contiki operating system. 00030 * 00031 */ 00032 00033 /** 00034 * \file 00035 * SD driver implementation using SPI. 00036 * \author 00037 * Nicolas Tsiftes <nvt@sics.se> 00038 */ 00039 00040 #include "contiki.h" 00041 #include "sd.h" 00042 #include "sd-arch.h" 00043 00044 #include <string.h> 00045 00046 #define DEBUG 0 00047 #if DEBUG 00048 #include <stdio.h> 00049 #define PRINTF(...) printf(__VA_ARGS__) 00050 #else 00051 #define PRINTF(...) 00052 #endif 00053 00054 #ifndef MIN 00055 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 00056 #endif /* MIN */ 00057 00058 #define SPI_IDLE 0xff 00059 00060 /* SD commands */ 00061 #define GO_IDLE_STATE 0 00062 #define SEND_OP_COND 1 00063 #define SWITCH_FUNC 6 00064 #define SEND_IF_COND 8 00065 #define SEND_CSD 9 00066 #define SEND_CID 10 00067 #define STOP_TRANSMISSION 12 00068 #define SEND_STATUS 13 00069 #define READ_SINGLE_BLOCK 17 00070 #define WRITE_BLOCK 24 00071 #define READ_OCR 58 00072 00073 /* SD response lengths. */ 00074 #define R1 1 00075 #define R2 2 00076 #define R3 5 00077 #define R7 5 00078 00079 #define START_BLOCK_TOKEN 0xfe 00080 00081 /* Status codes returned after writing a block. */ 00082 #define DATA_ACCEPTED 2 00083 #define DATA_CRC_ERROR 5 00084 #define DATA_WRITE_ERROR 6 00085 00086 static uint16_t rw_block_size; 00087 static uint16_t block_size; 00088 00089 static int read_register(int register_cmd, char *buf, int register_size); 00090 /*---------------------------------------------------------------------------*/ 00091 static int 00092 send_command(uint8_t cmd, uint32_t argument) 00093 { 00094 uint8_t req[6]; 00095 00096 req[0] = 0x40 | cmd; 00097 req[1] = argument >> 24; 00098 req[2] = argument >> 16; 00099 req[3] = argument >> 8; 00100 req[4] = argument; 00101 /* The CRC hard-wired to 0x95 is only needed for the initial 00102 GO_IDLE_STATE command. */ 00103 req[5] = 0x95; 00104 00105 sd_arch_spi_write(SPI_IDLE); 00106 sd_arch_spi_write_block(req, sizeof(req)); 00107 sd_arch_spi_write(SPI_IDLE); 00108 00109 return 0; 00110 } 00111 /*---------------------------------------------------------------------------*/ 00112 static uint8_t * 00113 get_response(int length) 00114 { 00115 int i; 00116 int x; 00117 static uint8_t r[R7]; 00118 00119 for(i = 0; i < SD_READ_RESPONSE_ATTEMPTS; i++) { 00120 x = sd_arch_spi_read(); 00121 if((x & 0x80) == 0) { 00122 /* A get_response byte is indicated by the MSB being 0. */ 00123 r[0] = x; 00124 break; 00125 } 00126 } 00127 00128 if(i == SD_READ_RESPONSE_ATTEMPTS) { 00129 return NULL; 00130 } 00131 00132 for(i = 1; i < length; i++) { 00133 r[i] = sd_arch_spi_read(); 00134 } 00135 00136 return r; 00137 } 00138 /*---------------------------------------------------------------------------*/ 00139 static unsigned char * 00140 transaction(int command, unsigned long argument, 00141 int response_type, unsigned attempts) 00142 { 00143 unsigned i; 00144 unsigned char *r; 00145 00146 LOCK_SPI(); 00147 r = NULL; 00148 for(i = 0; i < attempts; i++) { 00149 LOWER_CS(); 00150 send_command(command, argument); 00151 r = get_response(response_type); 00152 RAISE_CS(); 00153 if(r != NULL) { 00154 break; 00155 } 00156 } 00157 UNLOCK_SPI(); 00158 00159 return r; 00160 } 00161 /*---------------------------------------------------------------------------*/ 00162 int 00163 sd_initialize(void) 00164 { 00165 unsigned char reg[16]; 00166 int i; 00167 uint8_t *r, read_bl_len; 00168 00169 if(sd_arch_init() < 0) { 00170 return SD_INIT_ERROR_ARCH; 00171 } 00172 00173 if(SD_CONNECTED() < 0) { 00174 return SD_INIT_ERROR_NO_CARD; 00175 } 00176 00177 r = transaction(GO_IDLE_STATE, 0, R1, SD_TRANSACTION_ATTEMPTS); 00178 if(r != NULL) { 00179 PRINTF("Go-idle result: %d\n", r[0]); 00180 } else { 00181 PRINTF("Failed to get go-idle response\n"); 00182 } 00183 00184 r = transaction(SEND_IF_COND, 0, R7, SD_TRANSACTION_ATTEMPTS); 00185 if(r != NULL) { 00186 PRINTF("IF cond: %d %d %d %d %d\n", r[0], r[1], r[2], r[3], r[4]); 00187 } else { 00188 PRINTF("failed to get IF cond\n"); 00189 return SD_INIT_ERROR_NO_IF_COND; 00190 } 00191 00192 LOCK_SPI(); 00193 00194 for(i = 0; i < SD_TRANSACTION_ATTEMPTS; i++) { 00195 LOWER_CS(); 00196 send_command(SEND_OP_COND, 0); 00197 r = get_response(R1); 00198 RAISE_CS(); 00199 if(r != NULL && !(r[0] & 1)) { 00200 break; 00201 } 00202 } 00203 00204 UNLOCK_SPI(); 00205 00206 if(r != NULL) { 00207 PRINTF("OP cond: %d (%d iterations)\n", r[0], i); 00208 } else { 00209 PRINTF("Failed to get OP cond get_response\n"); 00210 } 00211 00212 LOCK_SPI(); 00213 00214 for(i = 0; i < SD_TRANSACTION_ATTEMPTS; i++) { 00215 LOWER_CS(); 00216 send_command(READ_OCR, 0); 00217 r = get_response(R3); 00218 RAISE_CS(); 00219 if(r != NULL) { 00220 break; 00221 } 00222 } 00223 00224 UNLOCK_SPI(); 00225 00226 if(r != NULL) { 00227 PRINTF("OCR: %d %d %d %d %d\n", r[0], r[1], r[2], r[3], r[4]); 00228 } 00229 00230 00231 if(read_register(SEND_CSD, reg, sizeof(reg)) < 0) { 00232 PRINTF("Failed to get block size of SD card\n"); 00233 return SD_INIT_ERROR_NO_BLOCK_SIZE; 00234 } 00235 00236 read_bl_len = reg[5] & 0x0f; 00237 block_size = 1 << read_bl_len; 00238 rw_block_size = (block_size > SD_DEFAULT_BLOCK_SIZE) ? 00239 SD_DEFAULT_BLOCK_SIZE : block_size; 00240 PRINTF("Found block size %d\n", block_size); 00241 00242 /* XXX Arbitrary wait time here. Need to investigate why this is needed. */ 00243 MS_DELAY(5); 00244 00245 return SD_OK; 00246 } 00247 /*---------------------------------------------------------------------------*/ 00248 int 00249 sd_write_block(sd_offset_t offset, char *buf) 00250 { 00251 unsigned char *r; 00252 int retval; 00253 int i; 00254 unsigned char data_response; 00255 unsigned char status_code; 00256 00257 LOCK_SPI(); 00258 r = NULL; 00259 retval = SD_WRITE_ERROR_NO_CMD_RESPONSE; 00260 for(i = 0; i < SD_TRANSACTION_ATTEMPTS; i++) { 00261 LOWER_CS(); 00262 send_command(WRITE_BLOCK, offset); 00263 r = get_response(R1); 00264 if(r != NULL) { 00265 break; 00266 } 00267 RAISE_CS(); 00268 } 00269 00270 if(r != NULL && r[0] == 0) { 00271 /* We received an R1 response with no errors. 00272 Send a start block token to the card now. */ 00273 sd_arch_spi_write(START_BLOCK_TOKEN); 00274 00275 /* Write the data block. */ 00276 sd_arch_spi_write_block(buf, rw_block_size); 00277 00278 /* Get a response from the card. */ 00279 retval = SD_WRITE_ERROR_NO_BLOCK_RESPONSE; 00280 for(i = 0; i < SD_TRANSACTION_ATTEMPTS; i++) { 00281 data_response = sd_arch_spi_read(); 00282 if((data_response & 0x11) == 1) { 00283 /* Data response token received. */ 00284 status_code = (data_response >> 1) & 0x7; 00285 if(status_code == DATA_ACCEPTED) { 00286 retval = rw_block_size; 00287 } else { 00288 retval = SD_WRITE_ERROR_PROGRAMMING; 00289 } 00290 break; 00291 } 00292 } 00293 } 00294 00295 RAISE_CS(); 00296 UNLOCK_SPI(); 00297 00298 return retval; 00299 } 00300 /*---------------------------------------------------------------------------*/ 00301 static int 00302 read_block(unsigned read_cmd, sd_offset_t offset, char *buf, int len) 00303 { 00304 unsigned char *r; 00305 int i; 00306 int token; 00307 int retval; 00308 00309 LOCK_SPI(); 00310 00311 r = NULL; 00312 for(i = 0; i < SD_TRANSACTION_ATTEMPTS; i++) { 00313 LOWER_CS(); 00314 send_command(read_cmd, offset); 00315 r = get_response(R1); 00316 if(r != NULL) { 00317 break; 00318 } 00319 RAISE_CS(); 00320 } 00321 00322 if(r != NULL && r[0] == 0) { 00323 /* We received an R1 response with no errors. 00324 Get a token from the card now. */ 00325 for(i = 0; i < SD_TRANSACTION_ATTEMPTS; i++) { 00326 token = sd_arch_spi_read(); 00327 if(token == START_BLOCK_TOKEN || (token > 0 && token <= 8)) { 00328 break; 00329 } 00330 } 00331 00332 if(token == START_BLOCK_TOKEN) { 00333 /* A start block token has been received. Read the block now. */ 00334 for(i = 0; i < len; i++) { 00335 buf[i] = sd_arch_spi_read(); 00336 } 00337 00338 /* Consume CRC. TODO: Validate the block. */ 00339 sd_arch_spi_read(); 00340 sd_arch_spi_read(); 00341 00342 retval = len; 00343 } else if(token > 0 && token <= 8) { 00344 /* The card returned a data error token. */ 00345 retval = SD_READ_ERROR_TOKEN; 00346 } else { 00347 /* The card never returned a token after our read attempts. */ 00348 retval = SD_READ_ERROR_NO_TOKEN; 00349 } 00350 00351 RAISE_CS(); 00352 UNLOCK_SPI(); 00353 return retval; 00354 } 00355 00356 RAISE_CS(); 00357 UNLOCK_SPI(); 00358 00359 if(r != NULL) { 00360 PRINTF("status during read: %d\n", r[0]); 00361 } 00362 00363 return SD_READ_ERROR_NO_CMD_RESPONSE; 00364 } 00365 /*---------------------------------------------------------------------------*/ 00366 int 00367 sd_read_block(sd_offset_t offset, char *buf) 00368 { 00369 return read_block(READ_SINGLE_BLOCK, offset, buf, rw_block_size); 00370 } 00371 /*---------------------------------------------------------------------------*/ 00372 static int 00373 read_register(int register_cmd, char *buf, int register_size) 00374 { 00375 return read_block(register_cmd, 0, buf, register_size); 00376 } 00377 /*---------------------------------------------------------------------------*/ 00378 sd_offset_t 00379 sd_get_capacity(void) 00380 { 00381 unsigned char reg[16]; 00382 int r; 00383 uint16_t c_size; 00384 uint8_t c_size_mult; 00385 sd_offset_t block_nr; 00386 sd_offset_t mult; 00387 00388 r = read_register(SEND_CSD, reg, sizeof(reg)); 00389 if(r < 0) { 00390 return r; 00391 } 00392 00393 c_size = ((reg[6] & 3) << 10) + (reg[7] << 2) + ((reg[8] >> 6) & 3); 00394 c_size_mult = ((reg[9] & 3) << 1) + ((reg[10] & 0x80) >> 7); 00395 mult = 1 << (c_size_mult + 2); 00396 block_nr = (c_size + 1) * mult; 00397 00398 return block_nr * block_size; 00399 } 00400 /*---------------------------------------------------------------------------*/ 00401 char * 00402 sd_error_string(int error_code) 00403 { 00404 #if DEBUG 00405 switch(error_code) { 00406 case SD_OK: 00407 return "operation succeeded"; 00408 case SD_INIT_ERROR_NO_CARD: 00409 return "no card was found"; 00410 case SD_INIT_ERROR_ARCH: 00411 return "architecture-dependent initialization failed"; 00412 case SD_INIT_ERROR_NO_IF_COND: 00413 return "unable to obtain the interface condition"; 00414 case SD_INIT_ERROR_NO_BLOCK_SIZE: 00415 return "unable to obtain the block size"; 00416 case SD_WRITE_ERROR_NO_CMD_RESPONSE: 00417 return "no response from the card after submitting a write request"; 00418 case SD_WRITE_ERROR_NO_BLOCK_RESPONSE: 00419 return "no response from the card after sending a data block"; 00420 case SD_WRITE_ERROR_PROGRAMMING: 00421 return "the write request failed because of a card error"; 00422 case SD_WRITE_ERROR_TOKEN: 00423 return "the card is not ready to grant a write request"; 00424 case SD_READ_ERROR_NO_TOKEN: 00425 case SD_WRITE_ERROR_NO_TOKEN: 00426 return "did not receive a start block token"; 00427 case SD_READ_ERROR_INVALID_SIZE: 00428 return "invalid read block size"; 00429 case SD_READ_ERROR_TOKEN: 00430 return "the card is not ready to read a data block"; 00431 case SD_READ_ERROR_NO_CMD_RESPONSE: 00432 return "no response from the card after submitting a read request"; 00433 default: 00434 break; 00435 } 00436 #endif 00437 return "unspecified error"; 00438 } 00439 /*---------------------------------------------------------------------------*/ 00440 int 00441 sd_write(sd_offset_t offset, char *buf, size_t size) 00442 { 00443 sd_offset_t address; 00444 uint16_t offset_in_block; 00445 int r, i; 00446 size_t written; 00447 size_t to_write; 00448 char sd_buf[rw_block_size]; 00449 00450 /* Emulation of data writing using arbitrary offsets and chunk sizes. */ 00451 memset(sd_buf, 0, sizeof(sd_buf)); 00452 written = 0; 00453 offset_in_block = offset & (rw_block_size - 1); 00454 00455 do { 00456 to_write = MIN(size - written, rw_block_size - offset_in_block); 00457 address = (offset + written) & ~(rw_block_size - 1); 00458 00459 for(i = 0; i < SD_READ_BLOCK_ATTEMPTS; i++) { 00460 r = sd_read_block(address, sd_buf); 00461 if(r == sizeof(sd_buf)) { 00462 break; 00463 } 00464 } 00465 if(r != sizeof(sd_buf)) { 00466 return r; 00467 } 00468 00469 memcpy(&sd_buf[offset_in_block], &buf[written], to_write); 00470 r = sd_write_block(address, sd_buf); 00471 if(r != sizeof(sd_buf)) { 00472 return r; 00473 } 00474 written += to_write; 00475 offset_in_block = 0; 00476 } while(written < size); 00477 00478 return written; 00479 } 00480 /*---------------------------------------------------------------------------*/ 00481 int 00482 sd_read(sd_offset_t offset, char *buf, size_t size) 00483 { 00484 size_t total_read; 00485 size_t to_read; 00486 char sd_buf[rw_block_size]; 00487 uint16_t offset_in_block; 00488 int r, i; 00489 00490 /* Emulation of data reading using arbitrary offsets and chunk sizes. */ 00491 total_read = 0; 00492 offset_in_block = offset & (rw_block_size - 1); 00493 00494 do { 00495 to_read = MIN(size - total_read, rw_block_size - offset_in_block); 00496 for(i = 0; i < SD_READ_BLOCK_ATTEMPTS; i++) { 00497 r = sd_read_block((offset + total_read) & ~(rw_block_size - 1), sd_buf); 00498 if(r == sizeof(sd_buf)) { 00499 break; 00500 } 00501 } 00502 if(r != sizeof(sd_buf)) { 00503 return r; 00504 } 00505 00506 memcpy(&buf[total_read], &sd_buf[offset_in_block], to_read); 00507 total_read += to_read; 00508 offset_in_block = 0; 00509 } while(total_read < size); 00510 00511 return size; 00512 } 00513 /*---------------------------------------------------------------------------*/