Contiki 2.6

sd.c

Go to the documentation of this file.
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 /*---------------------------------------------------------------------------*/