Contiki 2.5
sd.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009, Swedish Institute of Computer Science
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * SD driver implementation using SPI.
36  * \author
37  * Nicolas Tsiftes <nvt@sics.se>
38  */
39 
40 #include "contiki.h"
41 #include "sd.h"
42 #include "sd-arch.h"
43 
44 #include <string.h>
45 
46 #define DEBUG 0
47 #if DEBUG
48 #include <stdio.h>
49 #define PRINTF(...) printf(__VA_ARGS__)
50 #else
51 #define PRINTF(...)
52 #endif
53 
54 #ifndef MIN
55 #define MIN(a, b) ((a) < (b) ? (a) : (b))
56 #endif /* MIN */
57 
58 #define SPI_IDLE 0xff
59 
60 /* SD commands */
61 #define GO_IDLE_STATE 0
62 #define SEND_OP_COND 1
63 #define SWITCH_FUNC 6
64 #define SEND_IF_COND 8
65 #define SEND_CSD 9
66 #define SEND_CID 10
67 #define STOP_TRANSMISSION 12
68 #define SEND_STATUS 13
69 #define READ_SINGLE_BLOCK 17
70 #define WRITE_BLOCK 24
71 #define READ_OCR 58
72 
73 /* SD response lengths. */
74 #define R1 1
75 #define R2 2
76 #define R3 5
77 #define R7 5
78 
79 #define START_BLOCK_TOKEN 0xfe
80 
81 /* Status codes returned after writing a block. */
82 #define DATA_ACCEPTED 2
83 #define DATA_CRC_ERROR 5
84 #define DATA_WRITE_ERROR 6
85 
86 static uint16_t rw_block_size;
87 static uint16_t block_size;
88 
89 static int read_register(int register_cmd, char *buf, int register_size);
90 /*---------------------------------------------------------------------------*/
91 static int
92 send_command(uint8_t cmd, uint32_t argument)
93 {
94  uint8_t req[6];
95 
96  req[0] = 0x40 | cmd;
97  req[1] = argument >> 24;
98  req[2] = argument >> 16;
99  req[3] = argument >> 8;
100  req[4] = argument;
101  /* The CRC hard-wired to 0x95 is only needed for the initial
102  GO_IDLE_STATE command. */
103  req[5] = 0x95;
104 
105  sd_arch_spi_write(SPI_IDLE);
106  sd_arch_spi_write_block(req, sizeof(req));
107  sd_arch_spi_write(SPI_IDLE);
108 
109  return 0;
110 }
111 /*---------------------------------------------------------------------------*/
112 static uint8_t *
113 get_response(int length)
114 {
115  int i;
116  int x;
117  static uint8_t r[R7];
118 
119  for(i = 0; i < SD_READ_RESPONSE_ATTEMPTS; i++) {
120  x = sd_arch_spi_read();
121  if((x & 0x80) == 0) {
122  /* A get_response byte is indicated by the MSB being 0. */
123  r[0] = x;
124  break;
125  }
126  }
127 
128  if(i == SD_READ_RESPONSE_ATTEMPTS) {
129  return NULL;
130  }
131 
132  for(i = 1; i < length; i++) {
133  r[i] = sd_arch_spi_read();
134  }
135 
136  return r;
137 }
138 /*---------------------------------------------------------------------------*/
139 static unsigned char *
140 transaction(int command, unsigned long argument,
141  int response_type, unsigned attempts)
142 {
143  unsigned i;
144  unsigned char *r;
145 
146  LOCK_SPI();
147  r = NULL;
148  for(i = 0; i < attempts; i++) {
149  LOWER_CS();
150  send_command(command, argument);
151  r = get_response(response_type);
152  RAISE_CS();
153  if(r != NULL) {
154  break;
155  }
156  }
157  UNLOCK_SPI();
158 
159  return r;
160 }
161 /*---------------------------------------------------------------------------*/
162 int
163 sd_initialize(void)
164 {
165  unsigned char reg[16];
166  int i;
167  uint8_t *r, read_bl_len;
168 
169  if(sd_arch_init() < 0) {
170  return SD_INIT_ERROR_ARCH;
171  }
172 
173  if(SD_CONNECTED() < 0) {
174  return SD_INIT_ERROR_NO_CARD;
175  }
176 
177  r = transaction(GO_IDLE_STATE, 0, R1, SD_TRANSACTION_ATTEMPTS);
178  if(r != NULL) {
179  PRINTF("Go-idle result: %d\n", r[0]);
180  } else {
181  PRINTF("Failed to get go-idle response\n");
182  }
183 
184  r = transaction(SEND_IF_COND, 0, R7, SD_TRANSACTION_ATTEMPTS);
185  if(r != NULL) {
186  PRINTF("IF cond: %d %d %d %d %d\n", r[0], r[1], r[2], r[3], r[4]);
187  } else {
188  PRINTF("failed to get IF cond\n");
189  return SD_INIT_ERROR_NO_IF_COND;
190  }
191 
192  LOCK_SPI();
193 
194  for(i = 0; i < SD_TRANSACTION_ATTEMPTS; i++) {
195  LOWER_CS();
196  send_command(SEND_OP_COND, 0);
197  r = get_response(R1);
198  RAISE_CS();
199  if(r != NULL && !(r[0] & 1)) {
200  break;
201  }
202  }
203 
204  UNLOCK_SPI();
205 
206  if(r != NULL) {
207  PRINTF("OP cond: %d (%d iterations)\n", r[0], i);
208  } else {
209  PRINTF("Failed to get OP cond get_response\n");
210  }
211 
212  LOCK_SPI();
213 
214  for(i = 0; i < SD_TRANSACTION_ATTEMPTS; i++) {
215  LOWER_CS();
216  send_command(READ_OCR, 0);
217  r = get_response(R3);
218  RAISE_CS();
219  if(r != NULL) {
220  break;
221  }
222  }
223 
224  UNLOCK_SPI();
225 
226  if(r != NULL) {
227  PRINTF("OCR: %d %d %d %d %d\n", r[0], r[1], r[2], r[3], r[4]);
228  }
229 
230 
231  if(read_register(SEND_CSD, reg, sizeof(reg)) < 0) {
232  PRINTF("Failed to get block size of SD card\n");
233  return SD_INIT_ERROR_NO_BLOCK_SIZE;
234  }
235 
236  read_bl_len = reg[5] & 0x0f;
237  block_size = 1 << read_bl_len;
238  rw_block_size = (block_size > SD_DEFAULT_BLOCK_SIZE) ?
239  SD_DEFAULT_BLOCK_SIZE : block_size;
240  PRINTF("Found block size %d\n", block_size);
241 
242  /* XXX Arbitrary wait time here. Need to investigate why this is needed. */
243  MS_DELAY(5);
244 
245  return SD_OK;
246 }
247 /*---------------------------------------------------------------------------*/
248 int
249 sd_write_block(sd_offset_t offset, char *buf)
250 {
251  unsigned char *r;
252  int retval;
253  int i;
254  unsigned char data_response;
255  unsigned char status_code;
256 
257  LOCK_SPI();
258  r = NULL;
259  retval = SD_WRITE_ERROR_NO_CMD_RESPONSE;
260  for(i = 0; i < SD_TRANSACTION_ATTEMPTS; i++) {
261  LOWER_CS();
262  send_command(WRITE_BLOCK, offset);
263  r = get_response(R1);
264  if(r != NULL) {
265  break;
266  }
267  RAISE_CS();
268  }
269 
270  if(r != NULL && r[0] == 0) {
271  /* We received an R1 response with no errors.
272  Send a start block token to the card now. */
273  sd_arch_spi_write(START_BLOCK_TOKEN);
274 
275  /* Write the data block. */
276  sd_arch_spi_write_block(buf, rw_block_size);
277 
278  /* Get a response from the card. */
279  retval = SD_WRITE_ERROR_NO_BLOCK_RESPONSE;
280  for(i = 0; i < SD_TRANSACTION_ATTEMPTS; i++) {
281  data_response = sd_arch_spi_read();
282  if((data_response & 0x11) == 1) {
283  /* Data response token received. */
284  status_code = (data_response >> 1) & 0x7;
285  if(status_code == DATA_ACCEPTED) {
286  retval = rw_block_size;
287  } else {
288  retval = SD_WRITE_ERROR_PROGRAMMING;
289  }
290  break;
291  }
292  }
293  }
294 
295  RAISE_CS();
296  UNLOCK_SPI();
297 
298  return retval;
299 }
300 /*---------------------------------------------------------------------------*/
301 static int
302 read_block(unsigned read_cmd, sd_offset_t offset, char *buf, int len)
303 {
304  unsigned char *r;
305  int i;
306  int token;
307  int retval;
308 
309  LOCK_SPI();
310 
311  r = NULL;
312  for(i = 0; i < SD_TRANSACTION_ATTEMPTS; i++) {
313  LOWER_CS();
314  send_command(read_cmd, offset);
315  r = get_response(R1);
316  if(r != NULL) {
317  break;
318  }
319  RAISE_CS();
320  }
321 
322  if(r != NULL && r[0] == 0) {
323  /* We received an R1 response with no errors.
324  Get a token from the card now. */
325  for(i = 0; i < SD_TRANSACTION_ATTEMPTS; i++) {
326  token = sd_arch_spi_read();
327  if(token == START_BLOCK_TOKEN || (token > 0 && token <= 8)) {
328  break;
329  }
330  }
331 
332  if(token == START_BLOCK_TOKEN) {
333  /* A start block token has been received. Read the block now. */
334  for(i = 0; i < len; i++) {
335  buf[i] = sd_arch_spi_read();
336  }
337 
338  /* Consume CRC. TODO: Validate the block. */
339  sd_arch_spi_read();
340  sd_arch_spi_read();
341 
342  retval = len;
343  } else if(token > 0 && token <= 8) {
344  /* The card returned a data error token. */
345  retval = SD_READ_ERROR_TOKEN;
346  } else {
347  /* The card never returned a token after our read attempts. */
348  retval = SD_READ_ERROR_NO_TOKEN;
349  }
350 
351  RAISE_CS();
352  UNLOCK_SPI();
353  return retval;
354  }
355 
356  RAISE_CS();
357  UNLOCK_SPI();
358 
359  if(r != NULL) {
360  PRINTF("status during read: %d\n", r[0]);
361  }
362 
363  return SD_READ_ERROR_NO_CMD_RESPONSE;
364 }
365 /*---------------------------------------------------------------------------*/
366 int
367 sd_read_block(sd_offset_t offset, char *buf)
368 {
369  return read_block(READ_SINGLE_BLOCK, offset, buf, rw_block_size);
370 }
371 /*---------------------------------------------------------------------------*/
372 static int
373 read_register(int register_cmd, char *buf, int register_size)
374 {
375  return read_block(register_cmd, 0, buf, register_size);
376 }
377 /*---------------------------------------------------------------------------*/
378 sd_offset_t
379 sd_get_capacity(void)
380 {
381  unsigned char reg[16];
382  int r;
383  uint16_t c_size;
384  uint8_t c_size_mult;
385  sd_offset_t block_nr;
386  sd_offset_t mult;
387 
388  r = read_register(SEND_CSD, reg, sizeof(reg));
389  if(r < 0) {
390  return r;
391  }
392 
393  c_size = ((reg[6] & 3) << 10) + (reg[7] << 2) + ((reg[8] >> 6) & 3);
394  c_size_mult = ((reg[9] & 3) << 1) + ((reg[10] & 0x80) >> 7);
395  mult = 1 << (c_size_mult + 2);
396  block_nr = (c_size + 1) * mult;
397 
398  return block_nr * block_size;
399 }
400 /*---------------------------------------------------------------------------*/
401 char *
402 sd_error_string(int error_code)
403 {
404 #if DEBUG
405  switch(error_code) {
406  case SD_OK:
407  return "operation succeeded";
408  case SD_INIT_ERROR_NO_CARD:
409  return "no card was found";
410  case SD_INIT_ERROR_ARCH:
411  return "architecture-dependent initialization failed";
412  case SD_INIT_ERROR_NO_IF_COND:
413  return "unable to obtain the interface condition";
414  case SD_INIT_ERROR_NO_BLOCK_SIZE:
415  return "unable to obtain the block size";
416  case SD_WRITE_ERROR_NO_CMD_RESPONSE:
417  return "no response from the card after submitting a write request";
418  case SD_WRITE_ERROR_NO_BLOCK_RESPONSE:
419  return "no response from the card after sending a data block";
420  case SD_WRITE_ERROR_PROGRAMMING:
421  return "the write request failed because of a card error";
422  case SD_WRITE_ERROR_TOKEN:
423  return "the card is not ready to grant a write request";
424  case SD_READ_ERROR_NO_TOKEN:
425  case SD_WRITE_ERROR_NO_TOKEN:
426  return "did not receive a start block token";
427  case SD_READ_ERROR_INVALID_SIZE:
428  return "invalid read block size";
429  case SD_READ_ERROR_TOKEN:
430  return "the card is not ready to read a data block";
431  case SD_READ_ERROR_NO_CMD_RESPONSE:
432  return "no response from the card after submitting a read request";
433  default:
434  break;
435  }
436 #endif
437  return "unspecified error";
438 }
439 /*---------------------------------------------------------------------------*/
440 int
441 sd_write(sd_offset_t offset, char *buf, size_t size)
442 {
443  sd_offset_t address;
444  uint16_t offset_in_block;
445  int r, i;
446  size_t written;
447  size_t to_write;
448  char sd_buf[rw_block_size];
449 
450  /* Emulation of data writing using arbitrary offsets and chunk sizes. */
451  memset(sd_buf, 0, sizeof(sd_buf));
452  written = 0;
453  offset_in_block = offset & (rw_block_size - 1);
454 
455  do {
456  to_write = MIN(size - written, rw_block_size - offset_in_block);
457  address = (offset + written) & ~(rw_block_size - 1);
458 
459  for(i = 0; i < SD_READ_BLOCK_ATTEMPTS; i++) {
460  r = sd_read_block(address, sd_buf);
461  if(r == sizeof(sd_buf)) {
462  break;
463  }
464  }
465  if(r != sizeof(sd_buf)) {
466  return r;
467  }
468 
469  memcpy(&sd_buf[offset_in_block], &buf[written], to_write);
470  r = sd_write_block(address, sd_buf);
471  if(r != sizeof(sd_buf)) {
472  return r;
473  }
474  written += to_write;
475  offset_in_block = 0;
476  } while(written < size);
477 
478  return written;
479 }
480 /*---------------------------------------------------------------------------*/
481 int
482 sd_read(sd_offset_t offset, char *buf, size_t size)
483 {
484  size_t total_read;
485  size_t to_read;
486  char sd_buf[rw_block_size];
487  uint16_t offset_in_block;
488  int r, i;
489 
490  /* Emulation of data reading using arbitrary offsets and chunk sizes. */
491  total_read = 0;
492  offset_in_block = offset & (rw_block_size - 1);
493 
494  do {
495  to_read = MIN(size - total_read, rw_block_size - offset_in_block);
496  for(i = 0; i < SD_READ_BLOCK_ATTEMPTS; i++) {
497  r = sd_read_block((offset + total_read) & ~(rw_block_size - 1), sd_buf);
498  if(r == sizeof(sd_buf)) {
499  break;
500  }
501  }
502  if(r != sizeof(sd_buf)) {
503  return r;
504  }
505 
506  memcpy(&buf[total_read], &sd_buf[offset_in_block], to_read);
507  total_read += to_read;
508  offset_in_block = 0;
509  } while(total_read < size);
510 
511  return size;
512 }
513 /*---------------------------------------------------------------------------*/