STM32072B_EVAL BSP User Manual
|
stm32072b_eval_sd.c
Go to the documentation of this file.
00001 /** 00002 ****************************************************************************** 00003 * @file stm32072b_eval_sd.c 00004 * @author MCD Application Team 00005 * @brief This file provides a set of functions needed to manage the SPI SD 00006 * Card memory mounted on STM32072B-EVAL board. 00007 * It implements a high level communication layer for read and write 00008 * from/to this memory. The needed STM32F0xx hardware resources (SPI and 00009 * GPIO) are defined in stm32072b_eval.h file, and the initialization is 00010 * performed in SD_IO_Init() function declared in stm32072b_eval.c 00011 * file. 00012 * You can easily tailor this driver to any other development board, 00013 * by just adapting the defines for hardware resources and 00014 * SD_IO_Init() function. 00015 * 00016 * +-------------------------------------------------------+ 00017 * | Pin assignment | 00018 * +-------------------------+---------------+-------------+ 00019 * | STM32F0xx SPI Pins | SD | Pin | 00020 * +-------------------------+---------------+-------------+ 00021 * | SD_SPI_CS_PIN | ChipSelect | 1 | 00022 * | SD_SPI_MOSI_PIN / MOSI | DataIn | 2 | 00023 * | | GND | 3 (0 V) | 00024 * | | VDD | 4 (3.3 V)| 00025 * | SD_SPI_SCK_PIN / SCLK | Clock | 5 | 00026 * | | GND | 6 (0 V) | 00027 * | SD_SPI_MISO_PIN / MISO | DataOut | 7 | 00028 * +-------------------------+---------------+-------------+ 00029 ****************************************************************************** 00030 * @attention 00031 * 00032 * <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> 00033 * 00034 * Redistribution and use in source and binary forms, with or without modification, 00035 * are permitted provided that the following conditions are met: 00036 * 1. Redistributions of source code must retain the above copyright notice, 00037 * this list of conditions and the following disclaimer. 00038 * 2. Redistributions in binary form must reproduce the above copyright notice, 00039 * this list of conditions and the following disclaimer in the documentation 00040 * and/or other materials provided with the distribution. 00041 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00042 * may be used to endorse or promote products derived from this software 00043 * without specific prior written permission. 00044 * 00045 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00046 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00047 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00048 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00049 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00050 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00051 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00052 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00053 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00054 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00055 * 00056 ****************************************************************************** 00057 @verbatim 00058 ============================================================================== 00059 ##### How to use this driver ##### 00060 ============================================================================== 00061 [..] 00062 (#) This driver is used to drive the micro SD external card mounted on STM32072B-EVAL 00063 evaluation board. 00064 (#) This driver does not need a specific component driver for the micro SD device 00065 to be included with. 00066 00067 (#) Initialization steps: 00068 (++) Initialize the micro SD card using the SD_Init() function. 00069 (++) To check the SD card presence you can use the function BSP_SD_IsDetected() which 00070 returns the detection status 00071 (++) The function BSP_SD_GetCardInfo() is used to get the micro SD card information 00072 which is stored in the structure "SD_CardInfo". 00073 00074 (#) Micro SD card operations 00075 (++) The micro SD card can be accessed with read/write block(s) operations once 00076 it is reay for access. The access cand be performed in polling 00077 mode by calling the functions SD_ReadBlocks()/SD_WriteBlocks() 00078 (++) The SD erase block(s) is performed using the function BSP_SD_Erase() with 00079 specifying the number of blocks to erase. 00080 (++) The SD runtime status is returned when calling the function BSP_SD_GetStatus(). 00081 00082 @endverbatim 00083 */ 00084 00085 00086 /* Includes ------------------------------------------------------------------*/ 00087 #include "stm32072b_eval_sd.h" 00088 #include "stm32f0xx_hal.h" 00089 #include "stdlib.h" 00090 #include "string.h" 00091 #include "stdio.h" 00092 00093 /** @addtogroup BSP 00094 * @{ 00095 */ 00096 00097 /** @addtogroup STM32072B_EVAL 00098 * @{ 00099 */ 00100 00101 /** @addtogroup STM32072B_EVAL_SD 00102 * @{ 00103 */ 00104 00105 /* Private typedef -----------------------------------------------------------*/ 00106 00107 /** @defgroup STM32072BEVAL_SD_Private_Types_Definitions Types Definitions 00108 * @{ 00109 */ 00110 typedef struct { 00111 uint8_t r1; 00112 uint8_t r2; 00113 uint8_t r3; 00114 uint8_t r4; 00115 uint8_t r5; 00116 } SD_CmdAnswer_typedef; 00117 00118 /** 00119 * @} 00120 */ 00121 00122 /* Private define ------------------------------------------------------------*/ 00123 00124 /** @defgroup STM32072B_EVAL_SD_Private_Constants Private Constants 00125 * @{ 00126 */ 00127 #define SD_DUMMY_BYTE 0xFF 00128 00129 #define SD_MAX_FRAME_LENGTH 17 /* Lenght = 16 + 1 */ 00130 #define SD_CMD_LENGTH 6 00131 00132 #define SD_MAX_TRY 100 /* Number of try */ 00133 00134 #define SD_CSD_STRUCT_V1 0x2 /* CSD struct version V1 */ 00135 #define SD_CSD_STRUCT_V2 0x1 /* CSD struct version V2 */ 00136 00137 00138 /** 00139 * @brief SD ansewer format 00140 */ 00141 typedef enum { 00142 SD_ANSWER_R1_EXPECTED, 00143 SD_ANSWER_R1B_EXPECTED, 00144 SD_ANSWER_R2_EXPECTED, 00145 SD_ANSWER_R3_EXPECTED, 00146 SD_ANSWER_R4R5_EXPECTED, 00147 SD_ANSWER_R7_EXPECTED, 00148 }SD_Answer_type; 00149 00150 /** 00151 * @brief Start Data tokens: 00152 * Tokens (necessary because at nop/idle (and CS active) only 0xff is 00153 * on the data/command line) 00154 */ 00155 #define SD_TOKEN_START_DATA_SINGLE_BLOCK_READ 0xFE /* Data token start byte, Start Single Block Read */ 00156 #define SD_TOKEN_START_DATA_MULTIPLE_BLOCK_READ 0xFE /* Data token start byte, Start Multiple Block Read */ 00157 #define SD_TOKEN_START_DATA_SINGLE_BLOCK_WRITE 0xFE /* Data token start byte, Start Single Block Write */ 00158 #define SD_TOKEN_START_DATA_MULTIPLE_BLOCK_WRITE 0xFD /* Data token start byte, Start Multiple Block Write */ 00159 #define SD_TOKEN_STOP_DATA_MULTIPLE_BLOCK_WRITE 0xFD /* Data toke stop byte, Stop Multiple Block Write */ 00160 00161 /** 00162 * @brief Commands: CMDxx = CMD-number | 0x40 00163 */ 00164 #define SD_CMD_GO_IDLE_STATE 0 /* CMD0 = 0x40 */ 00165 #define SD_CMD_SEND_OP_COND 1 /* CMD1 = 0x41 */ 00166 #define SD_CMD_SEND_IF_COND 8 /* CMD8 = 0x48 */ 00167 #define SD_CMD_SEND_CSD 9 /* CMD9 = 0x49 */ 00168 #define SD_CMD_SEND_CID 10 /* CMD10 = 0x4A */ 00169 #define SD_CMD_STOP_TRANSMISSION 12 /* CMD12 = 0x4C */ 00170 #define SD_CMD_SEND_STATUS 13 /* CMD13 = 0x4D */ 00171 #define SD_CMD_SET_BLOCKLEN 16 /* CMD16 = 0x50 */ 00172 #define SD_CMD_READ_SINGLE_BLOCK 17 /* CMD17 = 0x51 */ 00173 #define SD_CMD_READ_MULT_BLOCK 18 /* CMD18 = 0x52 */ 00174 #define SD_CMD_SET_BLOCK_COUNT 23 /* CMD23 = 0x57 */ 00175 #define SD_CMD_WRITE_SINGLE_BLOCK 24 /* CMD24 = 0x58 */ 00176 #define SD_CMD_WRITE_MULT_BLOCK 25 /* CMD25 = 0x59 */ 00177 #define SD_CMD_PROG_CSD 27 /* CMD27 = 0x5B */ 00178 #define SD_CMD_SET_WRITE_PROT 28 /* CMD28 = 0x5C */ 00179 #define SD_CMD_CLR_WRITE_PROT 29 /* CMD29 = 0x5D */ 00180 #define SD_CMD_SEND_WRITE_PROT 30 /* CMD30 = 0x5E */ 00181 #define SD_CMD_SD_ERASE_GRP_START 32 /* CMD32 = 0x60 */ 00182 #define SD_CMD_SD_ERASE_GRP_END 33 /* CMD33 = 0x61 */ 00183 #define SD_CMD_UNTAG_SECTOR 34 /* CMD34 = 0x62 */ 00184 #define SD_CMD_ERASE_GRP_START 35 /* CMD35 = 0x63 */ 00185 #define SD_CMD_ERASE_GRP_END 36 /* CMD36 = 0x64 */ 00186 #define SD_CMD_UNTAG_ERASE_GROUP 37 /* CMD37 = 0x65 */ 00187 #define SD_CMD_ERASE 38 /* CMD38 = 0x66 */ 00188 #define SD_CMD_SD_APP_OP_COND 41 /* CMD41 = 0x69 */ 00189 #define SD_CMD_APP_CMD 55 /* CMD55 = 0x77 */ 00190 #define SD_CMD_READ_OCR 58 /* CMD55 = 0x79 */ 00191 00192 /** 00193 * @brief SD reponses and error flags 00194 */ 00195 typedef enum 00196 { 00197 /* R1 answer value */ 00198 SD_R1_NO_ERROR = (0x00), 00199 SD_R1_IN_IDLE_STATE = (0x01), 00200 SD_R1_ERASE_RESET = (0x02), 00201 SD_R1_ILLEGAL_COMMAND = (0x04), 00202 SD_R1_COM_CRC_ERROR = (0x08), 00203 SD_R1_ERASE_SEQUENCE_ERROR= (0x10), 00204 SD_R1_ADDRESS_ERROR = (0x20), 00205 SD_R1_PARAMETER_ERROR = (0x40), 00206 00207 /* R2 answer value */ 00208 SD_R2_NO_ERROR = 0x00, 00209 SD_R2_CARD_LOCKED = 0x01, 00210 SD_R2_LOCKUNLOCK_ERROR = 0x02, 00211 SD_R2_ERROR = 0x04, 00212 SD_R2_CC_ERROR = 0x08, 00213 SD_R2_CARD_ECC_FAILED = 0x10, 00214 SD_R2_WP_VIOLATION = 0x20, 00215 SD_R2_ERASE_PARAM = 0x40, 00216 SD_R2_OUTOFRANGE = 0x80, 00217 00218 /** 00219 * @brief Data response error 00220 */ 00221 SD_DATA_OK = (0x05), 00222 SD_DATA_CRC_ERROR = (0x0B), 00223 SD_DATA_WRITE_ERROR = (0x0D), 00224 SD_DATA_OTHER_ERROR = (0xFF) 00225 } SD_Error; 00226 00227 /** 00228 * @} 00229 */ 00230 00231 /* Private macro -------------------------------------------------------------*/ 00232 00233 /* Private variables ---------------------------------------------------------*/ 00234 00235 /** @defgroup STM32072B_EVAL_SD_Private_Variables Private Variables 00236 * @{ 00237 */ 00238 __IO uint8_t SdStatus = SD_NOT_PRESENT; 00239 00240 /* flag_SDHC : 00241 0 : Standard capacity 00242 1 : High capacity 00243 */ 00244 uint16_t flag_SDHC = 0; 00245 00246 /** 00247 * @} 00248 */ 00249 00250 /* Private function prototypes -----------------------------------------------*/ 00251 /** @defgroup STM32072B_EVAL_SD_Private_Functions Private Functions 00252 * @{ 00253 */ 00254 static uint8_t SD_GetCIDRegister(SD_CID* Cid); 00255 static uint8_t SD_GetCSDRegister(SD_CSD* Csd); 00256 static uint8_t SD_GetDataResponse(void); 00257 static uint8_t SD_GoIdleState(void); 00258 static SD_CmdAnswer_typedef SD_SendCmd(uint8_t Cmd, uint32_t Arg, uint8_t Crc, uint8_t Answer); 00259 static uint8_t SD_WaitData(uint8_t data); 00260 static uint8_t SD_ReadData(void); 00261 /** 00262 * @} 00263 */ 00264 00265 /* Exported functions ---------------------------------------------------------*/ 00266 00267 /** @addtogroup STM32072B_EVAL_SD_Exported_Functions 00268 * @{ 00269 */ 00270 00271 /** 00272 * @brief Initializes the SD/SD communication. 00273 * @retval The SD Response: 00274 * - MSD_ERROR: Sequence failed 00275 * - MSD_OK: Sequence succeed 00276 */ 00277 uint8_t BSP_SD_Init(void) 00278 { 00279 /* Configure IO functionalities for SD pin */ 00280 SD_IO_Init(); 00281 00282 /* Check SD card detect pin */ 00283 if(BSP_SD_IsDetected()==SD_NOT_PRESENT) 00284 { 00285 SdStatus = SD_NOT_PRESENT; 00286 return MSD_ERROR; 00287 } 00288 else 00289 { 00290 SdStatus = SD_PRESENT; 00291 } 00292 00293 /* SD initialized and set to SPI mode properly */ 00294 return (SD_GoIdleState()); 00295 } 00296 00297 /** 00298 * @brief Detects if SD card is correctly plugged in the memory slot or not. 00299 * @retval Returns if SD is detected or not 00300 */ 00301 uint8_t BSP_SD_IsDetected(void) 00302 { 00303 __IO uint8_t status = SD_PRESENT; 00304 00305 /* Check SD card detect pin */ 00306 if(HAL_GPIO_ReadPin(SD_DETECT_GPIO_PORT, SD_DETECT_PIN) != GPIO_PIN_RESET) 00307 { 00308 status = SD_NOT_PRESENT; 00309 } 00310 00311 return status; 00312 } 00313 00314 /** 00315 * @brief Returns information about specific card. 00316 * @param pCardInfo Pointer to a SD_CardInfo structure that contains all SD 00317 * card information. 00318 * @retval The SD Response: 00319 * - MSD_ERROR: Sequence failed 00320 * - MSD_OK: Sequence succeed 00321 */ 00322 uint8_t BSP_SD_GetCardInfo(SD_CardInfo *pCardInfo) 00323 { 00324 uint8_t status; 00325 00326 status = SD_GetCSDRegister(&(pCardInfo->Csd)); 00327 status|= SD_GetCIDRegister(&(pCardInfo->Cid)); 00328 if(flag_SDHC == 1 ) 00329 { 00330 pCardInfo->CardBlockSize = 512; 00331 pCardInfo->CardCapacity = (pCardInfo->Csd.version.v2.DeviceSize + 1) * pCardInfo->CardBlockSize; 00332 } 00333 else 00334 { 00335 pCardInfo->CardCapacity = (pCardInfo->Csd.version.v1.DeviceSize + 1) ; 00336 pCardInfo->CardCapacity *= (1 << (pCardInfo->Csd.version.v1.DeviceSizeMul + 2)); 00337 pCardInfo->CardBlockSize = 1 << (pCardInfo->Csd.RdBlockLen); 00338 pCardInfo->CardCapacity *= pCardInfo->CardBlockSize; 00339 } 00340 00341 return status; 00342 } 00343 00344 /** 00345 * @brief Reads block(s) from a specified address in the SD card, in polling mode. 00346 * @param pData Pointer to the buffer that will contain the data to transmit 00347 * @param ReadAddr Address from where data is to be read 00348 * @param BlockSize SD card data block size, that should be 512 00349 * @param NumberOfBlocks Number of SD blocks to read 00350 * @retval SD status 00351 */ 00352 uint8_t BSP_SD_ReadBlocks(uint32_t* pData, uint32_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks) 00353 { 00354 uint32_t offset = 0; 00355 uint8_t retr = BSP_SD_ERROR; 00356 uint8_t *ptr = NULL; 00357 SD_CmdAnswer_typedef response; 00358 00359 /* Send CMD16 (SD_CMD_SET_BLOCKLEN) to set the size of the block and 00360 Check if the SD acknowledged the set block length command: R1 response (0x00: no errors) */ 00361 response = SD_SendCmd(SD_CMD_SET_BLOCKLEN, BlockSize, 0xFF, SD_ANSWER_R1_EXPECTED); 00362 SD_IO_CSState(1); 00363 SD_IO_WriteByte(SD_DUMMY_BYTE); 00364 if ( response.r1 != SD_R1_NO_ERROR) 00365 { 00366 goto error; 00367 } 00368 00369 ptr = malloc(sizeof(uint8_t)*BlockSize); 00370 if( ptr == NULL ) 00371 { 00372 goto error; 00373 } 00374 memset(ptr, SD_DUMMY_BYTE, sizeof(uint8_t)*BlockSize); 00375 00376 /* Data transfer */ 00377 while (NumberOfBlocks--) 00378 { 00379 /* Send CMD17 (SD_CMD_READ_SINGLE_BLOCK) to read one block */ 00380 /* Check if the SD acknowledged the read block command: R1 response (0x00: no errors) */ 00381 response = SD_SendCmd(SD_CMD_READ_SINGLE_BLOCK, (ReadAddr + offset)/(flag_SDHC == 1 ?BlockSize: 1), 0xFF, SD_ANSWER_R1_EXPECTED); 00382 if ( response.r1 != SD_R1_NO_ERROR) 00383 { 00384 goto error; 00385 } 00386 00387 /* Now look for the data token to signify the start of the data */ 00388 if (SD_WaitData(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ) == BSP_SD_OK) 00389 { 00390 /* Read the SD block data : read NumByteToRead data */ 00391 SD_IO_WriteReadData(ptr, (uint8_t*)pData + offset, BlockSize); 00392 00393 /* Set next read address*/ 00394 offset += BlockSize; 00395 /* get CRC bytes (not really needed by us, but required by SD) */ 00396 SD_IO_WriteByte(SD_DUMMY_BYTE); 00397 SD_IO_WriteByte(SD_DUMMY_BYTE); 00398 } 00399 else 00400 { 00401 goto error; 00402 } 00403 00404 /* End the command data read cycle */ 00405 SD_IO_CSState(1); 00406 SD_IO_WriteByte(SD_DUMMY_BYTE); 00407 } 00408 00409 retr = BSP_SD_OK; 00410 00411 error : 00412 /* Send dummy byte: 8 Clock pulses of delay */ 00413 SD_IO_CSState(1); 00414 SD_IO_WriteByte(SD_DUMMY_BYTE); 00415 if(ptr != NULL) free(ptr); 00416 00417 /* Return the reponse */ 00418 return retr; 00419 } 00420 00421 /** 00422 * @brief Writes block(s) to a specified address in the SD card, in polling mode. 00423 * @param pData Pointer to the buffer that will contain the data to transmit 00424 * @param WriteAddr Address from where data is to be written 00425 * @param BlockSize SD card data block size, that should be 512 00426 * @param NumberOfBlocks Number of SD blocks to write 00427 * @retval SD status 00428 */ 00429 uint8_t BSP_SD_WriteBlocks(uint32_t* pData, uint32_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks) 00430 { 00431 uint32_t offset = 0; 00432 uint8_t retr = BSP_SD_ERROR; 00433 uint8_t *ptr = NULL; 00434 SD_CmdAnswer_typedef response; 00435 00436 /* Send CMD16 (SD_CMD_SET_BLOCKLEN) to set the size of the block and 00437 Check if the SD acknowledged the set block length command: R1 response (0x00: no errors) */ 00438 response = SD_SendCmd(SD_CMD_SET_BLOCKLEN, BlockSize, 0xFF, SD_ANSWER_R1_EXPECTED); 00439 SD_IO_CSState(1); 00440 SD_IO_WriteByte(SD_DUMMY_BYTE); 00441 if ( response.r1 != SD_R1_NO_ERROR) 00442 { 00443 goto error; 00444 } 00445 00446 ptr = malloc(sizeof(uint8_t)*BlockSize); 00447 if (ptr == NULL) 00448 { 00449 goto error; 00450 } 00451 00452 /* Data transfer */ 00453 while (NumberOfBlocks--) 00454 { 00455 /* Send CMD24 (SD_CMD_WRITE_SINGLE_BLOCK) to write blocks and 00456 Check if the SD acknowledged the write block command: R1 response (0x00: no errors) */ 00457 response = SD_SendCmd(SD_CMD_WRITE_SINGLE_BLOCK, (WriteAddr + offset)/(flag_SDHC == 1 ? BlockSize: 1), 0xFF, SD_ANSWER_R1_EXPECTED); 00458 if (response.r1 != SD_R1_NO_ERROR) 00459 { 00460 goto error; 00461 } 00462 00463 /* Send dummy byte for NWR timing : one byte between CMDWRITE and TOKEN */ 00464 SD_IO_WriteByte(SD_DUMMY_BYTE); 00465 SD_IO_WriteByte(SD_DUMMY_BYTE); 00466 00467 /* Send the data token to signify the start of the data */ 00468 SD_IO_WriteByte(SD_TOKEN_START_DATA_SINGLE_BLOCK_WRITE); 00469 00470 /* Write the block data to SD */ 00471 SD_IO_WriteReadData((uint8_t*)pData + offset, ptr, BlockSize); 00472 00473 /* Set next write address */ 00474 offset += BlockSize; 00475 00476 /* Put CRC bytes (not really needed by us, but required by SD) */ 00477 SD_IO_WriteByte(SD_DUMMY_BYTE); 00478 SD_IO_WriteByte(SD_DUMMY_BYTE); 00479 00480 /* Read data response */ 00481 if (SD_GetDataResponse() != SD_DATA_OK) 00482 { 00483 /* Set response value to failure */ 00484 goto error; 00485 } 00486 00487 SD_IO_CSState(1); 00488 SD_IO_WriteByte(SD_DUMMY_BYTE); 00489 } 00490 retr = BSP_SD_OK; 00491 00492 error : 00493 if(ptr != NULL) free(ptr); 00494 /* Send dummy byte: 8 Clock pulses of delay */ 00495 SD_IO_CSState(1); 00496 SD_IO_WriteByte(SD_DUMMY_BYTE); 00497 00498 /* Return the reponse */ 00499 return retr; 00500 } 00501 00502 /** 00503 * @brief Erases the specified memory area of the given SD card. 00504 * @param StartAddr Start byte address 00505 * @param EndAddr End byte address 00506 * @retval SD status 00507 */ 00508 uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr) 00509 { 00510 uint8_t retr = BSP_SD_ERROR; 00511 SD_CmdAnswer_typedef response; 00512 00513 /* Send CMD32 (Erase group start) and check if the SD acknowledged the erase command: R1 response (0x00: no errors) */ 00514 response = SD_SendCmd(SD_CMD_SD_ERASE_GRP_START, StartAddr, 0xFF, SD_ANSWER_R1_EXPECTED); 00515 SD_IO_CSState(1); 00516 SD_IO_WriteByte(SD_DUMMY_BYTE); if (response.r1 == SD_R1_NO_ERROR) 00517 { 00518 /* Send CMD33 (Erase group end) and Check if the SD acknowledged the erase command: R1 response (0x00: no errors) */ 00519 response = SD_SendCmd(SD_CMD_SD_ERASE_GRP_END, EndAddr, 0xFF, SD_ANSWER_R1_EXPECTED); 00520 SD_IO_CSState(1); 00521 SD_IO_WriteByte(SD_DUMMY_BYTE); 00522 if (response.r1 == SD_R1_NO_ERROR) 00523 { 00524 /* Send CMD38 (Erase) and Check if the SD acknowledged the erase command: R1 response (0x00: no errors) */ 00525 response = SD_SendCmd(SD_CMD_ERASE, 0, 0xFF, SD_ANSWER_R1B_EXPECTED); 00526 if (response.r1 == SD_R1_NO_ERROR) 00527 { 00528 retr = BSP_SD_OK; 00529 } 00530 SD_IO_CSState(1); 00531 SD_IO_WriteByte(SD_DUMMY_BYTE); 00532 } 00533 } 00534 00535 /* Return the reponse */ 00536 return retr; 00537 } 00538 00539 /** 00540 * @brief Returns the SD status. 00541 * @retval The SD status. 00542 */ 00543 uint8_t BSP_SD_GetStatus(void) 00544 { 00545 SD_CmdAnswer_typedef retr; 00546 00547 /* Send CMD13 (SD_SEND_STATUS) to get SD status */ 00548 retr = SD_SendCmd(SD_CMD_SEND_STATUS, 0, 0xFF, SD_ANSWER_R2_EXPECTED); 00549 SD_IO_CSState(1); 00550 SD_IO_WriteByte(SD_DUMMY_BYTE); 00551 00552 /* Find SD status according to card state */ 00553 if(( retr.r1 == SD_R1_NO_ERROR) && ( retr.r2 == SD_R2_NO_ERROR)) 00554 { 00555 return BSP_SD_OK; 00556 } 00557 00558 return BSP_SD_ERROR; 00559 } 00560 00561 /** 00562 * @brief Reads the SD card SCD register. 00563 * Reading the contents of the CSD register in SPI mode is a simple 00564 * read-block transaction. 00565 * @param Csd pointer on an SCD register structure 00566 * @retval SD status 00567 */ 00568 uint8_t SD_GetCSDRegister(SD_CSD* Csd) 00569 { 00570 uint16_t counter = 0; 00571 uint8_t CSD_Tab[16]; 00572 uint8_t retr = BSP_SD_ERROR; 00573 SD_CmdAnswer_typedef response; 00574 00575 /* Send CMD9 (CSD register) or CMD10(CSD register) and Wait for response in the R1 format (0x00 is no errors) */ 00576 response = SD_SendCmd(SD_CMD_SEND_CSD, 0, 0xFF, SD_ANSWER_R1_EXPECTED); 00577 if(response.r1 == SD_R1_NO_ERROR) 00578 { 00579 if (SD_WaitData(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ) == BSP_SD_OK) 00580 { 00581 for (counter = 0; counter < 16; counter++) 00582 { 00583 /* Store CSD register value on CSD_Tab */ 00584 CSD_Tab[counter] = SD_IO_WriteByte(SD_DUMMY_BYTE); 00585 } 00586 00587 /* Get CRC bytes (not really needed by us, but required by SD) */ 00588 SD_IO_WriteByte(SD_DUMMY_BYTE); 00589 SD_IO_WriteByte(SD_DUMMY_BYTE); 00590 00591 /************************************************************************* 00592 CSD header decoding 00593 *************************************************************************/ 00594 00595 /* Byte 0 */ 00596 Csd->CSDStruct = (CSD_Tab[0] & 0xC0) >> 6; 00597 Csd->Reserved1 = CSD_Tab[0] & 0x3F; 00598 00599 /* Byte 1 */ 00600 Csd->TAAC = CSD_Tab[1]; 00601 00602 /* Byte 2 */ 00603 Csd->NSAC = CSD_Tab[2]; 00604 00605 /* Byte 3 */ 00606 Csd->MaxBusClkFrec = CSD_Tab[3]; 00607 00608 /* Byte 4/5 */ 00609 Csd->CardComdClasses = (CSD_Tab[4] << 4) | ((CSD_Tab[5] & 0xF0) >> 4); 00610 Csd->RdBlockLen = CSD_Tab[5] & 0x0F; 00611 00612 /* Byte 6 */ 00613 Csd->PartBlockRead = (CSD_Tab[6] & 0x80) >> 7; 00614 Csd->WrBlockMisalign = (CSD_Tab[6] & 0x40) >> 6; 00615 Csd->RdBlockMisalign = (CSD_Tab[6] & 0x20) >> 5; 00616 Csd->DSRImpl = (CSD_Tab[6] & 0x10) >> 4; 00617 00618 /************************************************************************* 00619 CSD v1/v2 decoding 00620 *************************************************************************/ 00621 00622 if(flag_SDHC == 0) 00623 { 00624 Csd->version.v1.Reserved1 = ((CSD_Tab[6] & 0x0C) >> 2); 00625 00626 Csd->version.v1.DeviceSize = ((CSD_Tab[6] & 0x03) << 10) 00627 | (CSD_Tab[7] << 2) 00628 | ((CSD_Tab[8] & 0xC0) >> 6); 00629 Csd->version.v1.MaxRdCurrentVDDMin = (CSD_Tab[8] & 0x38) >> 3; 00630 Csd->version.v1.MaxRdCurrentVDDMax = (CSD_Tab[8] & 0x07); 00631 Csd->version.v1.MaxWrCurrentVDDMin = (CSD_Tab[9] & 0xE0) >> 5; 00632 Csd->version.v1.MaxWrCurrentVDDMax = (CSD_Tab[9] & 0x1C) >> 2; 00633 Csd->version.v1.DeviceSizeMul = ((CSD_Tab[9] & 0x03) << 1) 00634 |((CSD_Tab[10] & 0x80) >> 7); 00635 } 00636 else 00637 { 00638 Csd->version.v2.Reserved1 = ((CSD_Tab[6] & 0x0F) << 2) | ((CSD_Tab[7] & 0xC0) >> 6); 00639 Csd->version.v2.DeviceSize= ((CSD_Tab[7] & 0x3F) << 16) | (CSD_Tab[8] << 8) | CSD_Tab[9]; 00640 Csd->version.v2.Reserved2 = ((CSD_Tab[10] & 0x80) >> 8); 00641 } 00642 00643 Csd->EraseSingleBlockEnable = (CSD_Tab[10] & 0x40) >> 6; 00644 Csd->EraseSectorSize = ((CSD_Tab[10] & 0x3F) << 1) 00645 |((CSD_Tab[11] & 0x80) >> 7); 00646 Csd->WrProtectGrSize = (CSD_Tab[11] & 0x7F); 00647 Csd->WrProtectGrEnable = (CSD_Tab[12] & 0x80) >> 7; 00648 Csd->Reserved2 = (CSD_Tab[12] & 0x60) >> 5; 00649 Csd->WrSpeedFact = (CSD_Tab[12] & 0x1C) >> 2; 00650 Csd->MaxWrBlockLen = ((CSD_Tab[12] & 0x03) << 2) 00651 |((CSD_Tab[13] & 0xC0) >> 6); 00652 Csd->WriteBlockPartial = (CSD_Tab[13] & 0x20) >> 5; 00653 Csd->Reserved3 = (CSD_Tab[13] & 0x1F); 00654 Csd->FileFormatGrouop = (CSD_Tab[14] & 0x80) >> 7; 00655 Csd->CopyFlag = (CSD_Tab[14] & 0x40) >> 6; 00656 Csd->PermWrProtect = (CSD_Tab[14] & 0x20) >> 5; 00657 Csd->TempWrProtect = (CSD_Tab[14] & 0x10) >> 4; 00658 Csd->FileFormat = (CSD_Tab[14] & 0x0C) >> 2; 00659 Csd->Reserved4 = (CSD_Tab[14] & 0x03); 00660 Csd->crc = (CSD_Tab[15] & 0xFE) >> 1; 00661 Csd->Reserved5 = (CSD_Tab[15] & 0x01); 00662 00663 retr = BSP_SD_OK; 00664 } 00665 } 00666 00667 /* Send dummy byte: 8 Clock pulses of delay */ 00668 SD_IO_CSState(1); 00669 SD_IO_WriteByte(SD_DUMMY_BYTE); 00670 00671 /* Return the reponse */ 00672 return retr; 00673 } 00674 00675 /** 00676 * @brief Reads the SD card CID register. 00677 * Reading the contents of the CID register in SPI mode is a simple 00678 * read-block transaction. 00679 * @param Cid pointer on an CID register structure 00680 * @retval SD status 00681 */ 00682 uint8_t SD_GetCIDRegister(SD_CID* Cid) 00683 { 00684 uint32_t counter = 0; 00685 uint8_t retr = BSP_SD_ERROR; 00686 uint8_t CID_Tab[16]; 00687 SD_CmdAnswer_typedef response; 00688 00689 /* Send CMD10 (CID register) and Wait for response in the R1 format (0x00 is no errors) */ 00690 response = SD_SendCmd(SD_CMD_SEND_CID, 0, 0xFF, SD_ANSWER_R1_EXPECTED); 00691 if(response.r1 == SD_R1_NO_ERROR) 00692 { 00693 if(SD_WaitData(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ) == BSP_SD_OK) 00694 { 00695 /* Store CID register value on CID_Tab */ 00696 for (counter = 0; counter < 16; counter++) 00697 { 00698 CID_Tab[counter] = SD_IO_WriteByte(SD_DUMMY_BYTE); 00699 } 00700 00701 /* Get CRC bytes (not really needed by us, but required by SD) */ 00702 SD_IO_WriteByte(SD_DUMMY_BYTE); 00703 SD_IO_WriteByte(SD_DUMMY_BYTE); 00704 00705 /* Byte 0 */ 00706 Cid->ManufacturerID = CID_Tab[0]; 00707 00708 /* Byte 1 */ 00709 Cid->OEM_AppliID = CID_Tab[1] << 8; 00710 00711 /* Byte 2 */ 00712 Cid->OEM_AppliID |= CID_Tab[2]; 00713 00714 /* Byte 3 */ 00715 Cid->ProdName1 = CID_Tab[3] << 24; 00716 00717 /* Byte 4 */ 00718 Cid->ProdName1 |= CID_Tab[4] << 16; 00719 00720 /* Byte 5 */ 00721 Cid->ProdName1 |= CID_Tab[5] << 8; 00722 00723 /* Byte 6 */ 00724 Cid->ProdName1 |= CID_Tab[6]; 00725 00726 /* Byte 7 */ 00727 Cid->ProdName2 = CID_Tab[7]; 00728 00729 /* Byte 8 */ 00730 Cid->ProdRev = CID_Tab[8]; 00731 00732 /* Byte 9 */ 00733 Cid->ProdSN = CID_Tab[9] << 24; 00734 00735 /* Byte 10 */ 00736 Cid->ProdSN |= CID_Tab[10] << 16; 00737 00738 /* Byte 11 */ 00739 Cid->ProdSN |= CID_Tab[11] << 8; 00740 00741 /* Byte 12 */ 00742 Cid->ProdSN |= CID_Tab[12]; 00743 00744 /* Byte 13 */ 00745 Cid->Reserved1 |= (CID_Tab[13] & 0xF0) >> 4; 00746 Cid->ManufactDate = (CID_Tab[13] & 0x0F) << 8; 00747 00748 /* Byte 14 */ 00749 Cid->ManufactDate |= CID_Tab[14]; 00750 00751 /* Byte 15 */ 00752 Cid->CID_CRC = (CID_Tab[15] & 0xFE) >> 1; 00753 Cid->Reserved2 = 1; 00754 00755 retr = BSP_SD_OK; 00756 } 00757 } 00758 00759 /* Send dummy byte: 8 Clock pulses of delay */ 00760 SD_IO_CSState(1); 00761 SD_IO_WriteByte(SD_DUMMY_BYTE); 00762 00763 /* Return the reponse */ 00764 return retr; 00765 } 00766 00767 /** 00768 * @brief Send 5 bytes command to the SD card and get response 00769 * @param Cmd The user expected command to send to SD card. 00770 * @param Arg The command argument. 00771 * @param Crc The CRC. 00772 * @param Answer SD_ANSWER_NOT_EXPECTED or SD_ANSWER_EXPECTED 00773 * @retval SD status 00774 */ 00775 SD_CmdAnswer_typedef SD_SendCmd(uint8_t Cmd, uint32_t Arg, uint8_t Crc, uint8_t Answer) 00776 { 00777 uint8_t frame[SD_CMD_LENGTH], frameout[SD_CMD_LENGTH]; 00778 SD_CmdAnswer_typedef retr = {0xFF, 0xFF , 0xFF, 0xFF, 0xFF}; 00779 00780 /* R1 Lenght = NCS(0)+ 6 Bytes command + NCR(min1 max8) + 1 Bytes answer + NEC(0) = 15bytes */ 00781 /* R1b identical to R1 + Busy information */ 00782 /* R2 Lenght = NCS(0)+ 6 Bytes command + NCR(min1 max8) + 2 Bytes answer + NEC(0) = 16bytes */ 00783 00784 /* Prepare Frame to send */ 00785 frame[0] = (Cmd | 0x40); /* Construct byte 1 */ 00786 frame[1] = (uint8_t)(Arg >> 24); /* Construct byte 2 */ 00787 frame[2] = (uint8_t)(Arg >> 16); /* Construct byte 3 */ 00788 frame[3] = (uint8_t)(Arg >> 8); /* Construct byte 4 */ 00789 frame[4] = (uint8_t)(Arg); /* Construct byte 5 */ 00790 frame[5] = (Crc | 0x01); /* Construct byte 6 */ 00791 00792 /* Send the command */ 00793 SD_IO_CSState(0); 00794 SD_IO_WriteReadData(frame, frameout, SD_CMD_LENGTH); /* Send the Cmd bytes */ 00795 00796 switch(Answer) 00797 { 00798 case SD_ANSWER_R1_EXPECTED : 00799 retr.r1 = SD_ReadData(); 00800 break; 00801 case SD_ANSWER_R1B_EXPECTED : 00802 retr.r1 = SD_ReadData(); 00803 retr.r2 = SD_IO_WriteByte(SD_DUMMY_BYTE); 00804 /* Set CS High */ 00805 SD_IO_CSState(1); 00806 HAL_Delay(1); 00807 /* Set CS Low */ 00808 SD_IO_CSState(0); 00809 00810 /* Wait IO line return 0xFF */ 00811 while (SD_IO_WriteByte(SD_DUMMY_BYTE) != 0xFF); 00812 break; 00813 case SD_ANSWER_R2_EXPECTED : 00814 retr.r1 = SD_ReadData(); 00815 retr.r2 = SD_IO_WriteByte(SD_DUMMY_BYTE); 00816 break; 00817 case SD_ANSWER_R3_EXPECTED : 00818 case SD_ANSWER_R7_EXPECTED : 00819 retr.r1 = SD_ReadData(); 00820 retr.r2 = SD_IO_WriteByte(SD_DUMMY_BYTE); 00821 retr.r3 = SD_IO_WriteByte(SD_DUMMY_BYTE); 00822 retr.r4 = SD_IO_WriteByte(SD_DUMMY_BYTE); 00823 retr.r5 = SD_IO_WriteByte(SD_DUMMY_BYTE); 00824 break; 00825 default : 00826 break; 00827 } 00828 return retr; 00829 } 00830 00831 /** 00832 * @brief Gets the SD card data response and check the busy flag. 00833 * @retval The SD status: Read data response xxx0<status>1 00834 * - status 010: Data accecpted 00835 * - status 101: Data rejected due to a crc error 00836 * - status 110: Data rejected due to a Write error. 00837 * - status 111: Data rejected due to other error. 00838 */ 00839 uint8_t SD_GetDataResponse(void) 00840 { 00841 uint8_t dataresponse; 00842 uint8_t rvalue = SD_DATA_OTHER_ERROR; 00843 00844 dataresponse = SD_IO_WriteByte(SD_DUMMY_BYTE); 00845 SD_IO_WriteByte(SD_DUMMY_BYTE); /* read the busy response byte*/ 00846 00847 /* Mask unused bits */ 00848 switch (dataresponse & 0x1F) 00849 { 00850 case SD_DATA_OK: 00851 rvalue = SD_DATA_OK; 00852 00853 /* Set CS High */ 00854 SD_IO_CSState(1); 00855 /* Set CS Low */ 00856 SD_IO_CSState(0); 00857 00858 /* Wait IO line return 0xFF */ 00859 while (SD_IO_WriteByte(SD_DUMMY_BYTE) != 0xFF); 00860 break; 00861 case SD_DATA_CRC_ERROR: 00862 rvalue = SD_DATA_CRC_ERROR; 00863 break; 00864 case SD_DATA_WRITE_ERROR: 00865 rvalue = SD_DATA_WRITE_ERROR; 00866 break; 00867 default: 00868 break; 00869 } 00870 00871 /* Return response */ 00872 return rvalue; 00873 } 00874 00875 00876 /** 00877 * @brief Put the SD in Idle state. 00878 * @retval SD status 00879 */ 00880 uint8_t SD_GoIdleState(void) 00881 { 00882 SD_CmdAnswer_typedef response; 00883 __IO uint8_t counter = 0; 00884 /* Send CMD0 (SD_CMD_GO_IDLE_STATE) to put SD in SPI mode and 00885 wait for In Idle State Response (R1 Format) equal to 0x01 */ 00886 do{ 00887 counter++; 00888 response = SD_SendCmd(SD_CMD_GO_IDLE_STATE, 0, 0x95, SD_ANSWER_R1_EXPECTED); 00889 SD_IO_CSState(1); 00890 SD_IO_WriteByte(SD_DUMMY_BYTE); 00891 if(counter >= SD_MAX_TRY) 00892 { 00893 return BSP_SD_ERROR; 00894 } 00895 } 00896 while(response.r1 != SD_R1_IN_IDLE_STATE); 00897 00898 00899 /* Send CMD8 (SD_CMD_SEND_IF_COND) to check the power supply status 00900 and wait until response (R7 Format) equal to 0xAA and */ 00901 response = SD_SendCmd(SD_CMD_SEND_IF_COND, 0x1AA, 0x87, SD_ANSWER_R7_EXPECTED); 00902 SD_IO_CSState(1); 00903 SD_IO_WriteByte(SD_DUMMY_BYTE); 00904 if((response.r1 & SD_R1_ILLEGAL_COMMAND) == SD_R1_ILLEGAL_COMMAND) 00905 { 00906 /* initialise card V1 */ 00907 do 00908 { 00909 /* initialise card V1 */ 00910 /* Send CMD55 (SD_CMD_APP_CMD) before any ACMD command: R1 response (0x00: no errors) */ 00911 response = SD_SendCmd(SD_CMD_APP_CMD, 0x00000000, 0xFF, SD_ANSWER_R1_EXPECTED); 00912 SD_IO_CSState(1); 00913 SD_IO_WriteByte(SD_DUMMY_BYTE); 00914 00915 /* Send ACMD41 (SD_CMD_SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors) */ 00916 response = SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x00000000, 0xFF, SD_ANSWER_R1_EXPECTED); 00917 SD_IO_CSState(1); 00918 SD_IO_WriteByte(SD_DUMMY_BYTE); 00919 } 00920 while(response.r1 == SD_R1_IN_IDLE_STATE); 00921 flag_SDHC = 0; 00922 } 00923 else if(response.r1 == SD_R1_IN_IDLE_STATE) 00924 { 00925 /* initialise card V2 */ 00926 do { 00927 00928 /* Send CMD55 (SD_CMD_APP_CMD) before any ACMD command: R1 response (0x00: no errors) */ 00929 response = SD_SendCmd(SD_CMD_APP_CMD, 0, 0xFF, SD_ANSWER_R1_EXPECTED); 00930 SD_IO_CSState(1); 00931 SD_IO_WriteByte(SD_DUMMY_BYTE); 00932 00933 /* Send ACMD41 (SD_CMD_SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors) */ 00934 response = SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x40000000, 0xFF, SD_ANSWER_R1_EXPECTED); 00935 SD_IO_CSState(1); 00936 SD_IO_WriteByte(SD_DUMMY_BYTE); 00937 } 00938 while(response.r1 == SD_R1_IN_IDLE_STATE); 00939 00940 if((response.r1 & SD_R1_ILLEGAL_COMMAND) == SD_R1_ILLEGAL_COMMAND) 00941 { 00942 do { 00943 /* Send CMD55 (SD_CMD_APP_CMD) before any ACMD command: R1 response (0x00: no errors) */ 00944 response = SD_SendCmd(SD_CMD_APP_CMD, 0, 0xFF, SD_ANSWER_R1_EXPECTED); 00945 SD_IO_CSState(1); 00946 SD_IO_WriteByte(SD_DUMMY_BYTE); 00947 if(response.r1 != SD_R1_IN_IDLE_STATE) 00948 { 00949 return BSP_SD_ERROR; 00950 } 00951 /* Send ACMD41 (SD_CMD_SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors) */ 00952 response = SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x00000000, 0xFF, SD_ANSWER_R1_EXPECTED); 00953 SD_IO_CSState(1); 00954 SD_IO_WriteByte(SD_DUMMY_BYTE); 00955 } 00956 while(response.r1 == SD_R1_IN_IDLE_STATE); 00957 } 00958 00959 /* Send CMD58 (SD_CMD_READ_OCR) to initialize SDHC or SDXC cards: R3 response (0x00: no errors) */ 00960 response = SD_SendCmd(SD_CMD_READ_OCR, 0x00000000, 0xFF, SD_ANSWER_R3_EXPECTED); 00961 SD_IO_CSState(1); 00962 SD_IO_WriteByte(SD_DUMMY_BYTE); 00963 if(response.r1 != SD_R1_NO_ERROR) 00964 { 00965 return BSP_SD_ERROR; 00966 } 00967 flag_SDHC = (response.r2 & 0x40) >> 6; 00968 } 00969 else 00970 { 00971 return BSP_SD_ERROR; 00972 } 00973 00974 return BSP_SD_OK; 00975 } 00976 00977 /** 00978 * @brief Waits a data until a value different from SD_DUMMY_BITE 00979 * @retval the value read 00980 */ 00981 uint8_t SD_ReadData(void) 00982 { 00983 uint8_t timeout = 0x08; 00984 uint8_t readvalue; 00985 00986 /* Check if response is got or a timeout is happen */ 00987 do { 00988 readvalue = SD_IO_WriteByte(SD_DUMMY_BYTE); 00989 timeout--; 00990 00991 }while ((readvalue == SD_DUMMY_BYTE) && timeout); 00992 00993 /* Right response got */ 00994 return readvalue; 00995 } 00996 00997 /** 00998 * @brief Waits a data from the SD card 00999 * @param data Expected data from the SD card 01000 * @retval BSP_SD_OK or BSP_SD_TIMEOUT 01001 */ 01002 uint8_t SD_WaitData(uint8_t data) 01003 { 01004 uint16_t timeout = 0xFFFF; 01005 uint8_t readvalue; 01006 01007 /* Check if response is got or a timeout is happen */ 01008 01009 do { 01010 readvalue = SD_IO_WriteByte(SD_DUMMY_BYTE); 01011 timeout--; 01012 }while ((readvalue != data) && timeout); 01013 01014 if (timeout == 0) 01015 { 01016 /* After time out */ 01017 return BSP_SD_TIMEOUT; 01018 } 01019 01020 /* Right response got */ 01021 return BSP_SD_OK; 01022 } 01023 01024 /** 01025 * @} 01026 */ 01027 01028 /** 01029 * @} 01030 */ 01031 01032 /** 01033 * @} 01034 */ 01035 01036 /** 01037 * @} 01038 */ 01039 01040 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Wed Jul 5 2017 08:56:10 for STM32072B_EVAL BSP User Manual by
