Mercurial > ~darius > hgwebdir.cgi > stm32temp
comparison libs/STM32F10x_StdPeriph_Lib_V3.5.0/Utilities/STM32_EVAL/Common/stm32_eval_spi_sd.c @ 0:c59513fd84fb
Initial commit of STM32 test code.
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Mon, 03 Oct 2011 21:19:15 +1030 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c59513fd84fb |
---|---|
1 /** | |
2 ****************************************************************************** | |
3 * @file stm32_eval_spi_sd.c | |
4 * @author MCD Application Team | |
5 * @version V4.5.0 | |
6 * @date 07-March-2011 | |
7 * @brief This file provides a set of functions needed to manage the SPI SD | |
8 * Card memory mounted on STM32xx-EVAL board (refer to stm32_eval.h | |
9 * to know about the boards supporting this memory). | |
10 * It implements a high level communication layer for read and write | |
11 * from/to this memory. The needed STM32 hardware resources (SPI and | |
12 * GPIO) are defined in stm32xx_eval.h file, and the initialization is | |
13 * performed in SD_LowLevel_Init() function declared in stm32xx_eval.c | |
14 * file. | |
15 * You can easily tailor this driver to any other development board, | |
16 * by just adapting the defines for hardware resources and | |
17 * SD_LowLevel_Init() function. | |
18 * | |
19 * +-------------------------------------------------------+ | |
20 * | Pin assignment | | |
21 * +-------------------------+---------------+-------------+ | |
22 * | STM32 SPI Pins | SD | Pin | | |
23 * +-------------------------+---------------+-------------+ | |
24 * | SD_SPI_CS_PIN | ChipSelect | 1 | | |
25 * | SD_SPI_MOSI_PIN / MOSI | DataIn | 2 | | |
26 * | | GND | 3 (0 V) | | |
27 * | | VDD | 4 (3.3 V)| | |
28 * | SD_SPI_SCK_PIN / SCLK | Clock | 5 | | |
29 * | | GND | 6 (0 V) | | |
30 * | SD_SPI_MISO_PIN / MISO | DataOut | 7 | | |
31 * +-------------------------+---------------+-------------+ | |
32 ****************************************************************************** | |
33 * @attention | |
34 * | |
35 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS | |
36 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE | |
37 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY | |
38 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING | |
39 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE | |
40 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. | |
41 * | |
42 * <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2> | |
43 ****************************************************************************** | |
44 */ | |
45 | |
46 /* Includes ------------------------------------------------------------------*/ | |
47 #include "stm32_eval_spi_sd.h" | |
48 | |
49 /** @addtogroup Utilities | |
50 * @{ | |
51 */ | |
52 | |
53 /** @addtogroup STM32_EVAL | |
54 * @{ | |
55 */ | |
56 | |
57 /** @addtogroup Common | |
58 * @{ | |
59 */ | |
60 | |
61 /** @addtogroup STM32_EVAL_SPI_SD | |
62 * @brief This file includes the SD card driver of STM32-EVAL boards. | |
63 * @{ | |
64 */ | |
65 | |
66 /** @defgroup STM32_EVAL_SPI_SD_Private_Types | |
67 * @{ | |
68 */ | |
69 /** | |
70 * @} | |
71 */ | |
72 | |
73 | |
74 /** @defgroup STM32_EVAL_SPI_SD_Private_Defines | |
75 * @{ | |
76 */ | |
77 /** | |
78 * @} | |
79 */ | |
80 | |
81 /** @defgroup STM32_EVAL_SPI_SD_Private_Macros | |
82 * @{ | |
83 */ | |
84 /** | |
85 * @} | |
86 */ | |
87 | |
88 | |
89 /** @defgroup STM32_EVAL_SPI_SD_Private_Variables | |
90 * @{ | |
91 */ | |
92 /** | |
93 * @} | |
94 */ | |
95 | |
96 | |
97 /** @defgroup STM32_EVAL_SPI_SD_Private_Function_Prototypes | |
98 * @{ | |
99 */ | |
100 /** | |
101 * @} | |
102 */ | |
103 | |
104 | |
105 /** @defgroup STM32_EVAL_SPI_SD_Private_Functions | |
106 * @{ | |
107 */ | |
108 | |
109 /** | |
110 * @brief DeInitializes the SD/SD communication. | |
111 * @param None | |
112 * @retval None | |
113 */ | |
114 void SD_DeInit(void) | |
115 { | |
116 SD_LowLevel_DeInit(); | |
117 } | |
118 | |
119 /** | |
120 * @brief Initializes the SD/SD communication. | |
121 * @param None | |
122 * @retval The SD Response: | |
123 * - SD_RESPONSE_FAILURE: Sequence failed | |
124 * - SD_RESPONSE_NO_ERROR: Sequence succeed | |
125 */ | |
126 SD_Error SD_Init(void) | |
127 { | |
128 uint32_t i = 0; | |
129 | |
130 /*!< Initialize SD_SPI */ | |
131 SD_LowLevel_Init(); | |
132 | |
133 /*!< SD chip select high */ | |
134 SD_CS_HIGH(); | |
135 | |
136 /*!< Send dummy byte 0xFF, 10 times with CS high */ | |
137 /*!< Rise CS and MOSI for 80 clocks cycles */ | |
138 for (i = 0; i <= 9; i++) | |
139 { | |
140 /*!< Send dummy byte 0xFF */ | |
141 SD_WriteByte(SD_DUMMY_BYTE); | |
142 } | |
143 /*------------Put SD in SPI mode--------------*/ | |
144 /*!< SD initialized and set to SPI mode properly */ | |
145 return (SD_GoIdleState()); | |
146 } | |
147 | |
148 /** | |
149 * @brief Detect if SD card is correctly plugged in the memory slot. | |
150 * @param None | |
151 * @retval Return if SD is detected or not | |
152 */ | |
153 uint8_t SD_Detect(void) | |
154 { | |
155 __IO uint8_t status = SD_PRESENT; | |
156 | |
157 /*!< Check GPIO to detect SD */ | |
158 if (GPIO_ReadInputData(SD_DETECT_GPIO_PORT) & SD_DETECT_PIN) | |
159 { | |
160 status = SD_NOT_PRESENT; | |
161 } | |
162 return status; | |
163 } | |
164 | |
165 /** | |
166 * @brief Returns information about specific card. | |
167 * @param cardinfo: pointer to a SD_CardInfo structure that contains all SD | |
168 * card information. | |
169 * @retval The SD Response: | |
170 * - SD_RESPONSE_FAILURE: Sequence failed | |
171 * - SD_RESPONSE_NO_ERROR: Sequence succeed | |
172 */ | |
173 SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo) | |
174 { | |
175 SD_Error status = SD_RESPONSE_FAILURE; | |
176 | |
177 status = SD_GetCSDRegister(&(cardinfo->SD_csd)); | |
178 status = SD_GetCIDRegister(&(cardinfo->SD_cid)); | |
179 cardinfo->CardCapacity = (cardinfo->SD_csd.DeviceSize + 1) ; | |
180 cardinfo->CardCapacity *= (1 << (cardinfo->SD_csd.DeviceSizeMul + 2)); | |
181 cardinfo->CardBlockSize = 1 << (cardinfo->SD_csd.RdBlockLen); | |
182 cardinfo->CardCapacity *= cardinfo->CardBlockSize; | |
183 | |
184 /*!< Returns the reponse */ | |
185 return status; | |
186 } | |
187 | |
188 /** | |
189 * @brief Reads a block of data from the SD. | |
190 * @param pBuffer: pointer to the buffer that receives the data read from the | |
191 * SD. | |
192 * @param ReadAddr: SD's internal address to read from. | |
193 * @param BlockSize: the SD card Data block size. | |
194 * @retval The SD Response: | |
195 * - SD_RESPONSE_FAILURE: Sequence failed | |
196 * - SD_RESPONSE_NO_ERROR: Sequence succeed | |
197 */ | |
198 SD_Error SD_ReadBlock(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t BlockSize) | |
199 { | |
200 uint32_t i = 0; | |
201 SD_Error rvalue = SD_RESPONSE_FAILURE; | |
202 | |
203 /*!< SD chip select low */ | |
204 SD_CS_LOW(); | |
205 | |
206 /*!< Send CMD17 (SD_CMD_READ_SINGLE_BLOCK) to read one block */ | |
207 SD_SendCmd(SD_CMD_READ_SINGLE_BLOCK, ReadAddr, 0xFF); | |
208 | |
209 /*!< Check if the SD acknowledged the read block command: R1 response (0x00: no errors) */ | |
210 if (!SD_GetResponse(SD_RESPONSE_NO_ERROR)) | |
211 { | |
212 /*!< Now look for the data token to signify the start of the data */ | |
213 if (!SD_GetResponse(SD_START_DATA_SINGLE_BLOCK_READ)) | |
214 { | |
215 /*!< Read the SD block data : read NumByteToRead data */ | |
216 for (i = 0; i < BlockSize; i++) | |
217 { | |
218 /*!< Save the received data */ | |
219 *pBuffer = SD_ReadByte(); | |
220 | |
221 /*!< Point to the next location where the byte read will be saved */ | |
222 pBuffer++; | |
223 } | |
224 /*!< Get CRC bytes (not really needed by us, but required by SD) */ | |
225 SD_ReadByte(); | |
226 SD_ReadByte(); | |
227 /*!< Set response value to success */ | |
228 rvalue = SD_RESPONSE_NO_ERROR; | |
229 } | |
230 } | |
231 /*!< SD chip select high */ | |
232 SD_CS_HIGH(); | |
233 | |
234 /*!< Send dummy byte: 8 Clock pulses of delay */ | |
235 SD_WriteByte(SD_DUMMY_BYTE); | |
236 | |
237 /*!< Returns the reponse */ | |
238 return rvalue; | |
239 } | |
240 | |
241 /** | |
242 * @brief Reads multiple block of data from the SD. | |
243 * @param pBuffer: pointer to the buffer that receives the data read from the | |
244 * SD. | |
245 * @param ReadAddr: SD's internal address to read from. | |
246 * @param BlockSize: the SD card Data block size. | |
247 * @param NumberOfBlocks: number of blocks to be read. | |
248 * @retval The SD Response: | |
249 * - SD_RESPONSE_FAILURE: Sequence failed | |
250 * - SD_RESPONSE_NO_ERROR: Sequence succeed | |
251 */ | |
252 SD_Error SD_ReadMultiBlocks(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks) | |
253 { | |
254 uint32_t i = 0, Offset = 0; | |
255 SD_Error rvalue = SD_RESPONSE_FAILURE; | |
256 | |
257 /*!< SD chip select low */ | |
258 SD_CS_LOW(); | |
259 /*!< Data transfer */ | |
260 while (NumberOfBlocks--) | |
261 { | |
262 /*!< Send CMD17 (SD_CMD_READ_SINGLE_BLOCK) to read one block */ | |
263 SD_SendCmd (SD_CMD_READ_SINGLE_BLOCK, ReadAddr + Offset, 0xFF); | |
264 /*!< Check if the SD acknowledged the read block command: R1 response (0x00: no errors) */ | |
265 if (SD_GetResponse(SD_RESPONSE_NO_ERROR)) | |
266 { | |
267 return SD_RESPONSE_FAILURE; | |
268 } | |
269 /*!< Now look for the data token to signify the start of the data */ | |
270 if (!SD_GetResponse(SD_START_DATA_SINGLE_BLOCK_READ)) | |
271 { | |
272 /*!< Read the SD block data : read NumByteToRead data */ | |
273 for (i = 0; i < BlockSize; i++) | |
274 { | |
275 /*!< Read the pointed data */ | |
276 *pBuffer = SD_ReadByte(); | |
277 /*!< Point to the next location where the byte read will be saved */ | |
278 pBuffer++; | |
279 } | |
280 /*!< Set next read address*/ | |
281 Offset += 512; | |
282 /*!< get CRC bytes (not really needed by us, but required by SD) */ | |
283 SD_ReadByte(); | |
284 SD_ReadByte(); | |
285 /*!< Set response value to success */ | |
286 rvalue = SD_RESPONSE_NO_ERROR; | |
287 } | |
288 else | |
289 { | |
290 /*!< Set response value to failure */ | |
291 rvalue = SD_RESPONSE_FAILURE; | |
292 } | |
293 } | |
294 /*!< SD chip select high */ | |
295 SD_CS_HIGH(); | |
296 /*!< Send dummy byte: 8 Clock pulses of delay */ | |
297 SD_WriteByte(SD_DUMMY_BYTE); | |
298 /*!< Returns the reponse */ | |
299 return rvalue; | |
300 } | |
301 | |
302 /** | |
303 * @brief Writes a block on the SD | |
304 * @param pBuffer: pointer to the buffer containing the data to be written on | |
305 * the SD. | |
306 * @param WriteAddr: address to write on. | |
307 * @param BlockSize: the SD card Data block size. | |
308 * @retval The SD Response: | |
309 * - SD_RESPONSE_FAILURE: Sequence failed | |
310 * - SD_RESPONSE_NO_ERROR: Sequence succeed | |
311 */ | |
312 SD_Error SD_WriteBlock(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t BlockSize) | |
313 { | |
314 uint32_t i = 0; | |
315 SD_Error rvalue = SD_RESPONSE_FAILURE; | |
316 | |
317 /*!< SD chip select low */ | |
318 SD_CS_LOW(); | |
319 | |
320 /*!< Send CMD24 (SD_CMD_WRITE_SINGLE_BLOCK) to write multiple block */ | |
321 SD_SendCmd(SD_CMD_WRITE_SINGLE_BLOCK, WriteAddr, 0xFF); | |
322 | |
323 /*!< Check if the SD acknowledged the write block command: R1 response (0x00: no errors) */ | |
324 if (!SD_GetResponse(SD_RESPONSE_NO_ERROR)) | |
325 { | |
326 /*!< Send a dummy byte */ | |
327 SD_WriteByte(SD_DUMMY_BYTE); | |
328 | |
329 /*!< Send the data token to signify the start of the data */ | |
330 SD_WriteByte(0xFE); | |
331 | |
332 /*!< Write the block data to SD : write count data by block */ | |
333 for (i = 0; i < BlockSize; i++) | |
334 { | |
335 /*!< Send the pointed byte */ | |
336 SD_WriteByte(*pBuffer); | |
337 /*!< Point to the next location where the byte read will be saved */ | |
338 pBuffer++; | |
339 } | |
340 /*!< Put CRC bytes (not really needed by us, but required by SD) */ | |
341 SD_ReadByte(); | |
342 SD_ReadByte(); | |
343 | |
344 /*!< Read data response */ | |
345 if (SD_GetDataResponse() == SD_DATA_OK) | |
346 { | |
347 rvalue = SD_RESPONSE_NO_ERROR; | |
348 } | |
349 } | |
350 /*!< SD chip select high */ | |
351 SD_CS_HIGH(); | |
352 /*!< Send dummy byte: 8 Clock pulses of delay */ | |
353 SD_WriteByte(SD_DUMMY_BYTE); | |
354 | |
355 /*!< Returns the reponse */ | |
356 return rvalue; | |
357 } | |
358 | |
359 /** | |
360 * @brief Writes many blocks on the SD | |
361 * @param pBuffer: pointer to the buffer containing the data to be written on | |
362 * the SD. | |
363 * @param WriteAddr: address to write on. | |
364 * @param BlockSize: the SD card Data block size. | |
365 * @param NumberOfBlocks: number of blocks to be written. | |
366 * @retval The SD Response: | |
367 * - SD_RESPONSE_FAILURE: Sequence failed | |
368 * - SD_RESPONSE_NO_ERROR: Sequence succeed | |
369 */ | |
370 SD_Error SD_WriteMultiBlocks(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks) | |
371 { | |
372 uint32_t i = 0, Offset = 0; | |
373 SD_Error rvalue = SD_RESPONSE_FAILURE; | |
374 | |
375 /*!< SD chip select low */ | |
376 SD_CS_LOW(); | |
377 /*!< Data transfer */ | |
378 while (NumberOfBlocks--) | |
379 { | |
380 /*!< Send CMD24 (SD_CMD_WRITE_SINGLE_BLOCK) to write blocks */ | |
381 SD_SendCmd(SD_CMD_WRITE_SINGLE_BLOCK, WriteAddr + Offset, 0xFF); | |
382 /*!< Check if the SD acknowledged the write block command: R1 response (0x00: no errors) */ | |
383 if (SD_GetResponse(SD_RESPONSE_NO_ERROR)) | |
384 { | |
385 return SD_RESPONSE_FAILURE; | |
386 } | |
387 /*!< Send dummy byte */ | |
388 SD_WriteByte(SD_DUMMY_BYTE); | |
389 /*!< Send the data token to signify the start of the data */ | |
390 SD_WriteByte(SD_START_DATA_SINGLE_BLOCK_WRITE); | |
391 /*!< Write the block data to SD : write count data by block */ | |
392 for (i = 0; i < BlockSize; i++) | |
393 { | |
394 /*!< Send the pointed byte */ | |
395 SD_WriteByte(*pBuffer); | |
396 /*!< Point to the next location where the byte read will be saved */ | |
397 pBuffer++; | |
398 } | |
399 /*!< Set next write address */ | |
400 Offset += 512; | |
401 /*!< Put CRC bytes (not really needed by us, but required by SD) */ | |
402 SD_ReadByte(); | |
403 SD_ReadByte(); | |
404 /*!< Read data response */ | |
405 if (SD_GetDataResponse() == SD_DATA_OK) | |
406 { | |
407 /*!< Set response value to success */ | |
408 rvalue = SD_RESPONSE_NO_ERROR; | |
409 } | |
410 else | |
411 { | |
412 /*!< Set response value to failure */ | |
413 rvalue = SD_RESPONSE_FAILURE; | |
414 } | |
415 } | |
416 /*!< SD chip select high */ | |
417 SD_CS_HIGH(); | |
418 /*!< Send dummy byte: 8 Clock pulses of delay */ | |
419 SD_WriteByte(SD_DUMMY_BYTE); | |
420 /*!< Returns the reponse */ | |
421 return rvalue; | |
422 } | |
423 | |
424 /** | |
425 * @brief Read the CSD card register. | |
426 * Reading the contents of the CSD register in SPI mode is a simple | |
427 * read-block transaction. | |
428 * @param SD_csd: pointer on an SCD register structure | |
429 * @retval The SD Response: | |
430 * - SD_RESPONSE_FAILURE: Sequence failed | |
431 * - SD_RESPONSE_NO_ERROR: Sequence succeed | |
432 */ | |
433 SD_Error SD_GetCSDRegister(SD_CSD* SD_csd) | |
434 { | |
435 uint32_t i = 0; | |
436 SD_Error rvalue = SD_RESPONSE_FAILURE; | |
437 uint8_t CSD_Tab[16]; | |
438 | |
439 /*!< SD chip select low */ | |
440 SD_CS_LOW(); | |
441 /*!< Send CMD9 (CSD register) or CMD10(CSD register) */ | |
442 SD_SendCmd(SD_CMD_SEND_CSD, 0, 0xFF); | |
443 /*!< Wait for response in the R1 format (0x00 is no errors) */ | |
444 if (!SD_GetResponse(SD_RESPONSE_NO_ERROR)) | |
445 { | |
446 if (!SD_GetResponse(SD_START_DATA_SINGLE_BLOCK_READ)) | |
447 { | |
448 for (i = 0; i < 16; i++) | |
449 { | |
450 /*!< Store CSD register value on CSD_Tab */ | |
451 CSD_Tab[i] = SD_ReadByte(); | |
452 } | |
453 } | |
454 /*!< Get CRC bytes (not really needed by us, but required by SD) */ | |
455 SD_WriteByte(SD_DUMMY_BYTE); | |
456 SD_WriteByte(SD_DUMMY_BYTE); | |
457 /*!< Set response value to success */ | |
458 rvalue = SD_RESPONSE_NO_ERROR; | |
459 } | |
460 /*!< SD chip select high */ | |
461 SD_CS_HIGH(); | |
462 /*!< Send dummy byte: 8 Clock pulses of delay */ | |
463 SD_WriteByte(SD_DUMMY_BYTE); | |
464 | |
465 /*!< Byte 0 */ | |
466 SD_csd->CSDStruct = (CSD_Tab[0] & 0xC0) >> 6; | |
467 SD_csd->SysSpecVersion = (CSD_Tab[0] & 0x3C) >> 2; | |
468 SD_csd->Reserved1 = CSD_Tab[0] & 0x03; | |
469 | |
470 /*!< Byte 1 */ | |
471 SD_csd->TAAC = CSD_Tab[1]; | |
472 | |
473 /*!< Byte 2 */ | |
474 SD_csd->NSAC = CSD_Tab[2]; | |
475 | |
476 /*!< Byte 3 */ | |
477 SD_csd->MaxBusClkFrec = CSD_Tab[3]; | |
478 | |
479 /*!< Byte 4 */ | |
480 SD_csd->CardComdClasses = CSD_Tab[4] << 4; | |
481 | |
482 /*!< Byte 5 */ | |
483 SD_csd->CardComdClasses |= (CSD_Tab[5] & 0xF0) >> 4; | |
484 SD_csd->RdBlockLen = CSD_Tab[5] & 0x0F; | |
485 | |
486 /*!< Byte 6 */ | |
487 SD_csd->PartBlockRead = (CSD_Tab[6] & 0x80) >> 7; | |
488 SD_csd->WrBlockMisalign = (CSD_Tab[6] & 0x40) >> 6; | |
489 SD_csd->RdBlockMisalign = (CSD_Tab[6] & 0x20) >> 5; | |
490 SD_csd->DSRImpl = (CSD_Tab[6] & 0x10) >> 4; | |
491 SD_csd->Reserved2 = 0; /*!< Reserved */ | |
492 | |
493 SD_csd->DeviceSize = (CSD_Tab[6] & 0x03) << 10; | |
494 | |
495 /*!< Byte 7 */ | |
496 SD_csd->DeviceSize |= (CSD_Tab[7]) << 2; | |
497 | |
498 /*!< Byte 8 */ | |
499 SD_csd->DeviceSize |= (CSD_Tab[8] & 0xC0) >> 6; | |
500 | |
501 SD_csd->MaxRdCurrentVDDMin = (CSD_Tab[8] & 0x38) >> 3; | |
502 SD_csd->MaxRdCurrentVDDMax = (CSD_Tab[8] & 0x07); | |
503 | |
504 /*!< Byte 9 */ | |
505 SD_csd->MaxWrCurrentVDDMin = (CSD_Tab[9] & 0xE0) >> 5; | |
506 SD_csd->MaxWrCurrentVDDMax = (CSD_Tab[9] & 0x1C) >> 2; | |
507 SD_csd->DeviceSizeMul = (CSD_Tab[9] & 0x03) << 1; | |
508 /*!< Byte 10 */ | |
509 SD_csd->DeviceSizeMul |= (CSD_Tab[10] & 0x80) >> 7; | |
510 | |
511 SD_csd->EraseGrSize = (CSD_Tab[10] & 0x40) >> 6; | |
512 SD_csd->EraseGrMul = (CSD_Tab[10] & 0x3F) << 1; | |
513 | |
514 /*!< Byte 11 */ | |
515 SD_csd->EraseGrMul |= (CSD_Tab[11] & 0x80) >> 7; | |
516 SD_csd->WrProtectGrSize = (CSD_Tab[11] & 0x7F); | |
517 | |
518 /*!< Byte 12 */ | |
519 SD_csd->WrProtectGrEnable = (CSD_Tab[12] & 0x80) >> 7; | |
520 SD_csd->ManDeflECC = (CSD_Tab[12] & 0x60) >> 5; | |
521 SD_csd->WrSpeedFact = (CSD_Tab[12] & 0x1C) >> 2; | |
522 SD_csd->MaxWrBlockLen = (CSD_Tab[12] & 0x03) << 2; | |
523 | |
524 /*!< Byte 13 */ | |
525 SD_csd->MaxWrBlockLen |= (CSD_Tab[13] & 0xC0) >> 6; | |
526 SD_csd->WriteBlockPaPartial = (CSD_Tab[13] & 0x20) >> 5; | |
527 SD_csd->Reserved3 = 0; | |
528 SD_csd->ContentProtectAppli = (CSD_Tab[13] & 0x01); | |
529 | |
530 /*!< Byte 14 */ | |
531 SD_csd->FileFormatGrouop = (CSD_Tab[14] & 0x80) >> 7; | |
532 SD_csd->CopyFlag = (CSD_Tab[14] & 0x40) >> 6; | |
533 SD_csd->PermWrProtect = (CSD_Tab[14] & 0x20) >> 5; | |
534 SD_csd->TempWrProtect = (CSD_Tab[14] & 0x10) >> 4; | |
535 SD_csd->FileFormat = (CSD_Tab[14] & 0x0C) >> 2; | |
536 SD_csd->ECC = (CSD_Tab[14] & 0x03); | |
537 | |
538 /*!< Byte 15 */ | |
539 SD_csd->CSD_CRC = (CSD_Tab[15] & 0xFE) >> 1; | |
540 SD_csd->Reserved4 = 1; | |
541 | |
542 /*!< Return the reponse */ | |
543 return rvalue; | |
544 } | |
545 | |
546 /** | |
547 * @brief Read the CID card register. | |
548 * Reading the contents of the CID register in SPI mode is a simple | |
549 * read-block transaction. | |
550 * @param SD_cid: pointer on an CID register structure | |
551 * @retval The SD Response: | |
552 * - SD_RESPONSE_FAILURE: Sequence failed | |
553 * - SD_RESPONSE_NO_ERROR: Sequence succeed | |
554 */ | |
555 SD_Error SD_GetCIDRegister(SD_CID* SD_cid) | |
556 { | |
557 uint32_t i = 0; | |
558 SD_Error rvalue = SD_RESPONSE_FAILURE; | |
559 uint8_t CID_Tab[16]; | |
560 | |
561 /*!< SD chip select low */ | |
562 SD_CS_LOW(); | |
563 | |
564 /*!< Send CMD10 (CID register) */ | |
565 SD_SendCmd(SD_CMD_SEND_CID, 0, 0xFF); | |
566 | |
567 /*!< Wait for response in the R1 format (0x00 is no errors) */ | |
568 if (!SD_GetResponse(SD_RESPONSE_NO_ERROR)) | |
569 { | |
570 if (!SD_GetResponse(SD_START_DATA_SINGLE_BLOCK_READ)) | |
571 { | |
572 /*!< Store CID register value on CID_Tab */ | |
573 for (i = 0; i < 16; i++) | |
574 { | |
575 CID_Tab[i] = SD_ReadByte(); | |
576 } | |
577 } | |
578 /*!< Get CRC bytes (not really needed by us, but required by SD) */ | |
579 SD_WriteByte(SD_DUMMY_BYTE); | |
580 SD_WriteByte(SD_DUMMY_BYTE); | |
581 /*!< Set response value to success */ | |
582 rvalue = SD_RESPONSE_NO_ERROR; | |
583 } | |
584 /*!< SD chip select high */ | |
585 SD_CS_HIGH(); | |
586 /*!< Send dummy byte: 8 Clock pulses of delay */ | |
587 SD_WriteByte(SD_DUMMY_BYTE); | |
588 | |
589 /*!< Byte 0 */ | |
590 SD_cid->ManufacturerID = CID_Tab[0]; | |
591 | |
592 /*!< Byte 1 */ | |
593 SD_cid->OEM_AppliID = CID_Tab[1] << 8; | |
594 | |
595 /*!< Byte 2 */ | |
596 SD_cid->OEM_AppliID |= CID_Tab[2]; | |
597 | |
598 /*!< Byte 3 */ | |
599 SD_cid->ProdName1 = CID_Tab[3] << 24; | |
600 | |
601 /*!< Byte 4 */ | |
602 SD_cid->ProdName1 |= CID_Tab[4] << 16; | |
603 | |
604 /*!< Byte 5 */ | |
605 SD_cid->ProdName1 |= CID_Tab[5] << 8; | |
606 | |
607 /*!< Byte 6 */ | |
608 SD_cid->ProdName1 |= CID_Tab[6]; | |
609 | |
610 /*!< Byte 7 */ | |
611 SD_cid->ProdName2 = CID_Tab[7]; | |
612 | |
613 /*!< Byte 8 */ | |
614 SD_cid->ProdRev = CID_Tab[8]; | |
615 | |
616 /*!< Byte 9 */ | |
617 SD_cid->ProdSN = CID_Tab[9] << 24; | |
618 | |
619 /*!< Byte 10 */ | |
620 SD_cid->ProdSN |= CID_Tab[10] << 16; | |
621 | |
622 /*!< Byte 11 */ | |
623 SD_cid->ProdSN |= CID_Tab[11] << 8; | |
624 | |
625 /*!< Byte 12 */ | |
626 SD_cid->ProdSN |= CID_Tab[12]; | |
627 | |
628 /*!< Byte 13 */ | |
629 SD_cid->Reserved1 |= (CID_Tab[13] & 0xF0) >> 4; | |
630 SD_cid->ManufactDate = (CID_Tab[13] & 0x0F) << 8; | |
631 | |
632 /*!< Byte 14 */ | |
633 SD_cid->ManufactDate |= CID_Tab[14]; | |
634 | |
635 /*!< Byte 15 */ | |
636 SD_cid->CID_CRC = (CID_Tab[15] & 0xFE) >> 1; | |
637 SD_cid->Reserved2 = 1; | |
638 | |
639 /*!< Return the reponse */ | |
640 return rvalue; | |
641 } | |
642 | |
643 /** | |
644 * @brief Send 5 bytes command to the SD card. | |
645 * @param Cmd: The user expected command to send to SD card. | |
646 * @param Arg: The command argument. | |
647 * @param Crc: The CRC. | |
648 * @retval None | |
649 */ | |
650 void SD_SendCmd(uint8_t Cmd, uint32_t Arg, uint8_t Crc) | |
651 { | |
652 uint32_t i = 0x00; | |
653 | |
654 uint8_t Frame[6]; | |
655 | |
656 Frame[0] = (Cmd | 0x40); /*!< Construct byte 1 */ | |
657 | |
658 Frame[1] = (uint8_t)(Arg >> 24); /*!< Construct byte 2 */ | |
659 | |
660 Frame[2] = (uint8_t)(Arg >> 16); /*!< Construct byte 3 */ | |
661 | |
662 Frame[3] = (uint8_t)(Arg >> 8); /*!< Construct byte 4 */ | |
663 | |
664 Frame[4] = (uint8_t)(Arg); /*!< Construct byte 5 */ | |
665 | |
666 Frame[5] = (Crc); /*!< Construct CRC: byte 6 */ | |
667 | |
668 for (i = 0; i < 6; i++) | |
669 { | |
670 SD_WriteByte(Frame[i]); /*!< Send the Cmd bytes */ | |
671 } | |
672 } | |
673 | |
674 /** | |
675 * @brief Get SD card data response. | |
676 * @param None | |
677 * @retval The SD status: Read data response xxx0<status>1 | |
678 * - status 010: Data accecpted | |
679 * - status 101: Data rejected due to a crc error | |
680 * - status 110: Data rejected due to a Write error. | |
681 * - status 111: Data rejected due to other error. | |
682 */ | |
683 uint8_t SD_GetDataResponse(void) | |
684 { | |
685 uint32_t i = 0; | |
686 uint8_t response, rvalue; | |
687 | |
688 while (i <= 64) | |
689 { | |
690 /*!< Read resonse */ | |
691 response = SD_ReadByte(); | |
692 /*!< Mask unused bits */ | |
693 response &= 0x1F; | |
694 switch (response) | |
695 { | |
696 case SD_DATA_OK: | |
697 { | |
698 rvalue = SD_DATA_OK; | |
699 break; | |
700 } | |
701 case SD_DATA_CRC_ERROR: | |
702 return SD_DATA_CRC_ERROR; | |
703 case SD_DATA_WRITE_ERROR: | |
704 return SD_DATA_WRITE_ERROR; | |
705 default: | |
706 { | |
707 rvalue = SD_DATA_OTHER_ERROR; | |
708 break; | |
709 } | |
710 } | |
711 /*!< Exit loop in case of data ok */ | |
712 if (rvalue == SD_DATA_OK) | |
713 break; | |
714 /*!< Increment loop counter */ | |
715 i++; | |
716 } | |
717 | |
718 /*!< Wait null data */ | |
719 while (SD_ReadByte() == 0); | |
720 | |
721 /*!< Return response */ | |
722 return response; | |
723 } | |
724 | |
725 /** | |
726 * @brief Returns the SD response. | |
727 * @param None | |
728 * @retval The SD Response: | |
729 * - SD_RESPONSE_FAILURE: Sequence failed | |
730 * - SD_RESPONSE_NO_ERROR: Sequence succeed | |
731 */ | |
732 SD_Error SD_GetResponse(uint8_t Response) | |
733 { | |
734 uint32_t Count = 0xFFF; | |
735 | |
736 /*!< Check if response is got or a timeout is happen */ | |
737 while ((SD_ReadByte() != Response) && Count) | |
738 { | |
739 Count--; | |
740 } | |
741 if (Count == 0) | |
742 { | |
743 /*!< After time out */ | |
744 return SD_RESPONSE_FAILURE; | |
745 } | |
746 else | |
747 { | |
748 /*!< Right response got */ | |
749 return SD_RESPONSE_NO_ERROR; | |
750 } | |
751 } | |
752 | |
753 /** | |
754 * @brief Returns the SD status. | |
755 * @param None | |
756 * @retval The SD status. | |
757 */ | |
758 uint16_t SD_GetStatus(void) | |
759 { | |
760 uint16_t Status = 0; | |
761 | |
762 /*!< SD chip select low */ | |
763 SD_CS_LOW(); | |
764 | |
765 /*!< Send CMD13 (SD_SEND_STATUS) to get SD status */ | |
766 SD_SendCmd(SD_CMD_SEND_STATUS, 0, 0xFF); | |
767 | |
768 Status = SD_ReadByte(); | |
769 Status |= (uint16_t)(SD_ReadByte() << 8); | |
770 | |
771 /*!< SD chip select high */ | |
772 SD_CS_HIGH(); | |
773 | |
774 /*!< Send dummy byte 0xFF */ | |
775 SD_WriteByte(SD_DUMMY_BYTE); | |
776 | |
777 return Status; | |
778 } | |
779 | |
780 /** | |
781 * @brief Put SD in Idle state. | |
782 * @param None | |
783 * @retval The SD Response: | |
784 * - SD_RESPONSE_FAILURE: Sequence failed | |
785 * - SD_RESPONSE_NO_ERROR: Sequence succeed | |
786 */ | |
787 SD_Error SD_GoIdleState(void) | |
788 { | |
789 /*!< SD chip select low */ | |
790 SD_CS_LOW(); | |
791 | |
792 /*!< Send CMD0 (SD_CMD_GO_IDLE_STATE) to put SD in SPI mode */ | |
793 SD_SendCmd(SD_CMD_GO_IDLE_STATE, 0, 0x95); | |
794 | |
795 /*!< Wait for In Idle State Response (R1 Format) equal to 0x01 */ | |
796 if (SD_GetResponse(SD_IN_IDLE_STATE)) | |
797 { | |
798 /*!< No Idle State Response: return response failue */ | |
799 return SD_RESPONSE_FAILURE; | |
800 } | |
801 /*----------Activates the card initialization process-----------*/ | |
802 do | |
803 { | |
804 /*!< SD chip select high */ | |
805 SD_CS_HIGH(); | |
806 | |
807 /*!< Send Dummy byte 0xFF */ | |
808 SD_WriteByte(SD_DUMMY_BYTE); | |
809 | |
810 /*!< SD chip select low */ | |
811 SD_CS_LOW(); | |
812 | |
813 /*!< Send CMD1 (Activates the card process) until response equal to 0x0 */ | |
814 SD_SendCmd(SD_CMD_SEND_OP_COND, 0, 0xFF); | |
815 /*!< Wait for no error Response (R1 Format) equal to 0x00 */ | |
816 } | |
817 while (SD_GetResponse(SD_RESPONSE_NO_ERROR)); | |
818 | |
819 /*!< SD chip select high */ | |
820 SD_CS_HIGH(); | |
821 | |
822 /*!< Send dummy byte 0xFF */ | |
823 SD_WriteByte(SD_DUMMY_BYTE); | |
824 | |
825 return SD_RESPONSE_NO_ERROR; | |
826 } | |
827 | |
828 /** | |
829 * @brief Write a byte on the SD. | |
830 * @param Data: byte to send. | |
831 * @retval None | |
832 */ | |
833 uint8_t SD_WriteByte(uint8_t Data) | |
834 { | |
835 /*!< Wait until the transmit buffer is empty */ | |
836 while(SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_TXE) == RESET) | |
837 { | |
838 } | |
839 | |
840 /*!< Send the byte */ | |
841 SPI_I2S_SendData(SD_SPI, Data); | |
842 | |
843 /*!< Wait to receive a byte*/ | |
844 while(SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_RXNE) == RESET) | |
845 { | |
846 } | |
847 | |
848 /*!< Return the byte read from the SPI bus */ | |
849 return SPI_I2S_ReceiveData(SD_SPI); | |
850 } | |
851 | |
852 /** | |
853 * @brief Read a byte from the SD. | |
854 * @param None | |
855 * @retval The received byte. | |
856 */ | |
857 uint8_t SD_ReadByte(void) | |
858 { | |
859 uint8_t Data = 0; | |
860 | |
861 /*!< Wait until the transmit buffer is empty */ | |
862 while (SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_TXE) == RESET) | |
863 { | |
864 } | |
865 /*!< Send the byte */ | |
866 SPI_I2S_SendData(SD_SPI, SD_DUMMY_BYTE); | |
867 | |
868 /*!< Wait until a data is received */ | |
869 while (SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_RXNE) == RESET) | |
870 { | |
871 } | |
872 /*!< Get the received data */ | |
873 Data = SPI_I2S_ReceiveData(SD_SPI); | |
874 | |
875 /*!< Return the shifted data */ | |
876 return Data; | |
877 } | |
878 | |
879 /** | |
880 * @} | |
881 */ | |
882 | |
883 | |
884 /** | |
885 * @} | |
886 */ | |
887 | |
888 | |
889 /** | |
890 * @} | |
891 */ | |
892 | |
893 /** | |
894 * @} | |
895 */ | |
896 | |
897 /** | |
898 * @} | |
899 */ | |
900 | |
901 /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ |