STM8S/A Standard Peripherals Firmware Library: stm8s_eval_spi_sd.c Source File

STM8S/A

stm8s_eval_spi_sd.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm8s_eval_spi_sd.c
00004   * @author  MCD Application Team
00005   * @version V1.0.1
00006   * @date    30-September-2014
00007   * @brief   This file provides a set of functions needed to manage the SPI SD
00008   *          Card memory mounted on STM8xx-EVAL board (refer to stm8s_eval.h
00009   *          to know about the boards supporting this memory).
00010   *          It implements a high level communication layer for read and write
00011   *          from/to this memory. The needed STM8 hardware resources (SPI and
00012   *          GPIO) are defined in stm8xx_eval.h file, and the initialization is
00013   *          performed in SD_LowLevel_Init() function declared in stm8xx_eval.c
00014   *          file.
00015   *          You can easily tailor this driver to any other development board,
00016   *          by just adapting the defines for hardware resources and
00017   *          SD_LowLevel_Init() function.
00018   *
00019   *          +-------------------------------------------------------+
00020   *          |                     Pin assignment                    |
00021   *          +-------------------------+---------------+-------------+
00022   *          |  STM8 SPI Pins         |     SD        |    Pin      |
00023   *          +-------------------------+---------------+-------------+
00024   *          | SD_SPI_CS_PIN           |   ChipSelect  |    1        |
00025   *          | SD_SPI_MOSI_PIN / MOSI  |   DataIn      |    2        |
00026   *          |                         |   GND         |    3 (0 V)  |
00027   *          |                         |   VDD         |    4 (3.3 V)|
00028   *          | SD_SPI_SCK_PIN / SCLK   |   Clock       |    5        |
00029   *          |                         |   GND         |    6 (0 V)  |
00030   *          | SD_SPI_MISO_PIN / MISO  |   DataOut     |    7        |
00031   *          +-------------------------+---------------+-------------+
00032   ******************************************************************************
00033   *
00034   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
00035   * You may not use this file except in compliance with the License.
00036   * You may obtain a copy of the License at:
00037   *
00038   *        http://www.st.com/software_license_agreement_liberty_v2
00039   *
00040   * Unless required by applicable law or agreed to in writing, software 
00041   * distributed under the License is distributed on an "AS IS" BASIS, 
00042   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00043   * See the License for the specific language governing permissions and
00044   * limitations under the License.
00045   *
00046   ******************************************************************************
00047   */
00048 
00049 /* Includes ------------------------------------------------------------------*/
00050 #include "stm8s_eval_spi_sd.h"
00051 
00052 /** @addtogroup Utilities
00053   * @{
00054   */
00055 
00056 /** @addtogroup STM8S_EVAL
00057   * @{
00058   */
00059 
00060 /** @addtogroup Common
00061   * @{
00062   */
00063 
00064 /* Private typedef -----------------------------------------------------------*/
00065 /* Private define ------------------------------------------------------------*/
00066 /* Private macro -------------------------------------------------------------*/
00067 /* Private function prototypes -----------------------------------------------*/
00068 
00069 /** @defgroup STM8S_EVAL_SPI_SD_Private_Functions
00070   * @{
00071   */
00072 
00073 /**
00074   * @brief  DeInitializes the SD/SD communication.
00075   * @param  None
00076   * @retval None
00077   */
00078 void SD_DeInit(void)
00079 {
00080   SD_LowLevel_DeInit();
00081 }
00082 
00083 /**
00084   * @brief  Initializes the SD/SD communication.
00085   * @param  None
00086   * @retval The SD Response:
00087   *         - SD_RESPONSE_FAILURE: Sequence failed
00088   *         - SD_RESPONSE_NO_ERROR: Sequence succeed
00089   */
00090 uint8_t SD_Init(void)
00091 {
00092   uint32_t i = 0;
00093 
00094   /*!< Initialize SD_SPI */
00095   SD_LowLevel_Init();
00096 
00097   /*!< SD chip select high */
00098   SD_CS_LOW();
00099 
00100   /*!< Send dummy byte 0xFF, 10 times with CS high */
00101   /*!< Rise CS and MOSI for 80 clocks cycles */
00102   for (i = 0; i <= 9; i++)
00103   {
00104     /*!< Send dummy byte 0xFF */
00105     SD_WriteByte(SD_DUMMY_BYTE);
00106   }
00107   /*------------Put SD in SPI mode--------------*/
00108   /*!< SD initialized and set to SPI mode properly */
00109   return (SD_GoIdleState());
00110 }
00111 
00112 /**
00113  * @brief  Detect if SD card is correctly plugged in the memory slot.
00114  * @param  None
00115  * @retval Return if SD is detected or not
00116  */
00117 uint8_t SD_Detect(void)
00118 {
00119   __IO uint8_t status = SD_PRESENT;
00120 
00121   /*!< Check GPIO to detect SD */
00122   if (GPIO_ReadInputData(SD_DETECT_GPIO_PORT) & SD_DETECT_PIN)
00123   {
00124     status = SD_NOT_PRESENT;
00125   }
00126   return status;
00127 }
00128 
00129 /**
00130   * @brief  Returns information about specific card.
00131   * @param  cardinfo: pointer to a SD_CardInfo structure that contains all SD
00132   *         card information.
00133   * @retval The SD Response:
00134   *         - SD_RESPONSE_FAILURE: Sequence failed
00135   *         - SD_RESPONSE_NO_ERROR: Sequence succeed
00136   */
00137 uint8_t SD_GetCardInfo(SD_CardInfo *cardinfo)
00138 {
00139   uint8_t status = SD_RESPONSE_FAILURE;
00140 
00141   status = SD_GetCSDRegister(&(cardinfo->SD_csd));
00142   status = SD_GetCIDRegister(&(cardinfo->SD_cid));
00143   cardinfo->CardCapacity = (cardinfo->SD_csd.DeviceSize + 1) ;
00144   cardinfo->CardCapacity *= (1 << (cardinfo->SD_csd.DeviceSizeMul + 2));
00145   cardinfo->CardBlockSize = 1 << (cardinfo->SD_csd.RdBlockLen);
00146   cardinfo->CardCapacity *= cardinfo->CardBlockSize;
00147 
00148   /*!< Returns the response */
00149   return status;
00150 }
00151 
00152 /**
00153   * @brief  Reads a block of data from the SD.
00154   * @param  pBuffer: pointer to the buffer that receives the data read from the
00155   *                  SD.
00156   * @param  ReadAddr: SD's internal address to read from.
00157   * @param  BlockSize: the SD card Data block size.
00158   * @retval The SD Response:
00159   *         - SD_RESPONSE_FAILURE: Sequence failed
00160   *         - SD_RESPONSE_NO_ERROR: Sequence succeed
00161   */
00162 uint8_t SD_ReadBlock(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t BlockSize)
00163 {
00164   uint32_t i = 0;
00165   uint8_t rvalue = SD_RESPONSE_FAILURE;
00166 
00167   /*!< SD chip select low */
00168   SD_CS_LOW();
00169 
00170   /*!< Send CMD17 (SD_CMD_READ_SINGLE_BLOCK) to read one block */
00171   SD_SendCmd(SD_CMD_READ_SINGLE_BLOCK, ReadAddr, 0xFF);
00172 
00173   /*!< Check if the SD acknowledged the read block command: R1 response (0x00: no errors) */
00174   if (!SD_GetResponse(SD_RESPONSE_NO_ERROR))
00175   {
00176     /*!< Now look for the data token to signify the start of the data */
00177     if (!SD_GetResponse(SD_START_DATA_SINGLE_BLOCK_READ))
00178     {
00179       /*!< Read the SD block data : read NumByteToRead data */
00180       for (i = 0; i < BlockSize; i++)
00181       {
00182         /*!< Save the received data */
00183         *pBuffer = SD_ReadByte();
00184 
00185         /*!< Point to the next location where the byte read will be saved */
00186         pBuffer++;
00187       }
00188       /*!< Get CRC bytes (not really needed by us, but required by SD) */
00189       SD_ReadByte();
00190       SD_ReadByte();
00191       /*!< Set response value to success */
00192       rvalue = SD_RESPONSE_NO_ERROR;
00193     }
00194   }
00195   /*!< SD chip select high */
00196   SD_CS_HIGH();
00197 
00198   /*!< Send dummy byte: 8 Clock pulses of delay */
00199   SD_WriteByte(SD_DUMMY_BYTE);
00200 
00201   /*!< Returns the response */
00202   return rvalue;
00203 
00204 }
00205 
00206 /**
00207   * @brief  Read a buffer (many blocks) from the SD card.
00208   * @param  pBuffer : pointer to the buffer that receives the data read from the SD.
00209   * @param  ReadAddr : SD's internal address to read from.
00210   * @param  NumByteToRead : number of bytes to read from the SD.
00211   * @retval SD Response:
00212   *   - SD_RESPONSE_FAILURE: Sequence failed.
00213   *   - SD_RESPONSE_NO_ERROR: Sequence succeed.
00214   */
00215 uint8_t SD_ReadBuffer(uint8_t *pBuffer, uint32_t ReadAddr, uint32_t NumByteToRead)
00216 {
00217   uint32_t i = 0, NbrOfBlock = 0, Offset = 0;
00218   uint8_t rvalue = SD_RESPONSE_FAILURE;
00219 
00220   /* Calculate number of blocks to read */
00221   NbrOfBlock = NumByteToRead / SD_BLOCK_SIZE;
00222   /* SD chip select low */
00223   SD_CS_LOW();
00224 
00225   /* Data transfer */
00226   while (NbrOfBlock --)
00227   {
00228     /* Send CMD17 (SD_READ_SINGLE_BLOCK) to read one block */
00229     SD_SendCmd (SD_CMD_READ_SINGLE_BLOCK, ReadAddr + Offset, 0xFF);
00230     /* Check if the SD acknowledged the read block command: R1 response (0x00: no errors) */
00231     if (SD_GetResponse(SD_RESPONSE_NO_ERROR))
00232     {
00233       return  SD_RESPONSE_FAILURE;
00234     }
00235     /* Now look for the data token to signify the start of the data */
00236     if (!SD_GetResponse(SD_START_DATA_SINGLE_BLOCK_READ))
00237     {
00238       /* Read the SD block data : read NumByteToRead data */
00239       for (i = 0; i < SD_BLOCK_SIZE; i++)
00240       {
00241         /* Read the pointed data */
00242         *pBuffer = SD_ReadByte();
00243         /* Point to the next location where the byte read will be saved */
00244         pBuffer++;
00245       }
00246       /* Set next read address*/
00247       Offset += 512;
00248       /* get CRC bytes (not really needed by us, but required by SD) */
00249       SD_ReadByte();
00250       SD_ReadByte();
00251       /* Set response value to success */
00252       rvalue = SD_RESPONSE_NO_ERROR;
00253     }
00254     else
00255     {
00256       /* Set response value to failure */
00257       rvalue = SD_RESPONSE_FAILURE;
00258     }
00259   }
00260 
00261   /* SD chip select high */
00262   SD_CS_HIGH();
00263   /* Send dummy byte: 8 Clock pulses of delay */
00264   SD_WriteByte(SD_DUMMY_BYTE);
00265   /* Returns the response */
00266   return rvalue;
00267 }
00268 
00269 /**
00270   * @brief  Writes a block on the SD
00271   * @param  pBuffer: pointer to the buffer containing the data to be written on
00272   *                  the SD.
00273   * @param  WriteAddr: address to write on.
00274   * @param  BlockSize: the SD card Data block size.
00275   * @retval The SD Response:
00276   *         - SD_RESPONSE_FAILURE: Sequence failed
00277   *         - SD_RESPONSE_NO_ERROR: Sequence succeed
00278   */
00279 uint8_t SD_WriteBlock(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t BlockSize)
00280 {
00281   uint32_t i = 0;
00282   uint8_t rvalue = SD_RESPONSE_FAILURE;
00283 
00284   /*!< SD chip select low */
00285   SD_CS_LOW();
00286 
00287   /*!< Send CMD24 (SD_CMD_WRITE_SINGLE_BLOCK) to write multiple block */
00288   SD_SendCmd(SD_CMD_WRITE_SINGLE_BLOCK, WriteAddr, 0xFF);
00289 
00290   /*!< Check if the SD acknowledged the write block command: R1 response (0x00: no errors) */
00291   if (!SD_GetResponse(SD_RESPONSE_NO_ERROR))
00292   {
00293     /*!< Send a dummy byte */
00294     SD_WriteByte(SD_DUMMY_BYTE);
00295 
00296     /*!< Send the data token to signify the start of the data */
00297     SD_WriteByte(0xFE);
00298 
00299     /*!< Write the block data to SD : write count data by block */
00300     for (i = 0; i < BlockSize; i++)
00301     {
00302       /*!< Send the pointed byte */
00303       SD_WriteByte(*pBuffer);
00304       /*!< Point to the next location where the byte read will be saved */
00305       pBuffer++;
00306     }
00307 
00308     /* Send DUMMY bytes when the number of data to be written are lower
00309        than the SD card BLOCK size (512 Byte) */
00310     for (; i != SD_BLOCK_SIZE; i++)
00311     {
00312       /* Send the pointed byte */
00313       SD_WriteByte(SD_DUMMY_BYTE);
00314     }
00315 
00316     /*!< Put CRC bytes (not really needed by us, but required by SD) */
00317     SD_ReadByte();
00318     SD_ReadByte();
00319 
00320     /*!< Read data response */
00321     if (SD_GetDataResponse() == SD_DATA_OK)
00322     {
00323       rvalue = SD_RESPONSE_NO_ERROR;
00324     }
00325   }
00326   /*!< SD chip select high */
00327   SD_CS_HIGH();
00328   /*!< Send dummy byte: 8 Clock pulses of delay */
00329   SD_WriteByte(SD_DUMMY_BYTE);
00330 
00331   /*!< Returns the response */
00332   return rvalue;
00333 
00334 }
00335 
00336 
00337 /**
00338   * @brief  Write a buffer (many blocks) in the SD card.
00339   * @note   The amount of data to write should be a multiple of SD card BLOCK
00340   *         size (512 Byte).
00341   * @param  pBuffer : pointer to the buffer containing the data to be written on the SD.
00342   * @param  WriteAddr : address to write on.
00343   * @param  NumByteToWrite : number of data to write.
00344   * @retval SD Response:
00345   *   - SD_RESPONSE_FAILURE: Sequence failed.
00346   *   - SD_RESPONSE_NO_ERROR: Sequence succeed.
00347   */
00348 uint8_t SD_WriteBuffer(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t NumByteToWrite)
00349 {
00350   uint32_t i = 0, NbrOfBlock = 0, Offset = 0;
00351   uint8_t rvalue = SD_RESPONSE_FAILURE;
00352 
00353   /* Calculate number of blocks to write */
00354   NbrOfBlock = NumByteToWrite / SD_BLOCK_SIZE;
00355   /* SD chip select low */
00356   SD_CS_LOW();
00357 
00358   /* Data transfer */
00359   while (NbrOfBlock--)
00360   {
00361     /* Send CMD24 (SD_WRITE_BLOCK) to write blocks */
00362     SD_SendCmd(SD_CMD_WRITE_SINGLE_BLOCK, WriteAddr + Offset, 0xFF);
00363 
00364     /* Check if the SD acknowledged the write block command: R1 response (0x00: no errors) */
00365     if (SD_GetResponse(SD_RESPONSE_NO_ERROR))
00366     {
00367       return SD_RESPONSE_FAILURE;
00368     }
00369     /* Send dummy byte */
00370     SD_WriteByte(SD_DUMMY_BYTE);
00371     /* Send the data token to signify the start of the data */
00372     SD_WriteByte(SD_START_DATA_SINGLE_BLOCK_WRITE);
00373     /* Write the block data to SD : write count data by block */
00374     for (i = 0; i < SD_BLOCK_SIZE; i++)
00375     {
00376       /* Send the pointed byte */
00377       SD_WriteByte(*pBuffer);
00378       /* Point to the next location where the byte read will be saved */
00379       pBuffer++;
00380     }
00381     /* Set next write address */
00382     Offset += 512;
00383     /* Put CRC bytes (not really needed by us, but required by SD) */
00384     SD_ReadByte();
00385     SD_ReadByte();
00386     /* Read data response */
00387     if (SD_GetDataResponse() == SD_DATA_OK)
00388     {
00389       /* Set response value to success */
00390       rvalue = SD_RESPONSE_NO_ERROR;
00391     }
00392     else
00393     {
00394       /* Set response value to failure */
00395       rvalue = SD_RESPONSE_FAILURE;
00396     }
00397   }
00398 
00399   /* SD chip select high */
00400   SD_CS_HIGH();
00401   /* Send dummy byte: 8 Clock pulses of delay */
00402   SD_WriteByte(SD_DUMMY_BYTE);
00403   /* Returns the response */
00404   return rvalue;
00405 }
00406 
00407 /**
00408   * @brief  Read the CSD card register.
00409   *         Reading the contents of the CSD register in SPI mode is a simple
00410   *         read-block transaction.
00411   * @param  SD_csd: pointer on an SCD register structure
00412   * @retval The SD Response:
00413   *         - SD_RESPONSE_FAILURE: Sequence failed
00414   *         - SD_RESPONSE_NO_ERROR: Sequence succeed
00415   */
00416 uint8_t SD_GetCSDRegister(SD_CSD* SD_csd)
00417 {
00418   uint32_t i = 0;
00419   uint8_t rvalue = SD_RESPONSE_FAILURE;
00420   uint8_t CSD_Tab[16];
00421 
00422   /*!< SD chip select low */
00423   SD_CS_LOW();
00424   /*!< Send CMD9 (CSD register) or CMD10(CSD register) */
00425   SD_SendCmd(SD_CMD_SEND_CSD, 0, 0xFF);
00426   /*!< Wait for response in the R1 format (0x00 is no errors) */
00427   if (!SD_GetResponse(SD_RESPONSE_NO_ERROR))
00428   {
00429     if (!SD_GetResponse(SD_START_DATA_SINGLE_BLOCK_READ))
00430     {
00431       for (i = 0; i < 16; i++)
00432       {
00433         /*!< Store CSD register value on CSD_Tab */
00434         CSD_Tab[i] = SD_ReadByte();
00435       }
00436     }
00437     /*!< Get CRC bytes (not really needed by us, but required by SD) */
00438     SD_WriteByte(SD_DUMMY_BYTE);
00439     SD_WriteByte(SD_DUMMY_BYTE);
00440     /*!< Set response value to success */
00441     rvalue = SD_RESPONSE_NO_ERROR;
00442   }
00443   /*!< SD chip select high */
00444   SD_CS_HIGH();
00445   /*!< Send dummy byte: 8 Clock pulses of delay */
00446   SD_WriteByte(SD_DUMMY_BYTE);
00447 
00448   /*!< Byte 0 */
00449   SD_csd->CSDStruct = (uint8_t)((CSD_Tab[0] & 0xC0) >> 6);
00450   SD_csd->SysSpecVersion = (uint8_t)((CSD_Tab[0] & 0x3C) >> 2);
00451   SD_csd->Reserved1 = (uint8_t)(CSD_Tab[0] & 0x03);
00452 
00453   /*!< Byte 1 */
00454   SD_csd->TAAC = CSD_Tab[1];
00455 
00456   /*!< Byte 2 */
00457   SD_csd->NSAC = CSD_Tab[2];
00458 
00459   /*!< Byte 3 */
00460   SD_csd->MaxBusClkFrec = CSD_Tab[3];
00461 
00462   /*!< Byte 4 */
00463   SD_csd->CardComdClasses = CSD_Tab[4] << 4;
00464 
00465   /*!< Byte 5 */
00466   SD_csd->CardComdClasses |= (CSD_Tab[5] & 0xF0) >> 4;
00467   SD_csd->RdBlockLen = (uint8_t)(CSD_Tab[5] & 0x0F);
00468 
00469   /*!< Byte 6 */
00470   SD_csd->PartBlockRead = (uint8_t)((CSD_Tab[6] & 0x80) >> 7);
00471   SD_csd->WrBlockMisalign = (uint8_t)((CSD_Tab[6] & 0x40) >> 6);
00472   SD_csd->RdBlockMisalign = (uint8_t)((CSD_Tab[6] & 0x20) >> 5);
00473   SD_csd->DSRImpl = (uint8_t)((CSD_Tab[6] & 0x10) >> 4);
00474   SD_csd->Reserved2 = 0; /*!< Reserved */
00475 
00476   SD_csd->DeviceSize = (CSD_Tab[6] & 0x03) << 10;
00477 
00478   /*!< Byte 7 */
00479   SD_csd->DeviceSize |= (CSD_Tab[7]) << 2;
00480 
00481   /*!< Byte 8 */
00482   SD_csd->DeviceSize |= (CSD_Tab[8] & 0xC0) >> 6;
00483 
00484   SD_csd->MaxRdCurrentVDDMin = (uint8_t)((CSD_Tab[8] & 0x38) >> 3);
00485   SD_csd->MaxRdCurrentVDDMax = (uint8_t)((CSD_Tab[8] & 0x07));
00486 
00487   /*!< Byte 9 */
00488   SD_csd->MaxWrCurrentVDDMin = (uint8_t)((CSD_Tab[9] & 0xE0) >> 5);
00489   SD_csd->MaxWrCurrentVDDMax = (uint8_t)((CSD_Tab[9] & 0x1C) >> 2);
00490   SD_csd->DeviceSizeMul = (uint8_t)((CSD_Tab[9] & 0x03) << 1);
00491   /*!< Byte 10 */
00492   SD_csd->DeviceSizeMul |= (uint8_t)((CSD_Tab[10] & 0x80) >> 7);
00493 
00494   SD_csd->EraseGrSize = (uint8_t)((CSD_Tab[10] & 0x40) >> 6);
00495   SD_csd->EraseGrMul = (uint8_t)((CSD_Tab[10] & 0x3F) << 1);
00496 
00497   /*!< Byte 11 */
00498   SD_csd->EraseGrMul |= (uint8_t)((CSD_Tab[11] & 0x80) >> 7);
00499   SD_csd->WrProtectGrSize = (uint8_t)((CSD_Tab[11] & 0x7F));
00500 
00501   /*!< Byte 12 */
00502   SD_csd->WrProtectGrEnable = (uint8_t)((CSD_Tab[12] & 0x80) >> 7);
00503   SD_csd->ManDeflECC = (uint8_t)((CSD_Tab[12] & 0x60) >> 5);
00504   SD_csd->WrSpeedFact = (uint8_t)((CSD_Tab[12] & 0x1C) >> 2);
00505   SD_csd->MaxWrBlockLen = (uint8_t)((CSD_Tab[12] & 0x03) << 2);
00506 
00507   /*!< Byte 13 */
00508   SD_csd->MaxWrBlockLen |= (uint8_t)((CSD_Tab[13] & 0xC0) >> 6);
00509   SD_csd->WriteBlockPaPartial = (uint8_t)((CSD_Tab[13] & 0x20) >> 5);
00510   SD_csd->Reserved3 = 0;
00511   SD_csd->ContentProtectAppli = (uint8_t)(CSD_Tab[13] & 0x01);
00512 
00513   /*!< Byte 14 */
00514   SD_csd->FileFormatGrouop = (uint8_t)((CSD_Tab[14] & 0x80) >> 7);
00515   SD_csd->CopyFlag = (uint8_t)((CSD_Tab[14] & 0x40) >> 6);
00516   SD_csd->PermWrProtect = (uint8_t)((CSD_Tab[14] & 0x20) >> 5);
00517   SD_csd->TempWrProtect = (uint8_t)((CSD_Tab[14] & 0x10) >> 4);
00518   SD_csd->FileFormat = (uint8_t)((CSD_Tab[14] & 0x0C) >> 2);
00519   SD_csd->ECC = (uint8_t)(CSD_Tab[14] & 0x03);
00520 
00521   /*!< Byte 15 */
00522   SD_csd->CSD_CRC = (uint8_t)((CSD_Tab[15] & 0xFE) >> 1);
00523   SD_csd->Reserved4 = 1;
00524 
00525   /*!< Return the response */
00526   return rvalue;
00527 }
00528 
00529 /**
00530   * @brief  Read the CID card register.
00531   *         Reading the contents of the CID register in SPI mode is a simple
00532   *         read-block transaction.
00533   * @param  SD_cid: pointer on an CID register structure
00534   * @retval The SD Response:
00535   *         - SD_RESPONSE_FAILURE: Sequence failed
00536   *         - SD_RESPONSE_NO_ERROR: Sequence succeed
00537   */
00538 uint8_t SD_GetCIDRegister(SD_CID* SD_cid)
00539 {
00540   uint32_t i = 0;
00541   uint8_t rvalue = SD_RESPONSE_FAILURE;
00542   uint8_t CID_Tab[16];
00543 
00544   /*!< SD chip select low */
00545   SD_CS_LOW();
00546 
00547   /*!< Send CMD10 (CID register) */
00548   SD_SendCmd(SD_CMD_SEND_CID, 0, 0xFF);
00549 
00550   /*!< Wait for response in the R1 format (0x00 is no errors) */
00551   if (!SD_GetResponse(SD_RESPONSE_NO_ERROR))
00552   {
00553     if (!SD_GetResponse(SD_START_DATA_SINGLE_BLOCK_READ))
00554     {
00555       /*!< Store CID register value on CID_Tab */
00556       for (i = 0; i < 16; i++)
00557       {
00558         CID_Tab[i] = SD_ReadByte();
00559       }
00560     }
00561     /*!< Get CRC bytes (not really needed by us, but required by SD) */
00562     SD_WriteByte(SD_DUMMY_BYTE);
00563     SD_WriteByte(SD_DUMMY_BYTE);
00564     /*!< Set response value to success */
00565     rvalue = SD_RESPONSE_NO_ERROR;
00566   }
00567   /*!< SD chip select high */
00568   SD_CS_HIGH();
00569   /*!< Send dummy byte: 8 Clock pulses of delay */
00570   SD_WriteByte(SD_DUMMY_BYTE);
00571 
00572   /*!< Byte 0 */
00573   SD_cid->ManufacturerID = CID_Tab[0];
00574 
00575   /*!< Byte 1 */
00576   SD_cid->OEM_AppliID = CID_Tab[1] << 8;
00577 
00578   /*!< Byte 2 */
00579   SD_cid->OEM_AppliID |= CID_Tab[2];
00580 
00581   /*!< Byte 3 */
00582   SD_cid->ProdName1 = ((uint32_t)CID_Tab[3] << 24);
00583 
00584   /*!< Byte 4 */
00585   SD_cid->ProdName1 |= ((uint32_t)CID_Tab[4] << 16);
00586 
00587   /*!< Byte 5 */
00588   SD_cid->ProdName1 |= CID_Tab[5] << 8;
00589 
00590   /*!< Byte 6 */
00591   SD_cid->ProdName1 |= CID_Tab[6];
00592 
00593   /*!< Byte 7 */
00594   SD_cid->ProdName2 = CID_Tab[7];
00595 
00596   /*!< Byte 8 */
00597   SD_cid->ProdRev = CID_Tab[8];
00598 
00599   /*!< Byte 9 */
00600   SD_cid->ProdSN = ((uint32_t)CID_Tab[9] << 24);
00601 
00602   /*!< Byte 10 */
00603   SD_cid->ProdSN |= ((uint32_t)CID_Tab[10] << 16);
00604 
00605   /*!< Byte 11 */
00606   SD_cid->ProdSN |= CID_Tab[11] << 8;
00607 
00608   /*!< Byte 12 */
00609   SD_cid->ProdSN |= CID_Tab[12];
00610 
00611   /*!< Byte 13 */
00612   SD_cid->Reserved1 |= (uint8_t)((CID_Tab[13] & 0xF0) >> 4);
00613   SD_cid->ManufactDate = (CID_Tab[13] & 0x0F) << 8;
00614 
00615   /*!< Byte 14 */
00616   SD_cid->ManufactDate |= CID_Tab[14];
00617 
00618   /*!< Byte 15 */
00619   SD_cid->CID_CRC = (uint8_t)((CID_Tab[15] & 0xFE) >> 1);
00620   SD_cid->Reserved2 = 1;
00621 
00622   /*!< Return the response */
00623   return rvalue;
00624 }
00625 
00626 /**
00627   * @brief  Send 5 bytes command to the SD card.
00628   * @param  Cmd: The user expected command to send to SD card.
00629   * @param  Arg: The command argument.
00630   * @param  Crc: The CRC.
00631   * @retval None
00632   */
00633 void SD_SendCmd(uint8_t Cmd, uint32_t Arg, uint8_t Crc)
00634 {
00635   uint32_t i = 0x00;
00636 
00637   uint8_t Frame[6];
00638 
00639   Frame[0] = (uint8_t)(Cmd | 0x40); /*!< Construct byte 1 */
00640 
00641   Frame[1] = (uint8_t)(Arg >> 24); /*!< Construct byte 2 */
00642 
00643   Frame[2] = (uint8_t)(Arg >> 16); /*!< Construct byte 3 */
00644 
00645   Frame[3] = (uint8_t)(Arg >> 8); /*!< Construct byte 4 */
00646 
00647   Frame[4] = (uint8_t)(Arg); /*!< Construct byte 5 */
00648 
00649   Frame[5] = (Crc); /*!< Construct CRC: byte 6 */
00650 
00651   for (i = 0; i < 6; i++)
00652   {
00653     SD_WriteByte(Frame[i]); /*!< Send the Cmd bytes */
00654   }
00655 }
00656 
00657 /**
00658   * @brief  Get SD card data response.
00659   * @param  None
00660   * @retval The SD status: Read data response xxx0<status>1
00661   *         - status 010: Data accepted
00662   *         - status 101: Data rejected due to a crc error
00663   *         - status 110: Data rejected due to a Write error.
00664   *         - status 111: Data rejected due to other error.
00665   */
00666 uint8_t SD_GetDataResponse(void)
00667 {
00668   uint32_t i = 0;
00669   uint8_t response = 0, rvalue = 0;
00670 
00671   while (i <= 64)
00672   {
00673     /*!< Read response */
00674     response = SD_ReadByte();
00675     /*!< Mask unused bits */
00676     response &= 0x1F;
00677     switch (response)
00678     {
00679       case SD_DATA_OK:
00680       {
00681         rvalue = SD_DATA_OK;
00682         break;
00683       }
00684       case SD_DATA_CRC_ERROR:
00685         return SD_DATA_CRC_ERROR;
00686       case SD_DATA_WRITE_ERROR:
00687         return SD_DATA_WRITE_ERROR;
00688       default:
00689       {
00690         rvalue = SD_DATA_OTHER_ERROR;
00691         break;
00692       }
00693     }
00694     /*!< Exit loop in case of data ok */
00695     if (rvalue == SD_DATA_OK)
00696       break;
00697     /*!< Increment loop counter */
00698     i++;
00699   }
00700 
00701   /*!< Wait null data */
00702   while (SD_ReadByte() == 0);
00703 
00704   /*!< Return response */
00705   return response;
00706 }
00707 
00708 /**
00709   * @brief  Returns the SD response.
00710   * @param  None
00711   * @retval The SD Response:
00712   *         - SD_RESPONSE_FAILURE: Sequence failed
00713   *         - SD_RESPONSE_NO_ERROR: Sequence succeed
00714   */
00715 uint8_t SD_GetResponse(uint8_t Response)
00716 {
00717   uint32_t Count = 0xFFF;
00718 
00719   /*!< Check if response is got or a timeout is happen */
00720   while ((SD_ReadByte() != Response) && Count)
00721   {
00722     Count--;
00723   }
00724   if (Count == 0)
00725   {
00726     /*!< After time out */
00727     return SD_RESPONSE_FAILURE;
00728   }
00729   else
00730   {
00731     /*!< Right response got */
00732     return SD_RESPONSE_NO_ERROR;
00733   }
00734 }
00735 
00736 /**
00737   * @brief  Returns the SD status.
00738   * @param  None
00739   * @retval The SD status.
00740   */
00741 uint16_t SD_GetStatus(void)
00742 {
00743   uint16_t Status = 0;
00744 
00745   /*!< SD chip select low */
00746   SD_CS_LOW();
00747 
00748   /*!< Send CMD13 (SD_SEND_STATUS) to get SD status */
00749   SD_SendCmd(SD_CMD_SEND_STATUS, 0, 0xFF);
00750 
00751   Status = SD_ReadByte();
00752   Status |= (uint16_t)(SD_ReadByte() << 8);
00753 
00754   /*!< SD chip select high */
00755   SD_CS_HIGH();
00756 
00757   /*!< Send dummy byte 0xFF */
00758   SD_WriteByte(SD_DUMMY_BYTE);
00759 
00760   return Status;
00761 }
00762 
00763 /**
00764   * @brief  Put SD in Idle state.
00765   * @param  None
00766   * @retval The SD Response:
00767   *         - SD_RESPONSE_FAILURE: Sequence failed
00768   *         - SD_RESPONSE_NO_ERROR: Sequence succeed
00769   */
00770 uint8_t SD_GoIdleState(void)
00771 {
00772   /*!< SD chip select low */
00773   SD_CS_LOW();
00774 
00775   /*!< Send CMD0 (SD_CMD_GO_IDLE_STATE) to put SD in SPI mode */
00776   SD_SendCmd(SD_CMD_GO_IDLE_STATE, 0, 0x95);
00777 
00778   /*!< Wait for In Idle State Response (R1 Format) equal to 0x01 */
00779   if (SD_GetResponse(SD_IN_IDLE_STATE))
00780   {
00781     /*!< No Idle State Response: return response failure */
00782     return SD_RESPONSE_FAILURE;
00783   }
00784   /*----------Activates the card initialization process-----------*/
00785   do
00786   {
00787     /*!< SD chip select high */
00788     SD_CS_HIGH();
00789 
00790     /*!< Send Dummy byte 0xFF */
00791     SD_WriteByte(SD_DUMMY_BYTE);
00792 
00793     /*!< SD chip select low */
00794     SD_CS_LOW();
00795 
00796     /*!< Send CMD1 (Activates the card process) until response equal to 0x0 */
00797     SD_SendCmd(SD_CMD_SEND_OP_COND, 0, 0xFF);
00798     /*!< Wait for no error Response (R1 Format) equal to 0x00 */
00799   }
00800   while (SD_GetResponse(SD_RESPONSE_NO_ERROR));
00801 
00802   /*!< SD chip select high */
00803   SD_CS_HIGH();
00804 
00805   /*!< Send dummy byte 0xFF */
00806   SD_WriteByte(SD_DUMMY_BYTE);
00807 
00808   return SD_RESPONSE_NO_ERROR;
00809 }
00810 
00811 /**
00812   * @brief  Write a byte on the SD.
00813   * @param  Data: byte to send.
00814   * @retval None
00815   */
00816 uint8_t SD_WriteByte(uint8_t Data)
00817 {
00818   /*!< Wait until the transmit buffer is empty */
00819   while (SPI_GetFlagStatus(SPI_FLAG_TXE) == RESET)
00820   {}
00821 
00822   /*!< Send the byte */
00823   SPI_SendData(Data);
00824 
00825   /*!< Wait to receive a byte*/
00826   while (SPI_GetFlagStatus(SPI_FLAG_RXNE) == RESET)
00827   {}
00828 
00829   /*!< Return the byte read from the SPI bus */
00830   return SPI_ReceiveData();
00831 }
00832 
00833 /**
00834   * @brief  Read a byte from the SD.
00835   * @param  None
00836   * @retval The received byte.
00837   */
00838 uint8_t SD_ReadByte(void)
00839 {
00840   uint8_t Data = 0;
00841 
00842   /*!< Wait until the transmit buffer is empty */
00843   while (SPI_GetFlagStatus(SPI_FLAG_TXE) == RESET)
00844   {}
00845   /*!< Send the byte */
00846   SPI_SendData(SD_DUMMY_BYTE);
00847 
00848   /*!< Wait until a data is received */
00849   while (SPI_GetFlagStatus(SPI_FLAG_RXNE) == RESET)
00850   {}
00851   /*!< Get the received data */
00852   Data = SPI_ReceiveData();
00853 
00854   /*!< Return the shifted data */
00855   return Data;
00856 }
00857 
00858 /**
00859   * @}
00860   */
00861 
00862 
00863 /**
00864   * @}
00865   */
00866 
00867 
00868 /**
00869   * @}
00870   */
00871 
00872 /**
00873   * @}
00874   */
00875 
00876 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
STM8 Standard Peripherals Library: Footer

 

 

 

      For complete documentation on STM8 8-bit Microcontrollers platform visit www.st.com