Rev 231 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 231 | Rev 294 | ||
---|---|---|---|
1 | #include <avr/io.h> |
1 | #include <avr/io.h> |
2 | #include <util/delay.h> |
2 | #include <util/delay.h> |
3 | #include "fat16.h" |
3 | #include <string.h> |
4 | #include "sdc.h" |
4 | #include "sdc.h" |
5 | #include "ssc.h" |
5 | #include "ssc.h" |
- | 6 | #include "timer0.h" |
|
- | 7 | #include "printf_P.h" |
|
- | 8 | #include "crc16.h" |
|
- | 9 | ||
- | 10 | #define _SD_DEBUG |
|
- | 11 | ||
- | 12 | #define CMD_GO_IDLE_STATE 0x00 /* CMD00: response R1 */ |
|
- | 13 | #define CMD_SEND_OP_COND 0x01 /* CMD01: response R1 */ |
|
- | 14 | #define CMD_SEND_IF_COND 0x08 /* CMD08: response R7 */ |
|
- | 15 | #define CMD_SEND_CSD 0x09 /* CMD09: response R1 */ |
|
- | 16 | #define CMD_SEND_CID 0x0A /* CMD10: response R1 */ |
|
- | 17 | #define CMD_SEND_STATUS 0x0D /* CMD13: response R2 */ |
|
- | 18 | #define CMD_SET_BLOCKLEN 0x10 /* CMD16: arg0[31:0]: block length, response R1*/ |
|
- | 19 | #define CMD_READ_SINGLE_BLOCK 0x11 /* CMD17: arg0[31:0]: data address, response R1 */ |
|
- | 20 | #define CMD_WRITE_SINGLE_BLOCK 0x18 /* CMD24: arg0[31:0]: data address, response R1 */ |
|
- | 21 | #define CMD_APP_CMD 0x37 /* CMD55: response R1 */ |
|
- | 22 | #define CMD_READ_OCR 0x3A /* CMD58: response R3 */ |
|
- | 23 | #define CMD_CRC_ON_OFF 0x3B /* CMD59: arg0[31:1]: stuff bits, arg0[0:0]: crc option, response R1 */ |
|
- | 24 | #define ACMD_SEND_OP_COND 0x29 /* ACMD41: arg0[31]: stuff bits, arg0[30]: HCS, arg0[29:0] stuff bits*, response R1 */ |
|
- | 25 | ||
- | 26 | #define R1_NO_ERR 0x00 |
|
- | 27 | #define R1_IDLE_STATE 0x01 |
|
- | 28 | #define R1_ERASE_RESET 0x02 |
|
- | 29 | #define R1_ILLEGAL_CMD 0x04 |
|
- | 30 | #define R1_COM_CRC_ERR 0x08 |
|
- | 31 | #define R1_ERASE_SEQUENCE_ERR 0x10 |
|
- | 32 | #define R1_ADDRESS_ERR 0x20 |
|
- | 33 | #define R1_PARAMETER_ERR 0x40 |
|
- | 34 | #define R1_BAD_RESPONSE 0x80 |
|
- | 35 | ||
- | 36 | #define R2_NO_ERR 0x00 |
|
- | 37 | #define R2_CARD_LOCKED 0x01 |
|
- | 38 | #define R2_ERASE_WRITE_PROT_ERR 0x02 |
|
- | 39 | #define R2_UNKOWN_ERR 0x04 |
|
- | 40 | #define R2_CARD_CTRL_ERR 0x08 |
|
- | 41 | #define R2_CARD_ECC_ERR 0x10 |
|
- | 42 | #define R2_WRITE_PROT_ERR 0x20 |
|
- | 43 | #define R2_ERASE_PARAM_ERR 0x40 |
|
- | 44 | #define R2_OUT_OF_RANGE_ERR 0x80 |
|
- | 45 | ||
- | 46 | #define DATA_START_TOKEN 0xFE |
|
- | 47 | #define DATA_RESPONSE_MASK 0x1F |
|
- | 48 | #define DATA_RESPONSE_OK 0x05 |
|
- | 49 | #define DATA_RESPONSE_CRC_ERR 0x0B |
|
- | 50 | #define DATA_RESPONSE_WRITE_ERR 0x1D |
|
- | 51 | ||
- | 52 | typedef enum |
|
- | 53 | { |
|
- | 54 | VER_UNKNOWN, |
|
- | 55 | VER_1X, |
|
- | 56 | VER_20 |
|
- | 57 | } SDVersion_t; |
|
- | 58 | ||
- | 59 | typedef struct |
|
- | 60 | { |
|
- | 61 | uint8_t Valid; |
|
- | 62 | SDVersion_t Version; // HW-Version |
|
- | 63 | uint32_t Capacity; // Memory capacity in bytes |
|
- | 64 | uint8_t CID[16]; // CID register |
|
- | 65 | uint8_t CSD[16]; // CSD register |
|
- | 66 | } __attribute__((packed)) SDCardInfo_t; |
|
- | 67 | ||
- | 68 | ||
- | 69 | volatile SDCardInfo_t SDCardInfo; |
|
6 | 70 | ||
7 | //________________________________________________________________________________________________________________________________________ |
- | |
8 | // Module name: mmc.c |
- | |
9 | // Compiler used: avr-gcc 3.4.5 |
- | |
10 | // Last Modifikation: 24.07.2007 |
- | |
11 | // Version: 1.05 |
- | |
12 | // Authors: Stephan Busker |
71 | //________________________________________________________________________________________________________________________________________ |
13 | // Description: Source files for connecting to an sdcard using the SSC |
72 | // Function: CRC7(uint8_t* cmd, uint32_t len); |
14 | // |
73 | // |
15 | //........................................................................................................................................ |
- | |
16 | // Functions: u8 SDC_init(void); |
- | |
17 | // u8 SDC_PutCommand (u8*CMD); |
- | |
18 | // u8 SDC_PutSector(u32 addr,u8*Buffer); |
- | |
19 | // u8 SDC_GetSector(u32 addr,u8*Buffer); |
- | |
20 | // void SDC_GetBlock(u8*CMD,u8*Buffer,u16 Bytes); |
74 | // Description: This function calculated the CRC7 checksum used in the last byte of a spi command frame. |
21 | // |
- | |
22 | ////........................................................................................................................................ |
- | |
23 | // ext. functions: extern void SSC_Init(void); |
- | |
24 | // extern u8 SSC_GetChar (void); |
- | |
25 | // extern void SSC_PutChar (u8); |
- | |
26 | // extern void SSC_Enable(void); |
- | |
27 | // extern void SSC_Disable(void); |
- | |
28 | //........................................................................................................................................ |
75 | // |
29 | // |
- | |
30 | // URL: www.Mikro-Control.de |
76 | // |
31 | // mailto: stephan.busker@mikro-control.de |
77 | // Returnvalue: the function returns the crc7 including bit 0 set to 1 |
- | 78 | //________________________________________________________________________________________________________________________________________ |
|
- | 79 | ||
- | 80 | uint8_t CRC7(uint8_t *cmd, uint32_t len) |
|
- | 81 | { |
|
- | 82 | uint8_t i, a; |
|
- | 83 | uint8_t crc, Data; |
|
- | 84 | ||
- | 85 | crc = 0; // init CRC buffer |
|
- | 86 | for (a = 0; a < len ;a++) // for every byte in the msg |
|
- | 87 | { |
|
- | 88 | Data = cmd[a]; |
|
- | 89 | for (i=0;i<8;i++) // for every bit in the byte |
|
- | 90 | { |
|
- | 91 | crc <<= 1; // shift crc |
|
- | 92 | if ((Data & 0x80)^(crc & 0x80)) crc ^=0x09; //xor |
|
- | 93 | Data <<= 1; // shift data for next bit |
|
- | 94 | } |
|
- | 95 | } |
|
- | 96 | crc = (crc<<1)|1; // set terminating bit to 1 |
|
- | 97 | return(crc); |
|
- | 98 | } |
|
- | 99 | ||
- | 100 | ||
- | 101 | uint8_t SDC_WaitForBusy(uint16_t timeout) |
|
- | 102 | { |
|
- | 103 | uint8_t rsp = 0; |
|
- | 104 | uint16_t timestamp = 0; |
|
- | 105 | ||
- | 106 | SSC_Enable(); // enable chipselect. |
|
- | 107 | timestamp = SetDelay(timeout); |
|
- | 108 | do |
|
- | 109 | { |
|
- | 110 | rsp = SSC_GetChar(); |
|
32 | //________________________________________________________________________________________________________________________________________ |
111 | if(CheckDelay(timestamp)) break; |
33 | 112 | }while(rsp != 0xFF); // wait while card is busy (data out low) |
|
34 | - | ||
35 | - | ||
36 | - | ||
37 | //________________________________________________________________________________________________________________________________________ |
113 | return(rsp); |
- | 114 | } |
|
- | 115 | ||
- | 116 | //________________________________________________________________________________________________________________________________________ |
|
38 | // Funtion: SDC_Init(void); |
117 | // Function: SDC_SendCMDR1(uint8_t CmdNo, uint32_t arg); |
39 | // |
118 | // |
40 | // Description: This function initialises the SDCard to spi-mode. |
- | |
41 | // |
119 | // Description: This function send a command frame to the SD-Card in spi-mode. |
42 | // |
120 | // |
43 | // Returnvalue: the function returns 0 if the initialisation was successfull otherwise the function returns an errorcode. |
121 | // |
44 | //________________________________________________________________________________________________________________________________________ |
122 | // Returnvalue: The function returns the first response byte like for R1 commands |
45 | 123 | //________________________________________________________________________________________________________________________________________ |
|
46 | u8 SDC_Init(void) |
124 | uint8_t SDC_SendCMDR1(uint8_t CmdNo, uint32_t arg) |
47 | { |
125 | { |
- | 126 | uint8_t r1; |
|
- | 127 | uint16_t timeout = 0; |
|
- | 128 | uint16_t a; |
|
- | 129 | uint8_t cmd[6]; |
|
- | 130 | ||
- | 131 | cmd[0] = 0x40|CmdNo; // set command index |
|
- | 132 | cmd[1] = (arg & 0xFF000000)>>24; |
|
- | 133 | cmd[2] = (arg & 0x00FF0000)>>16; |
|
- | 134 | cmd[3] = (arg & 0x0000FF00)>>8; |
|
- | 135 | cmd[4] = (arg & 0x000000FF); |
|
- | 136 | cmd[5] = CRC7(cmd, 5); // update checksum |
|
- | 137 | #ifdef _SD_DEBUG |
|
- | 138 | printf("\r\nCmd=%02X, arg=%04X%04X", CmdNo, (uint16_t)(arg>>16), (uint16_t)(0xFFFF & arg)); |
|
48 | u8 Timeout = 0; |
139 | #endif |
- | 140 | SSC_Disable(); // disable chipselect. |
|
- | 141 | SSC_PutChar(0xFF); // dummy to sync |
|
- | 142 | SSC_Enable(); // enable chipselect. |
|
- | 143 | _delay_loop_2(200); |
|
- | 144 | //SDC_WaitForBusy(500); // wait 500ms until card is busy |
|
- | 145 | ||
- | 146 | for (a = 0;a < 6; a++) // send the command sequence to the sdcard (6 bytes) |
|
- | 147 | { |
|
- | 148 | SSC_PutChar(cmd[a]); |
|
- | 149 | _delay_loop_2(10); |
|
- | 150 | } |
|
- | 151 | // get response byte |
|
- | 152 | do |
|
- | 153 | { |
|
- | 154 | r1 = SSC_GetChar(); // get byte from sd-card |
|
- | 155 | if (timeout++ > 1000) break; |
|
- | 156 | }while(r1 == 0xFF); // wait for the response byte from sd-card. |
|
- | 157 | #ifdef _SD_DEBUG |
|
- | 158 | printf("-->R1=%02X", r1); |
|
- | 159 | #endif |
|
- | 160 | return(r1); |
|
- | 161 | } |
|
49 | u8 CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95}; |
162 | |
- | 163 | //________________________________________________________________________________________________________________________________________ |
|
- | 164 | // Function: SDC_SendACMDR1(uint8_t CmdNo, uint32_t arg); |
|
- | 165 | // |
|
- | 166 | // Description: This function send a application command frame to the SD-Card in spi-mode. |
|
- | 167 | // |
|
- | 168 | // |
|
- | 169 | // Returnvalue: The function returns the first response byte like for R1 commands |
|
- | 170 | //________________________________________________________________________________________________________________________________________ |
|
- | 171 | uint8_t SDC_SendACMDR1(uint8_t CmdNo, uint32_t arg) |
|
- | 172 | { |
|
- | 173 | uint8_t r1 = 0xFF; |
|
- | 174 | r1 = SDC_SendCMDR1(CMD_APP_CMD, 0UL); |
|
- | 175 | if(r1 & R1_BAD_RESPONSE) return(r1); |
|
- | 176 | r1 = SDC_SendCMDR1(CmdNo, arg); |
|
- | 177 | return(r1); |
|
- | 178 | } |
|
- | 179 | ||
50 | u16 a = 0; |
180 | //________________________________________________________________________________________________________________________________________ |
- | 181 | // Function: SDC_GetData(uint8_t * cmd ,u8 *Buffer, u32 len); |
|
- | 182 | // |
|
- | 183 | // Description: This function sneds cmd an reads a datablock of len from the sd-card |
|
- | 184 | // |
|
- | 185 | // |
|
- | 186 | // Returnvalue: SD_Result_t |
|
- | 187 | //________________________________________________________________________________________________________________________________________ |
|
- | 188 | ||
51 | u8 b = 0; |
189 | SD_Result_t SDC_GetData(uint8_t CmdNo, uint32_t addr, uint8_t *Buffer, uint32_t len) |
52 | 190 | { |
|
53 | SSC_Init(); // Initialise SSC to transmit data to the sdcard. |
191 | uint8_t rsp; |
54 | 192 | uint16_t a, crc16; |
|
55 | - | ||
56 | _delay_ms(10); // before initialising the sdcard wait for 10ms |
193 | SD_Result_t result = SD_ERROR_UNKNOWN; |
57 | - | ||
58 | - | ||
59 | for (b=0;b<0x0f;b++) // sending 74Clocks brings the sdcard into spimode. |
- | |
60 | { |
- | |
61 | _delay_us(1); // wait at least 1us between the characters. |
- | |
62 | SSC_PutChar(0xff); |
194 | |
63 | } |
- | |
64 | - | ||
65 | - | ||
66 | while(SDC_PutCommand (CMD) !=1) // Sending CMD0 (Reset) to the sdcard. |
- | |
67 | { |
- | |
68 | if (Timeout++ > 200) |
- | |
69 | { |
195 | // send the command |
70 | return(1); |
196 | rsp = SDC_SendCMDR1(CmdNo, addr); |
- | 197 | if (rsp != R1_NO_ERR) |
|
71 | } |
198 | { |
- | 199 | result = SD_ERROR_BAD_RESPONSE; |
|
72 | } |
200 | goto end; |
73 | 201 | } |
|
- | 202 | ||
- | 203 | do |
|
- | 204 | { |
|
- | 205 | rsp = SSC_GetChar(); |
|
- | 206 | if((rsp & 0xF0) == 0x00) // data error token |
|
74 | Timeout = 0; |
207 | { |
- | 208 | result = SD_ERROR_READ_DATA; |
|
- | 209 | goto end; |
|
- | 210 | } |
|
- | 211 | }while(rsp != DATA_START_TOKEN); |
|
- | 212 | // data start token received |
|
- | 213 | for (a = 0; a < len; a++) // read the block from the SSC |
|
- | 214 | { |
|
- | 215 | Buffer[a] = SSC_GetChar(); |
|
75 | CMD[0] = 0x41; |
216 | } |
- | 217 | // Read two bytes CRC16-Data checksum |
|
76 | CMD[5] = 0xFF; |
218 | crc16 = SSC_GetChar(); // highbyte first |
77 | while( SDC_PutCommand (CMD) !=0) // Sending CMD1 to the sdcard. |
219 | crc16 = (crc16<<8)|SSC_GetChar(); // lowbyte last |
78 | { |
220 | /* if(crc16 != CRC16(Buffer, len)) result = SD_ERROR_CRC_DATA; |
79 | if (Timeout++ > 100) |
221 | else */result = SD_SUCCESS; |
80 | { |
222 | |
81 | return(2); |
223 | end: |
82 | } |
224 | if(result != SD_SUCCESS) |
83 | } |
225 | { |
84 | 226 | printf("Error %02X reading data from sd card (R1=%02X).\r\n", result, rsp); |
|
85 | SSC_Disable(); // disable sdcard. |
227 | } |
86 | return(0); |
228 | return(result); |
87 | } |
229 | } |
88 | 230 | ||
89 | - | ||
90 | - | ||
91 | 231 | ||
92 | //________________________________________________________________________________________________________________________________________ |
232 | //________________________________________________________________________________________________________________________________________ |
93 | // Funtion: SDC_PutCommand(* CMD); |
- | |
94 | // |
- | |
95 | // Description: This function initialises the SDCard to spi-mode. |
- | |
96 | // |
233 | // Function: SDC_PrintCID(u8 * pCID); |
97 | // |
234 | // |
- | 235 | // Description: This function prints the CIS register in a human readable format. |
|
- | 236 | // |
|
- | 237 | // |
|
98 | // Returnvalue: the function returns 0 if the initialisation was successfull otherwise the function returns an errorcode. |
238 | // Returnvalue: the function returns nothing |
99 | //________________________________________________________________________________________________________________________________________ |
239 | //________________________________________________________________________________________________________________________________________ |
100 | 240 | ||
101 | u8 SDC_PutCommand (u8*CMD) |
241 | void SDC_PrintCID(uint8_t * pCID) |
102 | { |
242 | { |
103 | u8 tmp = 0xff; |
- | |
104 | u8 Timeout = 0; |
- | |
105 | u16 a = 0; |
243 | uint8_t pn[6]; |
106 | 244 | uint16_t temp1, temp2; |
|
107 | 245 | ||
108 | #ifdef SSC_RX_FIFO |
246 | printf("\r\n Manufacturer ID: %i\r\n", pCID[0]); |
- | 247 | memcpy(pn, &pCID[1], 2); |
|
109 | SSC_ClearRxFifo(); |
248 | pn[2] = '\0'; // terminate string |
110 | #endif |
249 | printf(" Application ID: %s\r\n",pn); |
111 | SSC_Disable(); // disable chipselect |
- | |
112 | SSC_PutChar(0xFF); // Send 8 Clocks to the sdcard while card is not selected. |
250 | memcpy(pn, &pCID[3], 5); |
113 | SSC_Enable(); // enable chipselect. |
- | |
- | 251 | pn[5] = '\0'; // terminate string |
|
114 | 252 | printf(" Product Name: %s\r\n",pn); |
|
115 | if (*CMD == 0x41) _delay_ms(10); // if command is CMD0 generate a short delay. |
253 | printf(" Product Rev.: %i.%i\r\n",pCID[8]>>4, pCID[8]&0xF); |
116 | 254 | printf(" Serial No.: "); |
|
117 | for (a = 0;a<0x06;a++) // send the command sequence to the sdcard (6 bytes) |
255 | for(temp1 = 0; temp1<4; temp1++) |
- | 256 | { |
|
- | 257 | printf("%02X", pCID[9+temp1]); |
|
- | 258 | } |
|
- | 259 | printf("\r\n"); |
|
- | 260 | temp1 = pCID[14] & 0x0F; // month |
|
118 | { |
- | |
- | 261 | temp2 = ((pCID[14]>>4)|(pCID[13]<<4)) + 2000; // year |
|
119 | SSC_PutChar(*CMD++); |
262 | printf(" Manufac. Date: %i/%i\r\n\r\n",temp1, temp2); |
120 | } |
263 | } |
121 | 264 | ||
122 | #ifdef SSC_RX_FIFO |
265 | //________________________________________________________________________________________________________________________________________ |
123 | SSC_ClearRxFifo(); |
- | |
124 | #endif |
- | |
125 | while (tmp == 0xff) // Wait for response from sdcard. |
266 | // Function: SDC_GetCID(uint8_t * pCID); |
126 | { |
267 | // |
127 | tmp = SSC_GetChar(); |
- | |
128 | if (Timeout++ > 100) |
- | |
- | 268 | // Description: This function reads the CIS register form the sd card in spi mode. |
|
- | 269 | // |
|
- | 270 | // |
|
129 | { |
271 | // Returnvalue: the function returns error state |
130 | break; // or timeout. |
272 | //________________________________________________________________________________________________________________________________________ |
- | 273 | ||
- | 274 | SD_Result_t SDC_GetCID(uint8_t * pCID) |
|
- | 275 | { |
|
- | 276 | return SDC_GetData(CMD_SEND_CID, 0UL, pCID, 16); |
|
- | 277 | } |
|
- | 278 | ||
- | 279 | //________________________________________________________________________________________________________________________________________ |
|
- | 280 | // Function: SDC_GetCSD(uint8_t * pCSD); |
|
- | 281 | // |
|
- | 282 | // Description: This function reads the CSD register form the sd card in spi mode. |
|
- | 283 | // |
|
- | 284 | // |
|
131 | } |
285 | // Returnvalue: the function returns error state |
132 | } |
286 | //________________________________________________________________________________________________________________________________________ |
133 | 287 | ||
134 | return(tmp); |
288 | SD_Result_t SDC_GetCSD(uint8_t * pCSD) |
135 | } |
289 | { |
136 | 290 | return SDC_GetData(CMD_SEND_CSD, 0UL, pCSD, 16); |
|
137 | 291 | } |
|
138 | 292 | ||
139 | 293 | ||
140 | //________________________________________________________________________________________________________________________________________ |
294 | //________________________________________________________________________________________________________________________________________ |
141 | // Funtion: SDC_PutSector(void); |
295 | // Function: SDC_Init(void); |
142 | // |
- | |
143 | // Description: This function writes one sector of data to the SSC |
- | |
144 | // |
- | |
145 | // |
296 | // |
146 | // Returnvalue: none |
297 | // Description: This function initialises the SDCard to spi-mode. |
- | 298 | // |
|
- | 299 | // |
|
- | 300 | // Returnvalue: the function returns 0 if the initialisation was successfull otherwise the function returns an errorcode. |
|
147 | //________________________________________________________________________________________________________________________________________ |
301 | //________________________________________________________________________________________________________________________________________ |
148 | 302 | ||
149 | u8 SDC_PutSector(u32 addr,u8*Buffer) |
303 | SD_Result_t SDC_Init(void) |
150 | { |
304 | { |
151 | u8 tmp; |
305 | uint16_t timeout = 0; |
152 | u8 CMD[] = {0x58,0x00,0x00,0x00,0x00,0xFF}; |
- | |
153 | - | ||
154 | addr = addr << 9; // convert sectoradress to byteadress |
- | |
155 | - | ||
156 | CMD[1] = ((addr & 0xFF000000) >>24 ); |
- | |
157 | CMD[2] = ((addr & 0x00FF0000) >>16 ); |
306 | uint8_t rsp[6]; // SD-SPI response buffer |
158 | CMD[3] = ((addr & 0x0000FF00) >>8 ); |
307 | SD_Result_t result = SD_ERROR_UNKNOWN; |
159 | - | ||
160 | tmp = SDC_PutCommand (CMD); // send command to sdcard. |
308 | |
- | 309 | if(SD_SWITCH) // init only if the SD-Switch is indicating a card in the slot |
|
161 | if (tmp != 0) |
310 | { |
- | 311 | printf("\r\n SSC init..."); |
|
- | 312 | SSC_Init(); |
|
- | 313 | printf("ok"); |
|
- | 314 | ||
- | 315 | _delay_loop_2(1050); |
|
- | 316 | ||
- | 317 | printf("\r\n SDC init..."); |
|
- | 318 | SDCardInfo.Valid = 0; |
|
- | 319 | /* The host shall supply power to the card so that the voltage is reached to Vdd_min within 250ms and |
|
- | 320 | start to supply at least 74 SD clocks to the SD card with keeping cmd line to high. In case of SPI |
|
- | 321 | mode, CS shall be held to high during 74 clock cycles. */ |
|
- | 322 | SSC_Disable(); // set SD_CS high |
|
- | 323 | for (timeout = 0; timeout < 15; timeout++) // 15*8 = 120 cycles |
|
- | 324 | { |
|
- | 325 | SSC_PutChar(0xFF); |
|
- | 326 | } |
|
- | 327 | ||
- | 328 | // switch to idle state |
|
- | 329 | #ifdef _SD_DEBUG |
|
- | 330 | printf("\r\nGoing idle state.."); |
|
- | 331 | #endif |
|
- | 332 | timeout = 0; |
|
- | 333 | do |
|
- | 334 | { |
|
- | 335 | rsp[0] = SDC_SendCMDR1(CMD_GO_IDLE_STATE, 0UL); |
|
- | 336 | if (timeout++ > 500) |
|
- | 337 | { |
|
- | 338 | printf("reset timeout"); |
|
- | 339 | result = SD_ERROR_RESET; |
|
- | 340 | goto end; |
|
- | 341 | } |
|
- | 342 | }while(rsp[0] != R1_IDLE_STATE); |
|
- | 343 | // enable crc feature |
|
- | 344 | /* if(SDC_SendCMDR1(CMD_CRC_ON_OFF, 1UL) != R1_IDLE_STATE) |
|
- | 345 | { |
|
- | 346 | printf("Bad cmd59 R1=%02X.", rsp[0]); |
|
- | 347 | result = SD_ERROR_BAD_RESPONSE; |
|
- | 348 | goto end; |
|
- | 349 | }*/ |
|
- | 350 | // check for card hw version |
|
- | 351 | // 2.7-3.6V Range = 0x01, check pattern 0xAA |
|
- | 352 | rsp[0] = SDC_SendCMDR1(CMD_SEND_IF_COND, 0x000001AA); |
|
- | 353 | // answer to cmd58 is an R7 response (R1+ 4Byte IFCond) |
|
- | 354 | if(rsp[0] & R1_BAD_RESPONSE) |
|
- | 355 | { |
|
- | 356 | printf("Bad cmd8 R1=%02X.", rsp[0]); |
|
- | 357 | result = SD_ERROR_BAD_RESPONSE; |
|
- | 358 | goto end; |
|
- | 359 | } |
|
- | 360 | if(rsp[0] & R1_ILLEGAL_CMD) |
|
- | 361 | { |
|
- | 362 | //Ver1.X SD Memory Card or not a SD Memory Card |
|
- | 363 | SDCardInfo.Version = VER_1X; |
|
- | 364 | } |
|
- | 365 | else |
|
- | 366 | { |
|
- | 367 | // Ver2.00 or later SD Memory Card |
|
- | 368 | // reading the remaining bytes of the R7 response |
|
- | 369 | SDCardInfo.Version = VER_20; |
|
- | 370 | for(timeout = 1; timeout < 5; timeout++) |
|
- | 371 | { |
|
- | 372 | rsp[timeout] = SSC_GetChar(); |
|
- | 373 | } |
|
- | 374 | //check pattern |
|
- | 375 | if(rsp[4]!= 0xAA) |
|
- | 376 | { |
|
- | 377 | printf("Bad cmd8 R7 check pattern.\r\n"); |
|
- | 378 | result = SD_ERROR_BAD_RESPONSE; |
|
- | 379 | goto end; |
|
- | 380 | } |
|
- | 381 | if ( (rsp[3] & 0x0F)!= 0x01 ) // voltage range is not 2.7-3.6V |
|
- | 382 | { |
|
- | 383 | ||
- | 384 | printf("Card is incompatible to 3.3V.\r\n"); |
|
- | 385 | result = SD_ERROR_BAD_VOLTAGE_RANGE; |
|
- | 386 | goto end; |
|
- | 387 | } |
|
- | 388 | } |
|
- | 389 | ||
- | 390 | rsp[0] = SDC_SendCMDR1(CMD_READ_OCR, 0UL); |
|
- | 391 | // answer to cmd58 is an R3 response (R1 + 4Byte OCR) |
|
- | 392 | if(rsp[0] & R1_BAD_RESPONSE) |
|
- | 393 | { |
|
- | 394 | printf("Bad cmd58 R1 %02x.", rsp[0]); |
|
- | 395 | result = SD_ERROR_BAD_RESPONSE; |
|
- | 396 | goto end; |
|
- | 397 | } |
|
- | 398 | if(rsp[0] & R1_ILLEGAL_CMD) |
|
- | 399 | { |
|
- | 400 | printf("Not an SD-CARD."); |
|
- | 401 | result = SD_ERROR_NO_SDCARD; |
|
- | 402 | goto end; |
|
- | 403 | } |
|
- | 404 | // read 4 bytes of OCR register |
|
- | 405 | for(timeout = 1; timeout < 5; timeout++) |
|
- | 406 | { |
|
- | 407 | rsp[timeout] = SSC_GetChar(); |
|
- | 408 | } |
|
- | 409 | // FollowMe & SD-Logger uses 3.3 V, therefore check for bit 20 & 21 |
|
- | 410 | if((rsp[2] & 0x30) != 0x30) |
|
- | 411 | { |
|
- | 412 | // supply voltage is not supported by sd-card |
|
- | 413 | printf("Card is incompatible to 3.3V."); |
|
- | 414 | result = SD_ERROR_BAD_VOLTAGE_RANGE; |
|
- | 415 | goto end; |
|
- | 416 | } |
|
- | 417 | ||
- | 418 | // Initialize the sd-card sending continously ACMD_SEND_OP_COND (only supported by SD cards) |
|
- | 419 | timeout = SetDelay(2000); // set timeout to 2000 ms (large cards tend to longer) |
|
- | 420 | do |
|
- | 421 | { |
|
- | 422 | rsp[0] = SDC_SendACMDR1(ACMD_SEND_OP_COND, 0UL); |
|
- | 423 | if(rsp[0] & R1_BAD_RESPONSE) |
|
- | 424 | { |
|
- | 425 | printf("Bad Acmd41 R1=%02X.", rsp[0]); |
|
- | 426 | result = SD_ERROR_BAD_RESPONSE; |
|
- | 427 | goto end; |
|
- | 428 | } |
|
- | 429 | if(CheckDelay(timeout)) |
|
- | 430 | { |
|
- | 431 | printf("Init timeout."); |
|
- | 432 | result = SD_ERROR_INITIALIZE; |
|
- | 433 | goto end; |
|
- | 434 | } |
|
- | 435 | } while(rsp[0] & R1_IDLE_STATE); // loop until idle state |
|
- | 436 | ||
- | 437 | if(rsp[0] != R1_NO_ERR) |
|
- | 438 | { |
|
- | 439 | printf("Init error."); |
|
- | 440 | result = SD_ERROR_INITIALIZE; |
|
- | 441 | goto end; |
|
- | 442 | } |
|
- | 443 | /* set block size to 512 bytes */ |
|
- | 444 | if(SDC_SendCMDR1(CMD_SET_BLOCKLEN, 512UL) != R1_NO_ERR) |
|
- | 445 | { |
|
- | 446 | printf("Error setting block length to 512."); |
|
- | 447 | result = SD_ERROR_SET_BLOCKLEN; |
|
- | 448 | goto end; |
|
- | 449 | } |
|
- | 450 | ||
- | 451 | //SSC_Disable(); // set SD_CS high |
|
- | 452 | // here is the right place to inrease the SPI baud rate to maximum |
|
- | 453 | //SSC_Enable(); // set SD_CS high |
|
- | 454 | ||
- | 455 | // read CID register |
|
- | 456 | result = SDC_GetCID((uint8_t *)&SDCardInfo.CID); |
|
- | 457 | if(result != SD_SUCCESS) |
|
- | 458 | { |
|
- | 459 | printf("Error reading CID.\r\n"); |
|
- | 460 | goto end; |
|
- | 461 | } |
|
- | 462 | ||
- | 463 | // read CSD register |
|
- | 464 | result = SDC_GetCSD((uint8_t *)&SDCardInfo.CSD); |
|
- | 465 | if(result != SD_SUCCESS) |
|
- | 466 | { |
|
- | 467 | printf("Error reading CSD."); |
|
- | 468 | goto end; |
|
- | 469 | } |
|
- | 470 | ||
- | 471 | printf("ok\r\n"); |
|
- | 472 | ||
- | 473 | uint8_t c_size_mult, read_bl_len; |
|
- | 474 | uint32_t c_size; |
|
- | 475 | ||
- | 476 | switch(SDCardInfo.CSD[0]>>6) // check CSD Version |
|
- | 477 | { |
|
- | 478 | case 0x00: // if CSD is V1.0 structure (2GB limit) |
|
- | 479 | ||
- | 480 | /* |
|
- | 481 | memory capacity = BLOCKNR * BLOCK_LEN |
|
- | 482 | BLOCKNR = (C_SIZE+1) * MULT |
|
- | 483 | MULT = 2^(C_SIZE_MULT+2) |
|
- | 484 | BLOCK_LEN = 2^READ_BL_LEN |
|
- | 485 | ||
- | 486 | C_SIZE is 12 bits [73:62] in CSD register |
|
- | 487 | C_SIZE_MULT is 3 bits [49:47] in CSD register |
|
- | 488 | READ_BL_LEN is 4 bits [83:80] in CSD register |
|
- | 489 | */ |
|
- | 490 | ||
- | 491 | read_bl_len = (SDCardInfo.CSD[5] & 0x0F); //CSD[05] -> [87:80] |
|
- | 492 | c_size = ((uint32_t)(SDCardInfo.CSD[6] & 0x03))<<10; //CSD[06] -> [79:72] |
|
- | 493 | c_size |= ((uint32_t)SDCardInfo.CSD[7])<<2; //CSD[07] -> [71:64] |
|
- | 494 | c_size |= (uint32_t)(SDCardInfo.CSD[8]>>6); //CSD[08] -> [63:56] |
|
- | 495 | c_size_mult = (SDCardInfo.CSD[9] & 0x03)<<1; //CSD[09] -> [55:48] |
|
- | 496 | c_size_mult |=(SDCardInfo.CSD[10] & 0x80)>>7; //CSD[10] -> [47:40] |
|
- | 497 | SDCardInfo.Capacity = (uint32_t)(c_size+1)*(1L<<(c_size_mult+2))*(1L<<read_bl_len); |
|
- | 498 | break; |
|
- | 499 | ||
- | 500 | case 0x01: // if CSD is V2.0 structure (HC SD-Card > 2GB) |
|
- | 501 | ||
- | 502 | /* |
|
- | 503 | memory capacity = (C_SIZE+1) * 512K byte |
|
- | 504 | C_SIZE is 22 bits [69:48] in CSR register |
|
- | 505 | */ |
|
- | 506 | ||
- | 507 | c_size = ((uint32_t)(SDCardInfo.CSD[7] & 0x3F))<<16; //CSD[07] -> [71:64] |
|
- | 508 | c_size |= ((uint32_t)SDCardInfo.CSD[8])<<8; //CSD[08] -> [63:56] |
|
- | 509 | c_size |= (uint32_t)SDCardInfo.CSD[9]; //CSD[09] -> [55:48]; |
|
- | 510 | SDCardInfo.Capacity = (c_size + 1)* 512L * 1024L; |
|
- | 511 | break; |
|
- | 512 | ||
- | 513 | default: //unknown CSD Version |
|
- | 514 | SDCardInfo.Capacity = 0; |
|
- | 515 | break; |
|
- | 516 | } |
|
- | 517 | ||
- | 518 | switch(SDCardInfo.Version) |
|
- | 519 | { |
|
- | 520 | case VER_1X: |
|
- | 521 | printf(" SD-CARD V1.x"); |
|
- | 522 | break; |
|
- | 523 | case VER_20: |
|
- | 524 | printf(" SD-CARD V2.0 or later"); |
|
- | 525 | default: |
|
- | 526 | break; |
|
- | 527 | } |
|
- | 528 | uint16_t mb_size = (uint16_t)(SDCardInfo.Capacity/(1024L*1024L)); |
|
- | 529 | printf("\r\n Capacity = %i MB", mb_size); |
|
- | 530 | ||
- | 531 | SDC_PrintCID((uint8_t *)&SDCardInfo.CID); |
|
- | 532 | SDCardInfo.Valid = 1; |
|
- | 533 | // jump point for error condition before |
|
162 | { |
534 | end: |
163 | return(tmp); |
- | |
164 | } |
- | |
165 | - | ||
166 | #ifdef SSC_RX_FIFO |
535 | SSC_Disable(); |
167 | SSC_ClearRxFifo(); |
- | |
168 | #endif |
536 | } |
169 | for (u8 a=0;a<100;a++) // wait until sdcard is ready |
537 | else |
- | 538 | { |
|
- | 539 | SSC_Deinit(); |
|
- | 540 | SDCardInfo.Valid = 0; |
|
170 | { |
541 | result = SD_ERROR_NOCARD; |
171 | SSC_GetChar(); |
- | |
172 | } |
- | |
173 | - | ||
174 | SSC_PutChar(0xFE); // send start of header to the SSC |
- | |
175 | - | ||
176 | for (u16 a=0;a<512;a++) // transmitt one sector (normaly 512bytes) of data to the sdcard. |
- | |
177 | { |
- | |
178 | SSC_PutChar(*Buffer++); |
- | |
179 | } |
- | |
180 | - | ||
181 | SSC_PutChar(0xFF); // write two bytes of crc to the sdcard (not used in spi-mode) |
- | |
182 | SSC_PutChar(0xFF); |
- | |
183 | #ifdef SSC_RX_FIFO |
- | |
184 | SSC_ClearRxFifo(); |
- | |
185 | #endif |
- | |
186 | - | ||
187 | while (SSC_GetChar() != 0xff){}; // wait untile the sdcard is ready. |
- | |
188 | - | ||
189 | SSC_Disable(); // disable sdcard. |
542 | printf("No Card in Slot."); |
190 | 543 | } |
|
191 | return(0); |
544 | return(result); |
192 | } |
545 | } |
193 | 546 | ||
- | 547 | ||
- | 548 | //________________________________________________________________________________________________________________________________________ |
|
- | 549 | // Function: SDC_Deinit(void); |
|
- | 550 | // |
|
- | 551 | // Description: This function deinitialises the SDCard interface. |
|
- | 552 | // |
|
- | 553 | // |
|
- | 554 | // Returnvalue: the function returns 0 if the initialisation was successfull otherwise the function returns an errorcode. |
|
- | 555 | //________________________________________________________________________________________________________________________________________ |
|
- | 556 | ||
- | 557 | SD_Result_t SDC_Deinit(void) |
|
- | 558 | { |
|
- | 559 | printf("\r\n SDC deinit..."); |
|
- | 560 | SSC_Deinit(); |
|
- | 561 | ||
- | 562 | SDCardInfo.Valid = 0; |
|
- | 563 | SDCardInfo.Capacity = 0; |
|
- | 564 | SDCardInfo.Version = VER_UNKNOWN; |
|
- | 565 | ||
- | 566 | printf("ok"); |
|
- | 567 | return(SD_SUCCESS); |
|
194 | 568 | } |
|
195 | 569 | ||
196 | //________________________________________________________________________________________________________________________________________ |
570 | //________________________________________________________________________________________________________________________________________ |
197 | // Funtion: SDC_GetSector(u32 addr,u8*Buffer); |
571 | // Function: SDC_PutSector(uint32_t addr, const uint8_t *Buffer) |
198 | // |
572 | // |
199 | // Description: This function reads one sector of data from the SSC |
573 | // Description: This function writes one sector of data to the SSC |
200 | // |
574 | // |
201 | // |
575 | // |
202 | // Returnvalue: none |
576 | // Returnvalue: SD_Result_t |
203 | //________________________________________________________________________________________________________________________________________ |
577 | //________________________________________________________________________________________________________________________________________ |
- | 578 | ||
- | 579 | SD_Result_t SDC_PutSector(uint32_t addr, const uint8_t *Buffer) |
|
- | 580 | { |
|
204 | 581 | uint8_t rsp; |
|
205 | u8 SDC_GetSector(u32 addr,u8*Buffer) |
582 | uint16_t a, crc16; |
206 | { |
583 | uint16_t timeout = 0; |
- | 584 | SD_Result_t result = SD_ERROR_UNKNOWN; |
|
- | 585 | ||
- | 586 | addr = addr << 9; // convert sectoradress to byteadress |
|
- | 587 | rsp = SDC_SendCMDR1(CMD_WRITE_SINGLE_BLOCK, addr); |
|
- | 588 | if (rsp != R1_NO_ERR) |
|
- | 589 | { |
|
- | 590 | result = SD_ERROR_BAD_RESPONSE; |
|
- | 591 | goto end; |
|
- | 592 | } |
|
- | 593 | ||
- | 594 | for (a=0;a<20;a++) // at least one byte |
|
- | 595 | { |
|
- | 596 | SSC_GetChar(); |
|
- | 597 | } |
|
- | 598 | crc16 = CRC16(Buffer, 512); // calc checksum for data block |
|
- | 599 | SSC_PutChar(DATA_START_TOKEN); // send data start of header to the SSC |
|
- | 600 | ||
207 | u8 CMD[] = {0x51,0x00,0x00,0x00,0x00,0xFF}; |
601 | for (a=0;a<512;a++) // transmit one sector (normaly 512bytes) of data to the sdcard. |
- | 602 | { |
|
208 | 603 | SSC_PutChar(Buffer[a]); |
|
- | 604 | } |
|
- | 605 | // write two bytes of crc16 to the sdcard |
|
- | 606 | SSC_PutChar((uint8_t)(crc16>>8)); // write high byte first |
|
- | 607 | SSC_PutChar((uint8_t)(0x00FF&crc16)); // lowbyte last |
|
- | 608 | ||
- | 609 | do // wait for data response token |
|
- | 610 | { |
|
- | 611 | rsp = SSC_GetChar(); |
|
- | 612 | if(timeout++ > 500) |
|
209 | addr = addr << 9; // convert sectoradress to byteadress. |
613 | { |
- | 614 | result = SD_ERROR_TIMEOUT; |
|
- | 615 | goto end; |
|
- | 616 | } |
|
- | 617 | }while((rsp & 0x11) != 0x01 ); |
|
- | 618 | // analyse data response token |
|
- | 619 | switch(rsp & DATA_RESPONSE_MASK) |
|
- | 620 | { |
|
- | 621 | case DATA_RESPONSE_OK: |
|
- | 622 | result = SD_SUCCESS; |
|
- | 623 | break; |
|
- | 624 | case DATA_RESPONSE_CRC_ERR: |
|
- | 625 | result = SD_ERROR_CRC_DATA; |
|
- | 626 | goto end; |
|
- | 627 | break; |
|
- | 628 | case DATA_RESPONSE_WRITE_ERR: |
|
- | 629 | result = SD_ERROR_WRITE_DATA; |
|
- | 630 | goto end; |
|
- | 631 | break; |
|
- | 632 | default: |
|
210 | 633 | result = SD_ERROR_UNKNOWN; |
|
- | 634 | goto end; |
|
- | 635 | break; |
|
- | 636 | ||
- | 637 | } |
|
- | 638 | // wait 2 seconds until the sdcard is busy. |
|
- | 639 | rsp = SDC_WaitForBusy(2000); |
|
- | 640 | if(rsp != 0xFF) |
|
- | 641 | { |
|
- | 642 | result = SD_ERROR_TIMEOUT; |
|
- | 643 | goto end; |
|
- | 644 | } |
|
- | 645 | ||
- | 646 | // check card status |
|
- | 647 | rsp = SDC_SendCMDR1(CMD_SEND_STATUS, 0); |
|
- | 648 | // first byte of R2 response is like R1 response |
|
- | 649 | if(rsp != R1_NO_ERR) |
|
- | 650 | { |
|
- | 651 | result = SD_ERROR_BAD_RESPONSE; |
|
- | 652 | SSC_GetChar(); // read out 2nd byte |
|
- | 653 | goto end; |
|
- | 654 | } |
|
- | 655 | // 2nd byte of r2 response |
|
- | 656 | rsp = SSC_GetChar(); |
|
- | 657 | if(rsp != R2_NO_ERR) |
|
- | 658 | { |
|
- | 659 | result = SD_ERROR_WRITE_DATA; |
|
- | 660 | SSC_GetChar(); |
|
- | 661 | goto end; |
|
211 | CMD[1] = ((addr & 0xFF000000) >>24 ); |
662 | } |
212 | CMD[2] = ((addr & 0x00FF0000) >>16 ); |
663 | end: |
213 | CMD[3] = ((addr & 0x0000FF00) >>8 ); |
664 | if(result != SD_SUCCESS) |
214 | 665 | { |
|
215 | SDC_GetBlock(CMD,Buffer,512); // read specified sector from sdcard. |
666 | printf("Error %02X writing data to sd card (R=%02X).\r\n", result, rsp); |
216 | 667 | } |
|
217 | return(0); |
668 | return(result); |
218 | } |
669 | } |
219 | 670 | ||
220 | 671 | ||
- | 672 | ||
221 | 673 | ||
222 | //________________________________________________________________________________________________________________________________________ |
674 | //________________________________________________________________________________________________________________________________________ |
223 | // Funtion: SDC_GetBlock(void); |
- | |
224 | // |
- | |
225 | // Description: This function reads one block of data of s16 bytes from the SSC. |
- | |
226 | // |
675 | // Function: SDC_GetSector(uint32_t addr,uint8_t *Buffer); |
227 | // |
676 | // |
- | 677 | // Description: This function reads one sector of data from the SSC |
|
- | 678 | // |
|
- | 679 | // |
|
228 | // Returnvalue: the function returns 0 if the initialisation was successfull otherwise the function returns an errorcode. |
680 | // Returnvalue: SD_Result_t |
229 | //________________________________________________________________________________________________________________________________________ |
681 | //________________________________________________________________________________________________________________________________________ |
230 | 682 | ||
231 | void SDC_GetBlock(u8*CMD,u8*Buffer,u16 Bytes) |
683 | SD_Result_t SDC_GetSector(uint32_t addr,uint8_t *Buffer) |
232 | { |
- | |
233 | if (SDC_PutCommand (CMD) != 0) // Send command to the sdcard. |
- | |
234 | { |
- | |
235 | return; |
- | |
236 | } |
- | |
237 | - | ||
238 | #ifdef SSC_RX_FIFO |
- | |
239 | SSC_ClearRxFifo(); |
- | |
240 | #endif |
- | |
241 | while (SSC_GetChar() != 0xfe){}; // wait until the sdcard is ready to transmitt data. |
- | |
242 | - | ||
243 | for (u16 a=0;a<Bytes;a++) // read the block from the SSC (normaly 512Bytes) |
- | |
244 | { |
- | |
245 | *Buffer++ = SSC_GetChar(); |
- | |
246 | } |
- | |
247 | - | ||
248 | SSC_GetChar(); // Read two bytes CRC- checksum (not used in spi-mode) |
684 | { |
249 | SSC_GetChar(); |
685 | addr = addr << 9; // convert sectoradress to byteadress |
250 | SSC_Disable(); // disable sdcard. |
- | |
251 | } |
- | |
252 | 686 | return SDC_GetData(CMD_READ_SINGLE_BLOCK, addr, Buffer, 512); |
|
253 | 687 | } |
|
254 | 688 | ||
255 | 689 |