Contiki 2.5
flash-microSD.c
Go to the documentation of this file.
1 /* Copyright (c) 2010, Ulf Kulau
2  *
3  * Permission is hereby granted, free of charge, to any person
4  * obtaining a copy of this software and associated documentation
5  * files (the "Software"), to deal in the Software without
6  * restriction, including without limitation the rights to use,
7  * copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following
10  * conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 /**
26  * \addtogroup Device Interfaces
27  * @{
28  *
29  * \addtogroup microSD_interface
30  * @{
31  */
32 
33 /**
34  * \file
35  * MicroSD Card interface implementation
36  * \author
37  * Original source: Ulrich Radig
38  * << modified by >>
39  * Ulf Kulau <kulau@ibr.cs.tu-bs.de>
40  *
41  */
42 
43 #include "flash-microSD.h"
44 
45 uint8_t microSD_init(void) {
46  uint16_t i;
47  /*set pin for mcro sd card power switch to output*/
48  MICRO_SD_PWR_PORT_DDR |= (1 << MICRO_SD_PWR_PIN);
49  /*switch off the sd card and tri state buffer whenever this is not done
50  *to avoid initialization failures */
51  microSD_deinit();
52  /*switch on the SD card and the tri state buffer*/
53  MICRO_SD_PWR_PORT |= (1 << MICRO_SD_PWR_PIN);
54  /*READY TO INITIALIZE micro SD / SD card*/
56  /*init mspi in mode0, at chip select pin 2 and max baud rate*/
58  /*set SPI mode by chip select (only necessary when mspi manager is active)*/
59 
62  /*wait 1ms before initialize sd card*/
63  _delay_ms(1);
64  /*send >74 clock cycles to setup spi-mode*/
65  for (i = 0; i < 16; i++) {
66  mspi_transceive(MSPI_DUMMY_BYTE);
67  }
68  /*CMD0: set sd card to idle state*/
69  uint8_t cmd[6] = { 0x40, 0x00, 0x00, 0x00, 0x00, 0x95 };
70  i = 0;
71  while (microSD_write_cmd(&cmd[0]) != 0x01) {
72  i++;
73  if (i > 200) {
75  microSD_deinit();
76  return 1;
77  }
78  }
79  i = 0;
80  /*prepare next 6 data bytes: CMD1*/
81  cmd[0] = 0x41;
82  cmd[5] = 0xFF;
83  while (microSD_write_cmd(&cmd[0]) != 0) {
84  i++;
85  if (i > 500) {
87  microSD_deinit();
88  return 2;
89  }
90  }
92  return 0;
93 }
94 
95 uint8_t microSD_read_block(uint32_t addr, uint8_t *buffer) {
96  uint16_t i;
97  /*CMD17 read block*/
98  uint8_t cmd[6] = { 0x51, 0x00, 0x00, 0x00, 0x00, 0xff };
99  /*calculate the start address: block_addr = addr * 512*/
100  addr = addr << 9;
101  /*create cmd bytes according to the address*/
102  cmd[1] = ((addr & 0xFF000000) >> 24);
103  cmd[2] = ((addr & 0x00FF0000) >> 16);
104  cmd[3] = ((addr & 0x0000FF00) >> 8);
105 
106  /* send CMD17 with address information. Chip select is done by
107  * the microSD_write_cmd method and */
108  if (microSD_write_cmd(&cmd[0]) != 0x00) {
109 #if DEBUG
110  printf("\nCMD17 failure!");
111 #endif
112  return 1;
113  }
114 
115  /*wait for the 0xFE start byte*/
116  while (mspi_transceive(MSPI_DUMMY_BYTE) != 0xFE) {
117  };
118 
119  for (i = 0; i < 512; i++) {
120  *buffer++ = mspi_transceive(MSPI_DUMMY_BYTE);
121  }
122  /*CRC-Byte: don't care*/
123  mspi_transceive(MSPI_DUMMY_BYTE);
124  mspi_transceive(MSPI_DUMMY_BYTE);
125 
126  /*release chip select and disable microSD spi*/
128 
129  return 0;
130 }
131 
132 uint8_t microSD_deinit(void) {
133  MICRO_SD_PWR_PORT &= ~(1 << MICRO_SD_PWR_PIN);
134  return 0;
135 }
136 
137 uint8_t microSD_write_block(uint32_t addr, uint8_t *buffer) {
138  uint16_t i;
139  /*CMD24 write block*/
140  uint8_t cmd[6] = { 0x58, 0x00, 0x00, 0x00, 0x00, 0xFF };
141 
142  /*calculate the start address: block_addr = addr * 512*/
143  addr = addr << 9;
144  /*create cmd bytes according to the address*/
145  cmd[1] = ((addr & 0xFF000000) >> 24);
146  cmd[2] = ((addr & 0x00FF0000) >> 16);
147  cmd[3] = ((addr & 0x0000FF00) >> 8);
148  /* send CMD24 with address information. Chip select is done by
149  * the microSD_write_cmd method and */
150  if (microSD_write_cmd(&cmd[0]) != 0x00) {
151 #if DEBUG
152  printf("\nCMD24 failure!");
153 #endif
154  return -1;
155  }
156 
157  for (i = 0; i < 10; i++) {
158  mspi_transceive(MSPI_DUMMY_BYTE);
159  }
160 
161  /* send start byte 0xFE to the microSD card to symbolize the beginning
162  * of one data block (512byte)*/
163  mspi_transceive(0xFE);
164 
165  /*send 1 block (512byte) to the microSD card*/
166  for (i = 0; i < 512; i++) {
167  mspi_transceive(*buffer++);
168  }
169 
170  /*write CRC checksum: Dummy*/
171  mspi_transceive(MSPI_DUMMY_BYTE);
172  mspi_transceive(MSPI_DUMMY_BYTE);
173 
174  /*failure check: Data Response XXX00101 = OK*/
175  if ((mspi_transceive(MSPI_DUMMY_BYTE) & 0x1F) != 0x05) {
176 #if DEBUG
177  printf("\nblock failure!");
178 #endif
179  return -1;
180  }
181 
182  /*wait while microSD card is busy*/
183  while (mspi_transceive(MSPI_DUMMY_BYTE) != 0xff) {
184  };
185  /*release chip select and disable microSD spi*/
187 
188  return 0;
189 }
190 
191 uint8_t microSD_write_cmd(uint8_t *cmd) {
192  uint16_t i;
193  uint8_t data;
194 
196  mspi_transceive(MSPI_DUMMY_BYTE);
197  /*begin to send 6 command bytes to the sd card*/
199 
200  for (i = 0; i < 6; i++) {
201  mspi_transceive(*cmd++);
202  }
203  i = 0;
204  /*wait for the answer of the sd card*/
205  do {
206  /*0x01 for acknowledge*/
207  data = mspi_transceive(MSPI_DUMMY_BYTE);
208  if (i > 500) {
209 #if DEBUG
210  printf("\nwrite_cmd timeout!");
211 #endif
212  break;
213  }
214  i++;
215  } while (data == 0xFF);
216  return data;
217 }