1 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
2 | // + Copyright (c) 2008 Stephan Busker
|
3 | // + Nur für den privaten Gebrauch
|
4 | // + FOR NON COMMERCIAL USE ONLY
|
5 | // + www.Mikro-control.de
|
6 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
7 | // + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
|
8 | // + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
|
9 | // + Sollten direkte oder indirekte kommerzielle Absichten verfolgt werden, ist mit uns (stephan.busker@mikro-control.de) Kontakt
|
10 | // + bzgl. der Nutzungsbedingungen aufzunehmen.
|
11 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
12 | // + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
|
13 | // + Benutzung auf eigene Gefahr
|
14 | // + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
|
15 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
16 | // + Redistributions of source code (with or without modifications) must retain the above copyright notice,
|
17 | // + this list of conditions and the following disclaimer.
|
18 | // + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
|
19 | // + from this software without specific prior written permission.
|
20 | // + * The use of this project (hardware, software, binary files, sources and documentation) is only permitted
|
21 | // + for non-commercial use (directly or indirectly)
|
22 | // + Commercial use is only permitted with our written permission
|
23 | //
|
24 | // + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
25 | // + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
26 | // + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
27 | // + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
28 | // + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
29 | // + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
30 | // + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
31 | // + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
32 | // + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
33 | // + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
34 | // + POSSIBILITY OF SUCH DAMAGE.
|
35 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
36 |
|
37 |
|
38 | #include <stdio.h>
|
39 | #include <string.h>
|
40 | //#include <avr/io.h>
|
41 | #include "Z_sdc.h"
|
42 | #include "Z_ssc.h"
|
43 | #include "Z_crc16.h"
|
44 |
|
45 |
|
46 | //________________________________________________________________________________________________________________________________________
|
47 | // Module name: sdc.c
|
48 | // Compiler used: avr-gcc 3.4.5
|
49 | // Last Modifikation: 08.06.2008
|
50 | // Version: 1.07
|
51 | // Authors: Stephan Busker, Gregor Stobrawa
|
52 | // Description: Source files for connecting to an sd-card using the SSC
|
53 | //
|
54 | //........................................................................................................................................
|
55 | // Functions: SD_Result_t SDC_init(void);
|
56 | // u8 SDC_PutCommand (u8 *cmd);
|
57 | // SD_Result_t SDC_PutSector(u32 addr,u8 *Buffer);
|
58 | // SD_Result_t SDC_GetSector(u32 addr,u8 *Buffer);
|
59 | //
|
60 | ////........................................................................................................................................
|
61 | // ext. functions: extern void SSC_Init(void);
|
62 | // extern u8 SSC_GetChar (void);
|
63 | // extern void SSC_PutChar (u8);
|
64 | // extern void SSC_Enable(void);
|
65 | // extern void SSC_Disable(void);
|
66 | // extern void SSC_ClearRxFifo();
|
67 | //........................................................................................................................................
|
68 | //
|
69 | // URL: www.Mikro-Control.de
|
70 | // mailto: stephan.busker@mikro-control.de
|
71 | //________________________________________________________________________________________________________________________________________
|
72 |
|
73 |
|
74 |
|
75 | #define CMD_GO_IDLE_STATE 0x00 /* CMD00: response R1 */
|
76 | #define CMD_SEND_OP_COND 0x01 /* CMD01: response R1 */
|
77 | #define CMD_SEND_IF_COND 0x08 /* CMD08: response R7 */
|
78 | #define CMD_SEND_CSD 0x09 /* CMD09: response R1 */
|
79 | #define CMD_SEND_CID 0x0A /* CMD10: response R1 */
|
80 | #define CMD_SEND_STATUS 0x0D /* CMD13: response R2 */
|
81 | #define CMD_SET_BLOCKLEN 0x10 /* CMD16: arg0[31:0]: block length, response R1*/
|
82 | #define CMD_READ_SINGLE_BLOCK 0x11 /* CMD17: arg0[31:0]: data address, response R1 */
|
83 | #define CMD_WRITE_SINGLE_BLOCK 0x18 /* CMD24: arg0[31:0]: data address, response R1 */
|
84 | #define CMD_APP_CMD 0x37 /* CMD55: response R1 */
|
85 | #define CMD_READ_OCR 0x3A /* CMD58: response R3 */
|
86 | #define CMD_CRC_ON_OFF 0x3B /* CMD59: arg0[31:1]: stuff bits, arg0[0:0]: crc option, response R1 */
|
87 | #define ACMD_SEND_OP_COND 0x29 /* ACMD41: arg0[31]: stuff bits, arg0[30]: HCS, arg0[29:0] stuff bits*, response R1 */
|
88 |
|
89 | #define R1_NO_ERR 0x00
|
90 | #define R1_IDLE_STATE 0x01
|
91 | #define R1_ERASE_RESET 0x02
|
92 | #define R1_ILLEGAL_CMD 0x04
|
93 | #define R1_COM_CRC_ERR 0x08
|
94 | #define R1_ERASE_SEQUENCE_ERR 0x10
|
95 | #define R1_ADDRESS_ERR 0x20
|
96 | #define R1_PARAMETER_ERR 0x40
|
97 | #define R1_BAD_RESPONSE 0x80
|
98 |
|
99 | #define R2_NO_ERR 0x00
|
100 | #define R2_CARD_LOCKED 0x01
|
101 | #define R2_ERASE_WRITE_PROT_ERR 0x02
|
102 | #define R2_UNKOWN_ERR 0x04
|
103 | #define R2_CARD_CTRL_ERR 0x08
|
104 | #define R2_CARD_ECC_ERR 0x10
|
105 | #define R2_WRITE_PROT_ERR 0x20
|
106 | #define R2_ERASE_PARAM_ERR 0x40
|
107 | #define R2_OUT_OF_RANGE_ERR 0x80
|
108 |
|
109 | #define DATA_START_TOKEN 0xFE
|
110 | #define DATA_RESPONSE_MASK 0x1F
|
111 | #define DATA_RESPONSE_OK 0x05
|
112 | #define DATA_RESPONSE_CRC_ERR 0x0B
|
113 | #define DATA_RESPONSE_WRITE_ERR 0x1D
|
114 |
|
115 | typedef enum
|
116 | {
|
117 | VER_UNKNOWN,
|
118 | VER_1X,
|
119 | VER_20
|
120 | } SDVersion_t;
|
121 |
|
122 | typedef struct
|
123 | {
|
124 | u8 Valid;
|
125 | SDVersion_t Version; // HW-Version
|
126 | u32 Capacity; // Memory capacity in bytes
|
127 | u8 CID[16]; // CID register
|
128 | u8 CSD[16]; // CSD register
|
129 | } /* __attribute__((packed)) */ SDCardInfo_t;
|
130 |
|
131 | volatile SDCardInfo_t SDCardInfo;
|
132 |
|
133 |
|
134 |
|
135 | char text[50];
|
136 |
|
137 |
|
138 | //________________________________________________________________________________________________________________________________________
|
139 | // Function: CRC7(u8* cmd, u32 len);
|
140 | //
|
141 | // Description: This function calculated the CRC7 checksum used in the last byte of a spi command frame.
|
142 | //
|
143 | //
|
144 | // Returnvalue: the function returns the crc7 including bit 0 set to 1
|
145 | //________________________________________________________________________________________________________________________________________
|
146 |
|
147 | u8 CRC7(u8 * cmd, u32 len)
|
148 | {
|
149 | u8 i, a;
|
150 | u8 crc, Data;
|
151 |
|
152 | crc = 0; // init CRC buffer
|
153 | for (a = 0; a < len ;a++) // for every byte in the msg
|
154 | {
|
155 | Data = cmd[a];
|
156 | for (i=0;i<8;i++) // for every bit in the byte
|
157 | {
|
158 | crc <<= 1; // shift crc
|
159 | if ((Data & 0x80)^(crc & 0x80)) crc ^=0x09; //xor
|
160 | Data <<= 1; // shift data for next bit
|
161 | }
|
162 | }
|
163 | crc = (crc<<1)|1; // set terminating bit to 1
|
164 | return(crc);
|
165 | }
|
166 |
|
167 | u8 SDC_WaitForBusy(void)
|
168 | {
|
169 | u8 rsp = 0;
|
170 | u16 timeout=0;
|
171 |
|
172 | SSC_ClearRxFifo();
|
173 | SSC_Enable(); // enable chipselect.
|
174 | do
|
175 | {
|
176 | rsp = SSC_GetChar();
|
177 | if(timeout++>500) break;
|
178 | }while(rsp != 0xFF); // wait while card is busy (data out low)
|
179 | return(rsp);
|
180 | }
|
181 |
|
182 |
|
183 |
|
184 | //________________________________________________________________________________________________________________________________________
|
185 | // Function: SDC_SendCMDR1(u8 CmdNo, u32 arg);
|
186 | //
|
187 | // Description: This function send a command frame to the SD-Card in spi-mode.
|
188 | //
|
189 | //
|
190 | // Returnvalue: The function returns the first response byte like for R1 commands
|
191 | //________________________________________________________________________________________________________________________________________
|
192 | u8 SDC_SendCMDR1(u8 CmdNo, u32 arg)
|
193 | {
|
194 | u8 r1;
|
195 | u16 Timeout = 0;
|
196 | u16 a;
|
197 | u8 cmd[6];
|
198 |
|
199 | SSC_ClearRxFifo(); // clear the rx fifo
|
200 | SSC_Enable(); // enable chipselect.
|
201 | SDC_WaitForBusy();
|
202 | SSC_ClearRxFifo(); // clear the rx fifo
|
203 | SSC_GetChar(); // dummy to sync
|
204 |
|
205 | /* Send cmd10 (SEND_CID) */;
|
206 | cmd[0] = 0x40|CmdNo; // set command index
|
207 | cmd[1] = (arg & 0xFF000000)>>24;
|
208 | cmd[2] = (arg & 0x00FF0000)>>16;
|
209 | cmd[3] = (arg & 0x0000FF00)>>8;
|
210 | cmd[4] = (arg & 0x000000FF);
|
211 | cmd[5] = CRC7(cmd, 5); // update checksum
|
212 | for (a = 0;a < 6; a++) // send the command sequence to the sdcard (6 bytes)
|
213 | {
|
214 | SSC_PutChar(cmd[a]);
|
215 | }
|
216 | SSC_ClearRxFifo(); // clear the rx fifo to discard the bytes received during the transmission of the 6 command bytes
|
217 | do
|
218 | {
|
219 | r1 = SSC_GetChar(); // get byte from sd-card
|
220 | if (Timeout++ > 500) return(r1);
|
221 | }while(r1 == 0xFF); // wait for the response byte from sd-card.
|
222 | return(r1);
|
223 | }
|
224 |
|
225 |
|
226 | //________________________________________________________________________________________________________________________________________
|
227 | // Function: SDC_SendACMDR1(u8 CmdNo, u32 arg);
|
228 | //
|
229 | // Description: This function send a application command frame to the SD-Card in spi-mode.
|
230 | //
|
231 | //
|
232 | // Returnvalue: The function returns the first response byte like for R1 commands
|
233 | //________________________________________________________________________________________________________________________________________
|
234 | u8 SDC_SendACMDR1(u8 CmdNo, u32 arg)
|
235 | {
|
236 | u8 r1 = 0xFF;
|
237 | r1 = SDC_SendCMDR1(CMD_APP_CMD, 0UL);
|
238 | if(r1 & R1_BAD_RESPONSE) return(r1);
|
239 | r1 = SDC_SendCMDR1(CmdNo, arg);
|
240 | return(r1);
|
241 | }
|
242 |
|
243 |
|
244 | //________________________________________________________________________________________________________________________________________
|
245 | // Function: SDC_GetData(u8 * cmd ,u8 *Buffer, u32 len);
|
246 | //
|
247 | // Description: This function sneds cmd an reads a datablock of len from the sd-card
|
248 | //
|
249 | //
|
250 | // Returnvalue: SD_Result_t
|
251 | //________________________________________________________________________________________________________________________________________
|
252 |
|
253 | SD_Result_t SDC_GetData(u8 CmdNo, u32 addr, u8 *Buffer, u32 len)
|
254 | {
|
255 | u8 rsp;
|
256 | u16 a, Crc16;
|
257 | SD_Result_t result = SD_ERROR_UNKNOWN;
|
258 |
|
259 | // send the command
|
260 | rsp = SDC_SendCMDR1(CmdNo, addr);
|
261 | if (rsp != R1_NO_ERR)
|
262 | {
|
263 | result = SD_ERROR_BAD_RESPONSE;
|
264 | goto end;
|
265 | }
|
266 | SSC_ClearRxFifo();
|
267 | do
|
268 | {
|
269 | rsp = SSC_GetChar();
|
270 | if((rsp & 0xF0) == 0x00) // data error token
|
271 | {
|
272 | result = SD_ERROR_READ_DATA;
|
273 | goto end;
|
274 | }
|
275 | // if(timeout++>500) break;
|
276 | }while(rsp != DATA_START_TOKEN);
|
277 | // data start token received
|
278 | for (a = 0; a < len; a++) // read the block from the SSC
|
279 | {
|
280 | Buffer[a] = SSC_GetChar();
|
281 | }
|
282 | // Read two bytes CRC16-Data checksum
|
283 | Crc16 = SSC_GetChar(); // highbyte fisrt
|
284 | Crc16 = (Crc16<<8)|SSC_GetChar(); // lowbyte last
|
285 | result = SD_SUCCESS;
|
286 |
|
287 | end:
|
288 | return(result);
|
289 | }
|
290 |
|
291 |
|
292 | //________________________________________________________________________________________________________________________________________
|
293 | // Function: SDC_PrintCID(u8 * pCID);
|
294 | //
|
295 | // Description: This function prints the CIS register in a human readable format.
|
296 | //
|
297 | //
|
298 | // Returnvalue: the function returns nothing
|
299 | //________________________________________________________________________________________________________________________________________
|
300 |
|
301 | void SDC_PrintCID(u8 * pCID)
|
302 | {
|
303 | /* u8 pn[6];
|
304 | u16 temp1, temp2;
|
305 |
|
306 | sprintf(&text[0], "\r\nManufacturer ID: %i\r\n", pCID[0]);
|
307 | PutString(text);
|
308 | memcpy(pn, &pCID[1], 2);
|
309 | pn[2] = '\0'; // terminate string
|
310 | sprintf(&text[0], "Application ID: %s\r\n",pn);
|
311 | PutString(text);
|
312 | memcpy(pn, &pCID[3], 5);
|
313 | pn[5] = '\0'; // terminate string
|
314 | sprintf(&text[0], "Product Name: %s\r\n",pn);
|
315 | PutString(text);
|
316 | sprintf(&text[0], "Product Rev.: %i.%i\r\n",pCID[8]>>4, pCID[8]&0xF);
|
317 | PutString(text);
|
318 | PutString("Serial No.: ");
|
319 | for(temp1 = 0; temp1<4; temp1++)
|
320 | {
|
321 | sprintf(&text[0],"%02X", pCID[9+temp1]);
|
322 | PutString(text);
|
323 | }
|
324 | PutString("\r\n");
|
325 | temp1 = pCID[14] & 0x0F; // month
|
326 | temp2 = ((pCID[14]>>4)|(pCID[13]<<4)) + 2000; // year
|
327 | sprintf(&text[0], "Manufac. Date: %i/%i\r\n\r\n",temp1, temp2);
|
328 | PutString(text);
|
329 | */
|
330 | }
|
331 |
|
332 | //________________________________________________________________________________________________________________________________________
|
333 | // Funtion: SDC_GetCID(u8 * pCID);
|
334 | //
|
335 | // Description: This function reads the CIS register form the sd card in spi mode.
|
336 | //
|
337 | //
|
338 | // Returnvalue: the function returns error state
|
339 | //________________________________________________________________________________________________________________________________________
|
340 |
|
341 | SD_Result_t SDC_GetCID(u8 * pCID)
|
342 | {
|
343 | return SDC_GetData(CMD_SEND_CID, 0UL, pCID, 16);
|
344 | }
|
345 |
|
346 | //________________________________________________________________________________________________________________________________________
|
347 | // Funtion: SDC_GetCSD(u8 * pCSD);
|
348 | //
|
349 | // Description: This function reads the CSD register form the sd card in spi mode.
|
350 | //
|
351 | //
|
352 | // Returnvalue: the function returns error state
|
353 | //________________________________________________________________________________________________________________________________________
|
354 |
|
355 | SD_Result_t SDC_GetCSD(u8 * pCSD)
|
356 | {
|
357 | return SDC_GetData(CMD_SEND_CSD, 0UL, pCSD, 16);
|
358 | }
|
359 |
|
360 |
|
361 | //________________________________________________________________________________________________________________________________________
|
362 | // Funtion: SDC_Init(void);
|
363 | //
|
364 | // Description: This function initialises the SDCard to spi-mode.
|
365 | //
|
366 | //
|
367 | // Returnvalue: the function returns 0 if the initialisation was successfull otherwise the function returns an errorcode.
|
368 | //________________________________________________________________________________________________________________________________________
|
369 |
|
370 | SD_Result_t SDC_Init(void)
|
371 | {
|
372 | u32 Timeout = 0;
|
373 | u8 rsp[6]; // SD-SPI response buffer
|
374 | SD_Result_t result = SD_ERROR_UNKNOWN;
|
375 |
|
376 | if(1)//CARD_DETECT) // init only if the SD-Switch is indicating a card in the slot
|
377 | {
|
378 | u8 c_size_mult // (M. Mark, Micronas GmbH)
|
379 | u8 read_bl_len; // (M. Mark, Micronas GmbH)
|
380 | u32 c_size; // (M. Mark, Micronas GmbH)
|
381 | SSC_Init();
|
382 | SDCardInfo.Valid = 0;
|
383 | /* The host shall supply power to the card so that the voltage is reached to Vdd_min within 250ms and
|
384 | start to supply at least 74 SD clocks to the SD card with keeping cmd line to high. In case of SPI
|
385 | mode, CS shall be held to high during 74 clock cycles. */
|
386 | SSC_Disable(); // set SD_CS high
|
387 | SSC_ClearRxFifo(); // clear the rx fifo
|
388 |
|
389 | for (Timeout = 0; Timeout < 15; Timeout++) // 15*8 = 120 cycles
|
390 | {
|
391 | SSC_PutChar(0xFF);
|
392 | }
|
393 |
|
394 | // switch to idle state
|
395 | while(!(SDC_SendCMDR1(CMD_GO_IDLE_STATE, 0UL) & R1_IDLE_STATE))
|
396 | {
|
397 | if (Timeout++ > 20)
|
398 | {
|
399 | result = SD_ERROR_RESET;
|
400 | goto end;
|
401 | }
|
402 | }
|
403 | rsp[0] = SDC_SendCMDR1(CMD_SEND_IF_COND, 0x000001AA);
|
404 | // answer to cmd58 is an R7 response (R1+ 4Byte IFCond)
|
405 | if(rsp[0] & R1_BAD_RESPONSE)
|
406 | {
|
407 | result = SD_ERROR_BAD_RESPONSE;
|
408 | goto end;
|
409 | }
|
410 | if(rsp[0] & R1_ILLEGAL_CMD)
|
411 | {
|
412 | //Ver1.X SD Memory Card or not a SD Memory Card
|
413 | SDCardInfo.Version = VER_1X;
|
414 | }
|
415 | else
|
416 | {
|
417 | // Ver2.00 or later SD Memory Card
|
418 | // reading the remaining bytes of the R7 response
|
419 | SDCardInfo.Version = VER_20;
|
420 | for(Timeout = 1; Timeout < 5; Timeout++)
|
421 | {
|
422 | rsp[Timeout] = SSC_GetChar();
|
423 | }
|
424 | //check pattern
|
425 | if(rsp[4]!= 0xAA)
|
426 | {
|
427 | result = SD_ERROR_BAD_RESPONSE;
|
428 | goto end;
|
429 | }
|
430 | if ( (rsp[3] & 0x0F)!= 0x01 ) // voltage range is not 2.7-3.6V
|
431 | {
|
432 | result = SD_ERROR_BAD_VOLTAGE_RANGE;
|
433 | goto end;
|
434 | }
|
435 | }
|
436 |
|
437 | rsp[0] = SDC_SendCMDR1(CMD_READ_OCR, 0UL);
|
438 | // answer to cmd58 is an R3 response (R1 + 4Byte OCR)
|
439 | if(rsp[0] & R1_BAD_RESPONSE)
|
440 | {
|
441 | result = SD_ERROR_BAD_RESPONSE;
|
442 | goto end;
|
443 | }
|
444 | if(rsp[0] & R1_ILLEGAL_CMD)
|
445 | {
|
446 | result = SD_ERROR_NO_SDCARD;
|
447 | goto end;
|
448 | }
|
449 | // read 4 bytes of OCR register
|
450 | for(Timeout = 1; Timeout < 5; Timeout++)
|
451 | {
|
452 | rsp[Timeout] = SSC_GetChar();
|
453 | }
|
454 | // NavicCtrl uses 3.3 V, therefore check for bit 20 & 21
|
455 | if((rsp[2] & 0x30) != 0x30)
|
456 | {
|
457 | // supply voltage is not supported by sd-card
|
458 | result = SD_ERROR_BAD_VOLTAGE_RANGE;
|
459 | goto end;
|
460 | }
|
461 |
|
462 | // Initialize the sd-card sending continously ACMD_SEND_OP_COND (only supported by SD cards)
|
463 | // Timeout = SetDelay(2000); // set timeout to 2000 ms (large cards tend to longer)
|
464 | do
|
465 | {
|
466 | rsp[0] = SDC_SendACMDR1(ACMD_SEND_OP_COND, 0UL);
|
467 | if(rsp[0] & R1_BAD_RESPONSE)
|
468 | {
|
469 | result = SD_ERROR_BAD_RESPONSE;
|
470 | goto end;
|
471 | }
|
472 | /* if(CheckDelay(Timeout))
|
473 | {
|
474 | result = SD_ERROR_INITIALIZE;
|
475 | goto end;
|
476 | }*/
|
477 | } while(rsp[0] & R1_IDLE_STATE); // loop until idle state
|
478 |
|
479 | if(rsp[0] != R1_NO_ERR)
|
480 | {
|
481 | result = SD_ERROR_INITIALIZE;
|
482 | goto end;
|
483 | }
|
484 | /* set block size to 512 bytes */
|
485 | if(SDC_SendCMDR1(CMD_SET_BLOCKLEN, 512UL) != R1_NO_ERR)
|
486 | {
|
487 | result = SD_ERROR_SET_BLOCKLEN;
|
488 | goto end;
|
489 | }
|
490 |
|
491 |
|
492 | // SSC_Init_High(); // init ssc in highspeed mode.
|
493 |
|
494 | // read CID register
|
495 | result = SDC_GetCID((u8 *)&SDCardInfo.CID);
|
496 | if(result != SD_SUCCESS)
|
497 | {
|
498 | goto end;
|
499 | }
|
500 |
|
501 | // read CSD register
|
502 | result = SDC_GetCSD((u8 *)&SDCardInfo.CSD);
|
503 | if(result != SD_SUCCESS)
|
504 | {
|
505 | goto end;
|
506 | }
|
507 |
|
508 | // u8 c_size_mult, read_bl_len; u8 c_size_mult, read_bl_len; // moved variable declaration to top of function (M. Mark, Micronas GmbH)
|
509 | //u32 c_size; // moved variable declaration to top of function (M. Mark, Micronas GmbH)
|
510 |
|
511 | switch(SDCardInfo.CSD[0]>>6) // check CSD Version
|
512 | {
|
513 | case 0x00: // if CSD is V1.0 structure (2GB limit)
|
514 |
|
515 | /*
|
516 | memory capacity = BLOCKNR * BLOCK_LEN
|
517 | BLOCKNR = (C_SIZE+1) * MULT
|
518 | MULT = 2^(C_SIZE_MULT+2)
|
519 | BLOCK_LEN = 2^READ_BL_LEN
|
520 |
|
521 | C_SIZE is 12 bits [73:62] in CSD register
|
522 | C_SIZE_MULT is 3 bits [49:47] in CSD register
|
523 | READ_BL_LEN is 4 bits [83:80] in CSD register
|
524 | */
|
525 |
|
526 | read_bl_len = (SDCardInfo.CSD[5] & 0x0F); //CSD[05] -> [87:80]
|
527 | c_size = ((u32)(SDCardInfo.CSD[6] & 0x03))<<10; //CSD[06] -> [79:72]
|
528 | c_size |= ((u32)SDCardInfo.CSD[7])<<2; //CSD[07] -> [71:64]
|
529 | c_size |= (u32)(SDCardInfo.CSD[8]>>6); //CSD[08] -> [63:56]
|
530 | c_size_mult = (SDCardInfo.CSD[9] & 0x03)<<1; //CSD[09] -> [55:48]
|
531 | c_size_mult |=(SDCardInfo.CSD[10] & 0x80)>>7; //CSD[10] -> [47:40]
|
532 | SDCardInfo.Capacity = (u32)(c_size+1)*(1L<<(c_size_mult+2))*(1L<<read_bl_len);
|
533 | break;
|
534 |
|
535 | case 0x01: // if CSD is V2.0 structure (HC SD-Card > 2GB)
|
536 |
|
537 | /*
|
538 | memory capacity = (C_SIZE+1) * 512K byte
|
539 | C_SIZE is 22 bits [69:48] in CSR register
|
540 | */
|
541 |
|
542 | c_size = ((u32)(SDCardInfo.CSD[7] & 0x3F))<<16; //CSD[07] -> [71:64]
|
543 | c_size |= ((u32)SDCardInfo.CSD[8])<<8; //CSD[08] -> [63:56]
|
544 | c_size |= (u32)SDCardInfo.CSD[9]; //CSD[09] -> [55:48];
|
545 | SDCardInfo.Capacity = (c_size + 1)* 512L * 1024L;
|
546 | break;
|
547 |
|
548 | default: //unknown CSD Version
|
549 | SDCardInfo.Capacity = 0;
|
550 | break;
|
551 | }
|
552 |
|
553 | /* switch(SDCardInfo.Version)
|
554 | {
|
555 | case VER_1X:
|
556 | SerialPutString(" SD-CARD V1.x");
|
557 | break;
|
558 | case VER_20:
|
559 | SerialPutString(" SD-CARD V2.0 or later");
|
560 | default:
|
561 | break;
|
562 | }
|
563 | */
|
564 | // u16 mb_size = (u16)(SDCardInfo.Capacity/(1024L*1024L));
|
565 | // s8 text[40];
|
566 | // sprintf(text,"\r\nsize: %d",mb_size);
|
567 | // PutString(text);
|
568 | // SDC_PrintCID((u8 *)&SDCardInfo.CID);
|
569 | SDCardInfo.Valid = 1;
|
570 |
|
571 | // jump point for error condition before
|
572 | end:
|
573 | SSC_Disable();
|
574 | }
|
575 | else
|
576 | {
|
577 | SDCardInfo.Valid = 0;
|
578 | result = SD_ERROR_NOCARD;
|
579 | }
|
580 |
|
581 | return(result);
|
582 | }
|
583 |
|
584 |
|
585 | //________________________________________________________________________________________________________________________________________
|
586 | // Funtion: SDC_PutSector(void);
|
587 | //
|
588 | // Description: This function writes one sector of data to the SSC
|
589 | //
|
590 | //
|
591 | // Returnvalue: SD_Result_t
|
592 | //________________________________________________________________________________________________________________________________________
|
593 |
|
594 | SD_Result_t SDC_PutSector(u32 addr, const u8 *Buffer)
|
595 | {
|
596 | u8 rsp;
|
597 |
|
598 | u16 timeout = 0;
|
599 | u16 a, Crc16;
|
600 | //u32 Timeout = 0;
|
601 | SD_Result_t result = SD_ERROR_UNKNOWN;
|
602 |
|
603 | addr = addr << 9; // convert sectoradress to byteadress
|
604 | rsp = SDC_SendCMDR1(CMD_WRITE_SINGLE_BLOCK, addr);
|
605 | if (rsp != R1_NO_ERR)
|
606 | {
|
607 | result = SD_ERROR_BAD_RESPONSE;
|
608 | goto end;
|
609 | }
|
610 | SSC_ClearRxFifo();
|
611 | for (a=0;a<20;a++) // at least one byte
|
612 | {
|
613 | SSC_GetChar();
|
614 | }
|
615 | Crc16 = CRC16(Buffer, 512); // calc checksum for data block
|
616 | SSC_PutChar(DATA_START_TOKEN); // send data start of header to the SSC
|
617 |
|
618 | for (a=0;a<512;a++) // transmit one sector (normaly 512bytes) of data to the sdcard.
|
619 | {
|
620 | SSC_PutChar(Buffer[a]);
|
621 | }
|
622 | // write two bytes of crc16 to the sdcard
|
623 | SSC_PutChar((u8)(Crc16>>8)); // write high byte first
|
624 | SSC_PutChar((u8)(0x00FF&Crc16)); // lowbyte last
|
625 | SSC_ClearRxFifo();
|
626 | do // wait for data response token
|
627 | {
|
628 | rsp = SSC_GetChar();
|
629 | if(timeout++>500) break;
|
630 | }while((rsp & 0x11) != 0x01 );
|
631 | // analyse data response token
|
632 | switch(rsp & DATA_RESPONSE_MASK)
|
633 | {
|
634 | case DATA_RESPONSE_OK:
|
635 | result = SD_SUCCESS;
|
636 | break;
|
637 | case DATA_RESPONSE_CRC_ERR:
|
638 | result = SD_ERROR_CRC_DATA;
|
639 | goto end;
|
640 | break;
|
641 | case DATA_RESPONSE_WRITE_ERR:
|
642 | result = SD_ERROR_WRITE_DATA;
|
643 | goto end;
|
644 | break;
|
645 | default:
|
646 | result = SD_ERROR_UNKNOWN;
|
647 | goto end;
|
648 | break;
|
649 |
|
650 | }
|
651 | // wait until the sdcard is busy.
|
652 | rsp = SDC_WaitForBusy();
|
653 | if(rsp != 0xFF)
|
654 | {
|
655 | result = SD_ERROR_TIMEOUT;
|
656 | goto end;
|
657 | }
|
658 | // check card status
|
659 | rsp = SDC_SendCMDR1(CMD_SEND_STATUS, 0);
|
660 | if(rsp != R1_NO_ERR)
|
661 | {
|
662 | result = SD_ERROR_BAD_RESPONSE;
|
663 | SSC_GetChar();
|
664 | goto end;
|
665 | }
|
666 | // 2nd byte of r2 response
|
667 | rsp = SSC_GetChar();
|
668 | if(rsp != R2_NO_ERR)
|
669 | {
|
670 | result = SD_ERROR_WRITE_DATA;
|
671 | SSC_GetChar();
|
672 | goto end;
|
673 | }
|
674 | end:
|
675 | SSC_Disable(); // disable sdcard. WAR AUSKOMMENTIERT!
|
676 | return(result);
|
677 | }
|
678 |
|
679 |
|
680 | //________________________________________________________________________________________________________________________________________
|
681 | // Funtion: SDC_GetSector(u32 addr,u8 *Buffer);
|
682 | //
|
683 | // Description: This function reads one sector of data from the SSC
|
684 | //
|
685 | //
|
686 | // Returnvalue: SD_Result_t
|
687 | //________________________________________________________________________________________________________________________________________
|
688 |
|
689 | SD_Result_t SDC_GetSector(u32 addr,u8 *Buffer)
|
690 | {
|
691 | addr = addr << 9; // convert sectoradress to byteadress
|
692 | return SDC_GetData(CMD_READ_SINGLE_BLOCK, addr, Buffer, 512);
|
693 | }
|