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