WILLY BAYOT / stm32_adafruit

Dependents:   TDEMNucleo

Committer:
willybayot
Date:
Sun Jan 04 13:25:59 2015 +0000
Revision:
0:4db361f2e6d5
ADAFRUIT revision

Who changed what in which revision?

UserRevisionLine numberNew contents of line
willybayot 0:4db361f2e6d5 1 /**
willybayot 0:4db361f2e6d5 2 ******************************************************************************
willybayot 0:4db361f2e6d5 3 * @file stm32_adafruit_sd.c
willybayot 0:4db361f2e6d5 4 * @author MCD Application Team
willybayot 0:4db361f2e6d5 5 * @version V1.0.0
willybayot 0:4db361f2e6d5 6 * @date 22-April-2014
willybayot 0:4db361f2e6d5 7 * @brief This file provides a set of functions needed to manage the SD card
willybayot 0:4db361f2e6d5 8 * mounted on the Adafruit 1.8" TFT LCD shield (reference ID 802),
willybayot 0:4db361f2e6d5 9 * that is used with the STM32 Nucleo board through SPI interface.
willybayot 0:4db361f2e6d5 10 * It implements a high level communication layer for read and write
willybayot 0:4db361f2e6d5 11 * from/to this memory. The needed STM32XXxx hardware resources (SPI and
willybayot 0:4db361f2e6d5 12 * GPIO) are defined in stm32XXxx_nucleo.h file, and the initialization is
willybayot 0:4db361f2e6d5 13 * performed in SD_IO_Init() function declared in stm32XXxx_nucleo.c
willybayot 0:4db361f2e6d5 14 * file.
willybayot 0:4db361f2e6d5 15 * You can easily tailor this driver to any other development board,
willybayot 0:4db361f2e6d5 16 * by just adapting the defines for hardware resources and
willybayot 0:4db361f2e6d5 17 * SD_IO_Init() function.
willybayot 0:4db361f2e6d5 18 *
willybayot 0:4db361f2e6d5 19 * +-------------------------------------------------------+
willybayot 0:4db361f2e6d5 20 * | Pin assignment |
willybayot 0:4db361f2e6d5 21 * +-------------------------+---------------+-------------+
willybayot 0:4db361f2e6d5 22 * | STM32XXxx SPI Pins | SD | Pin |
willybayot 0:4db361f2e6d5 23 * +-------------------------+---------------+-------------+
willybayot 0:4db361f2e6d5 24 * | SD_SPI_CS_PIN | ChipSelect | 1 |
willybayot 0:4db361f2e6d5 25 * | SD_SPI_MOSI_PIN / MOSI | DataIn | 2 |
willybayot 0:4db361f2e6d5 26 * | | GND | 3 (0 V) |
willybayot 0:4db361f2e6d5 27 * | | VDD | 4 (3.3 V)|
willybayot 0:4db361f2e6d5 28 * | SD_SPI_SCK_PIN / SCLK | Clock | 5 |
willybayot 0:4db361f2e6d5 29 * | | GND | 6 (0 V) |
willybayot 0:4db361f2e6d5 30 * | SD_SPI_MISO_PIN / MISO | DataOut | 7 |
willybayot 0:4db361f2e6d5 31 * +-------------------------+---------------+-------------+
willybayot 0:4db361f2e6d5 32 ******************************************************************************
willybayot 0:4db361f2e6d5 33 * @attention
willybayot 0:4db361f2e6d5 34 *
willybayot 0:4db361f2e6d5 35 * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
willybayot 0:4db361f2e6d5 36 *
willybayot 0:4db361f2e6d5 37 * Redistribution and use in source and binary forms, with or without modification,
willybayot 0:4db361f2e6d5 38 * are permitted provided that the following conditions are met:
willybayot 0:4db361f2e6d5 39 * 1. Redistributions of source code must retain the above copyright notice,
willybayot 0:4db361f2e6d5 40 * this list of conditions and the following disclaimer.
willybayot 0:4db361f2e6d5 41 * 2. Redistributions in binary form must reproduce the above copyright notice,
willybayot 0:4db361f2e6d5 42 * this list of conditions and the following disclaimer in the documentation
willybayot 0:4db361f2e6d5 43 * and/or other materials provided with the distribution.
willybayot 0:4db361f2e6d5 44 * 3. Neither the name of STMicroelectronics nor the names of its contributors
willybayot 0:4db361f2e6d5 45 * may be used to endorse or promote products derived from this software
willybayot 0:4db361f2e6d5 46 * without specific prior written permission.
willybayot 0:4db361f2e6d5 47 *
willybayot 0:4db361f2e6d5 48 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
willybayot 0:4db361f2e6d5 49 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
willybayot 0:4db361f2e6d5 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
willybayot 0:4db361f2e6d5 51 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
willybayot 0:4db361f2e6d5 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
willybayot 0:4db361f2e6d5 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
willybayot 0:4db361f2e6d5 54 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
willybayot 0:4db361f2e6d5 55 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
willybayot 0:4db361f2e6d5 56 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
willybayot 0:4db361f2e6d5 57 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
willybayot 0:4db361f2e6d5 58 *
willybayot 0:4db361f2e6d5 59 ******************************************************************************
willybayot 0:4db361f2e6d5 60 */
willybayot 0:4db361f2e6d5 61
willybayot 0:4db361f2e6d5 62 /* File Info : -----------------------------------------------------------------
willybayot 0:4db361f2e6d5 63 User NOTES
willybayot 0:4db361f2e6d5 64 1. How to use this driver:
willybayot 0:4db361f2e6d5 65 --------------------------
willybayot 0:4db361f2e6d5 66 - This driver does not need a specific component driver for the micro SD device
willybayot 0:4db361f2e6d5 67 to be included with.
willybayot 0:4db361f2e6d5 68
willybayot 0:4db361f2e6d5 69 2. Driver description:
willybayot 0:4db361f2e6d5 70 ---------------------
willybayot 0:4db361f2e6d5 71 + Initialization steps:
willybayot 0:4db361f2e6d5 72 o Initialize the micro SD card using the BSP_SD_Init() function.
willybayot 0:4db361f2e6d5 73 o Cheking the SD card presence is not managed because SD detection pin is
willybayot 0:4db361f2e6d5 74 not physically mapped on the Adafruit shield.
willybayot 0:4db361f2e6d5 75 o The function BSP_SD_GetCardInfo() is used to get the micro SD card information
willybayot 0:4db361f2e6d5 76 which is stored in the structure "SD_CardInfo".
willybayot 0:4db361f2e6d5 77
willybayot 0:4db361f2e6d5 78 + Micro SD card operations
willybayot 0:4db361f2e6d5 79 o The micro SD card can be accessed with read/write block(s) operations once
willybayot 0:4db361f2e6d5 80 it is ready for access. The access can be performed in polling
willybayot 0:4db361f2e6d5 81 mode by calling the functions BSP_SD_ReadBlocks()/BSP_SD_WriteBlocks()
willybayot 0:4db361f2e6d5 82
willybayot 0:4db361f2e6d5 83 o The SD erase block(s) is performed using the function BSP_SD_Erase() with
willybayot 0:4db361f2e6d5 84 specifying the number of blocks to erase.
willybayot 0:4db361f2e6d5 85 o The SD runtime status is returned when calling the function BSP_SD_GetStatus().
willybayot 0:4db361f2e6d5 86
willybayot 0:4db361f2e6d5 87 @note This driver's version interfacing SD card using SPI protocol, supports only
willybayot 0:4db361f2e6d5 88 SDSC (Secure Digital Standard Capacity) cards (capacity up to 4GB).
willybayot 0:4db361f2e6d5 89 ------------------------------------------------------------------------------*/
willybayot 0:4db361f2e6d5 90
willybayot 0:4db361f2e6d5 91 /* Includes ------------------------------------------------------------------*/
willybayot 0:4db361f2e6d5 92 #include "stm32_adafruit_sd.h"
willybayot 0:4db361f2e6d5 93
willybayot 0:4db361f2e6d5 94 /** @addtogroup BSP
willybayot 0:4db361f2e6d5 95 * @{
willybayot 0:4db361f2e6d5 96 */
willybayot 0:4db361f2e6d5 97
willybayot 0:4db361f2e6d5 98 /** @addtogroup STM32_ADAFRUIT
willybayot 0:4db361f2e6d5 99 * @{
willybayot 0:4db361f2e6d5 100 */
willybayot 0:4db361f2e6d5 101
willybayot 0:4db361f2e6d5 102 /** @defgroup STM32_ADAFRUIT_SD
willybayot 0:4db361f2e6d5 103 * @{
willybayot 0:4db361f2e6d5 104 */
willybayot 0:4db361f2e6d5 105
willybayot 0:4db361f2e6d5 106 /* Private typedef -----------------------------------------------------------*/
willybayot 0:4db361f2e6d5 107
willybayot 0:4db361f2e6d5 108 /** @defgroup STM32_ADAFRUIT_SD_Private_Types_Definitions
willybayot 0:4db361f2e6d5 109 * @{
willybayot 0:4db361f2e6d5 110 */
willybayot 0:4db361f2e6d5 111
willybayot 0:4db361f2e6d5 112 /**
willybayot 0:4db361f2e6d5 113 * @}
willybayot 0:4db361f2e6d5 114 */
willybayot 0:4db361f2e6d5 115
willybayot 0:4db361f2e6d5 116 /* Private define ------------------------------------------------------------*/
willybayot 0:4db361f2e6d5 117
willybayot 0:4db361f2e6d5 118 /** @defgroup STM32_ADAFRUIT_SD_Private_Defines
willybayot 0:4db361f2e6d5 119 * @{
willybayot 0:4db361f2e6d5 120 */
willybayot 0:4db361f2e6d5 121 #define SD_DUMMY_BYTE 0xFF
willybayot 0:4db361f2e6d5 122 #define SD_NO_RESPONSE_EXPECTED 0x80
willybayot 0:4db361f2e6d5 123 /**
willybayot 0:4db361f2e6d5 124 * @}
willybayot 0:4db361f2e6d5 125 */
willybayot 0:4db361f2e6d5 126
willybayot 0:4db361f2e6d5 127 /* Private macro -------------------------------------------------------------*/
willybayot 0:4db361f2e6d5 128
willybayot 0:4db361f2e6d5 129 /** @defgroup STM32_ADAFRUIT_SD_Private_Macros
willybayot 0:4db361f2e6d5 130 * @{
willybayot 0:4db361f2e6d5 131 */
willybayot 0:4db361f2e6d5 132
willybayot 0:4db361f2e6d5 133 /**
willybayot 0:4db361f2e6d5 134 * @}
willybayot 0:4db361f2e6d5 135 */
willybayot 0:4db361f2e6d5 136
willybayot 0:4db361f2e6d5 137 /* Private variables ---------------------------------------------------------*/
willybayot 0:4db361f2e6d5 138
willybayot 0:4db361f2e6d5 139 /** @defgroup STM32_ADAFRUIT_SD_Private_Variables
willybayot 0:4db361f2e6d5 140 * @{
willybayot 0:4db361f2e6d5 141 */
willybayot 0:4db361f2e6d5 142 __IO uint8_t SdStatus = SD_PRESENT;
willybayot 0:4db361f2e6d5 143
willybayot 0:4db361f2e6d5 144 /**
willybayot 0:4db361f2e6d5 145 * @}
willybayot 0:4db361f2e6d5 146 */
willybayot 0:4db361f2e6d5 147
willybayot 0:4db361f2e6d5 148 /* Private function prototypes -----------------------------------------------*/
willybayot 0:4db361f2e6d5 149 static uint8_t SD_GetCIDRegister(SD_CID* Cid);
willybayot 0:4db361f2e6d5 150 static uint8_t SD_GetCSDRegister(SD_CSD* Csd);
willybayot 0:4db361f2e6d5 151 static uint8_t SD_GetDataResponse(void);
willybayot 0:4db361f2e6d5 152 static uint8_t SD_GoIdleState(void);
willybayot 0:4db361f2e6d5 153 static uint8_t SD_SendCmd(uint8_t Cmd, uint32_t Arg, uint8_t Crc, uint8_t Response);
willybayot 0:4db361f2e6d5 154
willybayot 0:4db361f2e6d5 155 /** @defgroup STM32_ADAFRUIT_SD_Private_Function_Prototypes
willybayot 0:4db361f2e6d5 156 * @{
willybayot 0:4db361f2e6d5 157 */
willybayot 0:4db361f2e6d5 158 /**
willybayot 0:4db361f2e6d5 159 * @}
willybayot 0:4db361f2e6d5 160 */
willybayot 0:4db361f2e6d5 161
willybayot 0:4db361f2e6d5 162 /* Private functions ---------------------------------------------------------*/
willybayot 0:4db361f2e6d5 163
willybayot 0:4db361f2e6d5 164 /** @defgroup STM32_ADAFRUIT_SD_Private_Functions
willybayot 0:4db361f2e6d5 165 * @{
willybayot 0:4db361f2e6d5 166 */
willybayot 0:4db361f2e6d5 167
willybayot 0:4db361f2e6d5 168 /**
willybayot 0:4db361f2e6d5 169 * @brief Initializes the SD/SD communication.
willybayot 0:4db361f2e6d5 170 * @param None
willybayot 0:4db361f2e6d5 171 * @retval The SD Response:
willybayot 0:4db361f2e6d5 172 * - MSD_ERROR: Sequence failed
willybayot 0:4db361f2e6d5 173 * - MSD_OK: Sequence succeed
willybayot 0:4db361f2e6d5 174 */
willybayot 0:4db361f2e6d5 175 uint8_t BSP_SD_Init(void)
willybayot 0:4db361f2e6d5 176 {
willybayot 0:4db361f2e6d5 177 uint8_t status = MSD_ERROR;
willybayot 0:4db361f2e6d5 178
willybayot 0:4db361f2e6d5 179 /* Configure IO functionalities for SD pin */
willybayot 0:4db361f2e6d5 180 SD_IO_Init();
willybayot 0:4db361f2e6d5 181
willybayot 0:4db361f2e6d5 182 /* SD detection pin is not physically mapped on the Adafruit shield */
willybayot 0:4db361f2e6d5 183 SdStatus = SD_PRESENT;
willybayot 0:4db361f2e6d5 184
willybayot 0:4db361f2e6d5 185 /* SD initialized and set to SPI mode properly */
willybayot 0:4db361f2e6d5 186 status = SD_GoIdleState();
willybayot 0:4db361f2e6d5 187
willybayot 0:4db361f2e6d5 188 if (status == SD_RESPONSE_NO_ERROR)
willybayot 0:4db361f2e6d5 189 {
willybayot 0:4db361f2e6d5 190 return MSD_OK;
willybayot 0:4db361f2e6d5 191 }
willybayot 0:4db361f2e6d5 192 else
willybayot 0:4db361f2e6d5 193 {
willybayot 0:4db361f2e6d5 194 return MSD_ERROR;
willybayot 0:4db361f2e6d5 195 }
willybayot 0:4db361f2e6d5 196 }
willybayot 0:4db361f2e6d5 197
willybayot 0:4db361f2e6d5 198 /**
willybayot 0:4db361f2e6d5 199 * @brief Returns information about specific card.
willybayot 0:4db361f2e6d5 200 * @param pCardInfo: Pointer to a SD_CardInfo structure that contains all SD
willybayot 0:4db361f2e6d5 201 * card information.
willybayot 0:4db361f2e6d5 202 * @retval The SD Response:
willybayot 0:4db361f2e6d5 203 * - MSD_ERROR: Sequence failed
willybayot 0:4db361f2e6d5 204 * - MSD_OK: Sequence succeed
willybayot 0:4db361f2e6d5 205 */
willybayot 0:4db361f2e6d5 206 uint8_t BSP_SD_GetCardInfo(SD_CardInfo *pCardInfo)
willybayot 0:4db361f2e6d5 207 {
willybayot 0:4db361f2e6d5 208 uint8_t status = MSD_ERROR;
willybayot 0:4db361f2e6d5 209
willybayot 0:4db361f2e6d5 210 SD_GetCSDRegister(&(pCardInfo->Csd));
willybayot 0:4db361f2e6d5 211 status = SD_GetCIDRegister(&(pCardInfo->Cid));
willybayot 0:4db361f2e6d5 212 pCardInfo->CardCapacity = (pCardInfo->Csd.DeviceSize + 1) ;
willybayot 0:4db361f2e6d5 213 pCardInfo->CardCapacity *= (1 << (pCardInfo->Csd.DeviceSizeMul + 2));
willybayot 0:4db361f2e6d5 214 pCardInfo->CardBlockSize = 1 << (pCardInfo->Csd.RdBlockLen);
willybayot 0:4db361f2e6d5 215 pCardInfo->CardCapacity *= pCardInfo->CardBlockSize;
willybayot 0:4db361f2e6d5 216
willybayot 0:4db361f2e6d5 217 /* Returns the reponse */
willybayot 0:4db361f2e6d5 218 if (status == SD_RESPONSE_NO_ERROR)
willybayot 0:4db361f2e6d5 219 {
willybayot 0:4db361f2e6d5 220 return MSD_OK;
willybayot 0:4db361f2e6d5 221 }
willybayot 0:4db361f2e6d5 222 else
willybayot 0:4db361f2e6d5 223 {
willybayot 0:4db361f2e6d5 224 return MSD_ERROR;
willybayot 0:4db361f2e6d5 225 }
willybayot 0:4db361f2e6d5 226 }
willybayot 0:4db361f2e6d5 227
willybayot 0:4db361f2e6d5 228 /**
willybayot 0:4db361f2e6d5 229 * @brief Reads block(s) from a specified address in the SD card, in polling mode.
willybayot 0:4db361f2e6d5 230 * @param pData: Pointer to the buffer that will contain the data to transmit
willybayot 0:4db361f2e6d5 231 * @param ReadAddr: Address from where data is to be read
willybayot 0:4db361f2e6d5 232 * @param BlockSize: SD card data block size, that should be 512
willybayot 0:4db361f2e6d5 233 * @param NumOfBlocks: Number of SD blocks to read
willybayot 0:4db361f2e6d5 234 * @retval SD status
willybayot 0:4db361f2e6d5 235 */
willybayot 0:4db361f2e6d5 236 uint8_t BSP_SD_ReadBlocks(uint32_t* pData, uint32_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks)
willybayot 0:4db361f2e6d5 237 {
willybayot 0:4db361f2e6d5 238 uint32_t counter = 0, offset = 0;
willybayot 0:4db361f2e6d5 239 uint8_t rvalue = MSD_ERROR;
willybayot 0:4db361f2e6d5 240 uint8_t *ptr = (uint8_t*) pData;
willybayot 0:4db361f2e6d5 241
willybayot 0:4db361f2e6d5 242 /* Send CMD16 (SD_CMD_SET_BLOCKLEN) to set the size of the block and
willybayot 0:4db361f2e6d5 243 Check if the SD acknowledged the set block length command: R1 response (0x00: no errors) */
willybayot 0:4db361f2e6d5 244 if (SD_IO_WriteCmd(SD_CMD_SET_BLOCKLEN, BlockSize, 0xFF, SD_RESPONSE_NO_ERROR) != 0)
willybayot 0:4db361f2e6d5 245 {
willybayot 0:4db361f2e6d5 246 return MSD_ERROR;
willybayot 0:4db361f2e6d5 247 }
willybayot 0:4db361f2e6d5 248
willybayot 0:4db361f2e6d5 249 /* Data transfer */
willybayot 0:4db361f2e6d5 250 while (NumberOfBlocks--)
willybayot 0:4db361f2e6d5 251 {
willybayot 0:4db361f2e6d5 252 /* Send dummy byte: 8 Clock pulses of delay */
willybayot 0:4db361f2e6d5 253 SD_IO_WriteDummy();
willybayot 0:4db361f2e6d5 254
willybayot 0:4db361f2e6d5 255 /* Send CMD17 (SD_CMD_READ_SINGLE_BLOCK) to read one block */
willybayot 0:4db361f2e6d5 256 /* Check if the SD acknowledged the read block command: R1 response (0x00: no errors) */
willybayot 0:4db361f2e6d5 257 if (SD_IO_WriteCmd(SD_CMD_READ_SINGLE_BLOCK, ReadAddr + offset, 0xFF, SD_RESPONSE_NO_ERROR) != 0)
willybayot 0:4db361f2e6d5 258 {
willybayot 0:4db361f2e6d5 259 return MSD_ERROR;
willybayot 0:4db361f2e6d5 260 }
willybayot 0:4db361f2e6d5 261
willybayot 0:4db361f2e6d5 262 /* Now look for the data token to signify the start of the data */
willybayot 0:4db361f2e6d5 263 if (!SD_IO_WaitResponse(SD_START_DATA_SINGLE_BLOCK_READ))
willybayot 0:4db361f2e6d5 264 {
willybayot 0:4db361f2e6d5 265 /* Read the SD block data : read NumByteToRead data */
willybayot 0:4db361f2e6d5 266 for (counter = 0; counter < BlockSize; counter++)
willybayot 0:4db361f2e6d5 267 {
willybayot 0:4db361f2e6d5 268 /* Read the pointed data */
willybayot 0:4db361f2e6d5 269 *ptr = SD_IO_ReadByte();
willybayot 0:4db361f2e6d5 270 /* Point to the next location where the byte read will be saved */
willybayot 0:4db361f2e6d5 271 ptr++;
willybayot 0:4db361f2e6d5 272 }
willybayot 0:4db361f2e6d5 273 /* Set next read address*/
willybayot 0:4db361f2e6d5 274 offset += BlockSize;
willybayot 0:4db361f2e6d5 275 /* get CRC bytes (not really needed by us, but required by SD) */
willybayot 0:4db361f2e6d5 276 SD_IO_ReadByte();
willybayot 0:4db361f2e6d5 277 SD_IO_ReadByte();
willybayot 0:4db361f2e6d5 278 /* Set response value to success */
willybayot 0:4db361f2e6d5 279 rvalue = MSD_OK;
willybayot 0:4db361f2e6d5 280 }
willybayot 0:4db361f2e6d5 281 else
willybayot 0:4db361f2e6d5 282 {
willybayot 0:4db361f2e6d5 283 /* Set response value to failure */
willybayot 0:4db361f2e6d5 284 rvalue = MSD_ERROR;
willybayot 0:4db361f2e6d5 285 }
willybayot 0:4db361f2e6d5 286 }
willybayot 0:4db361f2e6d5 287
willybayot 0:4db361f2e6d5 288 /* Send dummy byte: 8 Clock pulses of delay */
willybayot 0:4db361f2e6d5 289 SD_IO_WriteDummy();
willybayot 0:4db361f2e6d5 290
willybayot 0:4db361f2e6d5 291 /* Return the reponse */
willybayot 0:4db361f2e6d5 292 return rvalue;
willybayot 0:4db361f2e6d5 293 }
willybayot 0:4db361f2e6d5 294
willybayot 0:4db361f2e6d5 295 /**
willybayot 0:4db361f2e6d5 296 * @brief Writes block(s) to a specified address in the SD card, in polling mode.
willybayot 0:4db361f2e6d5 297 * @param pData: Pointer to the buffer that will contain the data to transmit
willybayot 0:4db361f2e6d5 298 * @param WriteAddr: Address from where data is to be written
willybayot 0:4db361f2e6d5 299 * @param BlockSize: SD card data block size, that should be 512
willybayot 0:4db361f2e6d5 300 * @param NumOfBlocks: Number of SD blocks to write
willybayot 0:4db361f2e6d5 301 * @retval SD status
willybayot 0:4db361f2e6d5 302 */
willybayot 0:4db361f2e6d5 303 uint8_t BSP_SD_WriteBlocks(uint32_t* pData, uint32_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks)
willybayot 0:4db361f2e6d5 304 {
willybayot 0:4db361f2e6d5 305 uint32_t counter = 0, offset = 0;
willybayot 0:4db361f2e6d5 306 uint8_t rvalue = MSD_ERROR;
willybayot 0:4db361f2e6d5 307 uint8_t *ptr = (uint8_t*) pData;
willybayot 0:4db361f2e6d5 308
willybayot 0:4db361f2e6d5 309 /* Data transfer */
willybayot 0:4db361f2e6d5 310 while (NumberOfBlocks--)
willybayot 0:4db361f2e6d5 311 {
willybayot 0:4db361f2e6d5 312 /* Send CMD24 (SD_CMD_WRITE_SINGLE_BLOCK) to write blocks and
willybayot 0:4db361f2e6d5 313 Check if the SD acknowledged the write block command: R1 response (0x00: no errors) */
willybayot 0:4db361f2e6d5 314 if (SD_IO_WriteCmd(SD_CMD_WRITE_SINGLE_BLOCK, WriteAddr + offset, 0xFF, SD_RESPONSE_NO_ERROR))
willybayot 0:4db361f2e6d5 315 {
willybayot 0:4db361f2e6d5 316 return MSD_ERROR;
willybayot 0:4db361f2e6d5 317 }
willybayot 0:4db361f2e6d5 318
willybayot 0:4db361f2e6d5 319 /* Send dummy byte */
willybayot 0:4db361f2e6d5 320 SD_IO_WriteByte(SD_DUMMY_BYTE);
willybayot 0:4db361f2e6d5 321
willybayot 0:4db361f2e6d5 322 /* Send the data token to signify the start of the data */
willybayot 0:4db361f2e6d5 323 SD_IO_WriteByte(SD_START_DATA_SINGLE_BLOCK_WRITE);
willybayot 0:4db361f2e6d5 324
willybayot 0:4db361f2e6d5 325 /* Write the block data to SD : write count data by block */
willybayot 0:4db361f2e6d5 326 for (counter = 0; counter < BlockSize; counter++)
willybayot 0:4db361f2e6d5 327 {
willybayot 0:4db361f2e6d5 328 /* Send the pointed byte */
willybayot 0:4db361f2e6d5 329 SD_IO_WriteByte(*ptr);
willybayot 0:4db361f2e6d5 330
willybayot 0:4db361f2e6d5 331 /* Point to the next location where the byte read will be saved */
willybayot 0:4db361f2e6d5 332 ptr++;
willybayot 0:4db361f2e6d5 333 }
willybayot 0:4db361f2e6d5 334
willybayot 0:4db361f2e6d5 335 /* Set next write address */
willybayot 0:4db361f2e6d5 336 offset += BlockSize;
willybayot 0:4db361f2e6d5 337
willybayot 0:4db361f2e6d5 338 /* Put CRC bytes (not really needed by us, but required by SD) */
willybayot 0:4db361f2e6d5 339 SD_IO_ReadByte();
willybayot 0:4db361f2e6d5 340 SD_IO_ReadByte();
willybayot 0:4db361f2e6d5 341
willybayot 0:4db361f2e6d5 342 /* Read data response */
willybayot 0:4db361f2e6d5 343 if (SD_GetDataResponse() == SD_DATA_OK)
willybayot 0:4db361f2e6d5 344 {
willybayot 0:4db361f2e6d5 345 /* Set response value to success */
willybayot 0:4db361f2e6d5 346 rvalue = MSD_OK;
willybayot 0:4db361f2e6d5 347 }
willybayot 0:4db361f2e6d5 348 else
willybayot 0:4db361f2e6d5 349 {
willybayot 0:4db361f2e6d5 350 /* Set response value to failure */
willybayot 0:4db361f2e6d5 351 rvalue = MSD_ERROR;
willybayot 0:4db361f2e6d5 352 }
willybayot 0:4db361f2e6d5 353 }
willybayot 0:4db361f2e6d5 354
willybayot 0:4db361f2e6d5 355 /* Send dummy byte: 8 Clock pulses of delay */
willybayot 0:4db361f2e6d5 356 SD_IO_WriteDummy();
willybayot 0:4db361f2e6d5 357
willybayot 0:4db361f2e6d5 358 /* Return the reponse */
willybayot 0:4db361f2e6d5 359 return rvalue;
willybayot 0:4db361f2e6d5 360 }
willybayot 0:4db361f2e6d5 361
willybayot 0:4db361f2e6d5 362 /**
willybayot 0:4db361f2e6d5 363 * @brief Reads the SD card SCD register.
willybayot 0:4db361f2e6d5 364 * Reading the contents of the CSD register in SPI mode is a simple
willybayot 0:4db361f2e6d5 365 * read-block transaction.
willybayot 0:4db361f2e6d5 366 * @param Csd: pointer on an SCD register structure
willybayot 0:4db361f2e6d5 367 * @retval SD status
willybayot 0:4db361f2e6d5 368 */
willybayot 0:4db361f2e6d5 369 static uint8_t SD_GetCSDRegister(SD_CSD* Csd)
willybayot 0:4db361f2e6d5 370 {
willybayot 0:4db361f2e6d5 371 uint32_t counter = 0;
willybayot 0:4db361f2e6d5 372 uint8_t rvalue = SD_RESPONSE_FAILURE;
willybayot 0:4db361f2e6d5 373 uint8_t CSD_Tab[16];
willybayot 0:4db361f2e6d5 374
willybayot 0:4db361f2e6d5 375 /* Send CMD9 (CSD register) or CMD10(CSD register) and Wait for response in the R1 format (0x00 is no errors) */
willybayot 0:4db361f2e6d5 376 if (!SD_IO_WriteCmd(SD_CMD_SEND_CSD, 0, 0xFF, SD_RESPONSE_NO_ERROR))
willybayot 0:4db361f2e6d5 377 {
willybayot 0:4db361f2e6d5 378 if (!SD_IO_WaitResponse(SD_START_DATA_SINGLE_BLOCK_READ))
willybayot 0:4db361f2e6d5 379 {
willybayot 0:4db361f2e6d5 380 for (counter = 0; counter < 16; counter++)
willybayot 0:4db361f2e6d5 381 {
willybayot 0:4db361f2e6d5 382 /* Store CSD register value on CSD_Tab */
willybayot 0:4db361f2e6d5 383 CSD_Tab[counter] = SD_IO_ReadByte();
willybayot 0:4db361f2e6d5 384 }
willybayot 0:4db361f2e6d5 385
willybayot 0:4db361f2e6d5 386 /* Get CRC bytes (not really needed by us, but required by SD) */
willybayot 0:4db361f2e6d5 387 SD_IO_WriteByte(SD_DUMMY_BYTE);
willybayot 0:4db361f2e6d5 388 SD_IO_WriteByte(SD_DUMMY_BYTE);
willybayot 0:4db361f2e6d5 389
willybayot 0:4db361f2e6d5 390 /* Set response value to success */
willybayot 0:4db361f2e6d5 391 rvalue = SD_RESPONSE_NO_ERROR;
willybayot 0:4db361f2e6d5 392 }
willybayot 0:4db361f2e6d5 393 }
willybayot 0:4db361f2e6d5 394 /* Send dummy byte: 8 Clock pulses of delay */
willybayot 0:4db361f2e6d5 395 SD_IO_WriteDummy();
willybayot 0:4db361f2e6d5 396
willybayot 0:4db361f2e6d5 397 if(rvalue == SD_RESPONSE_NO_ERROR)
willybayot 0:4db361f2e6d5 398 {
willybayot 0:4db361f2e6d5 399 /* Byte 0 */
willybayot 0:4db361f2e6d5 400 Csd->CSDStruct = (CSD_Tab[0] & 0xC0) >> 6;
willybayot 0:4db361f2e6d5 401 Csd->SysSpecVersion = (CSD_Tab[0] & 0x3C) >> 2;
willybayot 0:4db361f2e6d5 402 Csd->Reserved1 = CSD_Tab[0] & 0x03;
willybayot 0:4db361f2e6d5 403
willybayot 0:4db361f2e6d5 404 /* Byte 1 */
willybayot 0:4db361f2e6d5 405 Csd->TAAC = CSD_Tab[1];
willybayot 0:4db361f2e6d5 406
willybayot 0:4db361f2e6d5 407 /* Byte 2 */
willybayot 0:4db361f2e6d5 408 Csd->NSAC = CSD_Tab[2];
willybayot 0:4db361f2e6d5 409
willybayot 0:4db361f2e6d5 410 /* Byte 3 */
willybayot 0:4db361f2e6d5 411 Csd->MaxBusClkFrec = CSD_Tab[3];
willybayot 0:4db361f2e6d5 412
willybayot 0:4db361f2e6d5 413 /* Byte 4 */
willybayot 0:4db361f2e6d5 414 Csd->CardComdClasses = CSD_Tab[4] << 4;
willybayot 0:4db361f2e6d5 415
willybayot 0:4db361f2e6d5 416 /* Byte 5 */
willybayot 0:4db361f2e6d5 417 Csd->CardComdClasses |= (CSD_Tab[5] & 0xF0) >> 4;
willybayot 0:4db361f2e6d5 418 Csd->RdBlockLen = CSD_Tab[5] & 0x0F;
willybayot 0:4db361f2e6d5 419
willybayot 0:4db361f2e6d5 420 /* Byte 6 */
willybayot 0:4db361f2e6d5 421 Csd->PartBlockRead = (CSD_Tab[6] & 0x80) >> 7;
willybayot 0:4db361f2e6d5 422 Csd->WrBlockMisalign = (CSD_Tab[6] & 0x40) >> 6;
willybayot 0:4db361f2e6d5 423 Csd->RdBlockMisalign = (CSD_Tab[6] & 0x20) >> 5;
willybayot 0:4db361f2e6d5 424 Csd->DSRImpl = (CSD_Tab[6] & 0x10) >> 4;
willybayot 0:4db361f2e6d5 425 Csd->Reserved2 = 0; /*!< Reserved */
willybayot 0:4db361f2e6d5 426
willybayot 0:4db361f2e6d5 427 Csd->DeviceSize = (CSD_Tab[6] & 0x03) << 10;
willybayot 0:4db361f2e6d5 428
willybayot 0:4db361f2e6d5 429 /* Byte 7 */
willybayot 0:4db361f2e6d5 430 Csd->DeviceSize |= (CSD_Tab[7]) << 2;
willybayot 0:4db361f2e6d5 431
willybayot 0:4db361f2e6d5 432 /* Byte 8 */
willybayot 0:4db361f2e6d5 433 Csd->DeviceSize |= (CSD_Tab[8] & 0xC0) >> 6;
willybayot 0:4db361f2e6d5 434
willybayot 0:4db361f2e6d5 435 Csd->MaxRdCurrentVDDMin = (CSD_Tab[8] & 0x38) >> 3;
willybayot 0:4db361f2e6d5 436 Csd->MaxRdCurrentVDDMax = (CSD_Tab[8] & 0x07);
willybayot 0:4db361f2e6d5 437
willybayot 0:4db361f2e6d5 438 /* Byte 9 */
willybayot 0:4db361f2e6d5 439 Csd->MaxWrCurrentVDDMin = (CSD_Tab[9] & 0xE0) >> 5;
willybayot 0:4db361f2e6d5 440 Csd->MaxWrCurrentVDDMax = (CSD_Tab[9] & 0x1C) >> 2;
willybayot 0:4db361f2e6d5 441 Csd->DeviceSizeMul = (CSD_Tab[9] & 0x03) << 1;
willybayot 0:4db361f2e6d5 442 /* Byte 10 */
willybayot 0:4db361f2e6d5 443 Csd->DeviceSizeMul |= (CSD_Tab[10] & 0x80) >> 7;
willybayot 0:4db361f2e6d5 444
willybayot 0:4db361f2e6d5 445 Csd->EraseGrSize = (CSD_Tab[10] & 0x40) >> 6;
willybayot 0:4db361f2e6d5 446 Csd->EraseGrMul = (CSD_Tab[10] & 0x3F) << 1;
willybayot 0:4db361f2e6d5 447
willybayot 0:4db361f2e6d5 448 /* Byte 11 */
willybayot 0:4db361f2e6d5 449 Csd->EraseGrMul |= (CSD_Tab[11] & 0x80) >> 7;
willybayot 0:4db361f2e6d5 450 Csd->WrProtectGrSize = (CSD_Tab[11] & 0x7F);
willybayot 0:4db361f2e6d5 451
willybayot 0:4db361f2e6d5 452 /* Byte 12 */
willybayot 0:4db361f2e6d5 453 Csd->WrProtectGrEnable = (CSD_Tab[12] & 0x80) >> 7;
willybayot 0:4db361f2e6d5 454 Csd->ManDeflECC = (CSD_Tab[12] & 0x60) >> 5;
willybayot 0:4db361f2e6d5 455 Csd->WrSpeedFact = (CSD_Tab[12] & 0x1C) >> 2;
willybayot 0:4db361f2e6d5 456 Csd->MaxWrBlockLen = (CSD_Tab[12] & 0x03) << 2;
willybayot 0:4db361f2e6d5 457
willybayot 0:4db361f2e6d5 458 /* Byte 13 */
willybayot 0:4db361f2e6d5 459 Csd->MaxWrBlockLen |= (CSD_Tab[13] & 0xC0) >> 6;
willybayot 0:4db361f2e6d5 460 Csd->WriteBlockPaPartial = (CSD_Tab[13] & 0x20) >> 5;
willybayot 0:4db361f2e6d5 461 Csd->Reserved3 = 0;
willybayot 0:4db361f2e6d5 462 Csd->ContentProtectAppli = (CSD_Tab[13] & 0x01);
willybayot 0:4db361f2e6d5 463
willybayot 0:4db361f2e6d5 464 /* Byte 14 */
willybayot 0:4db361f2e6d5 465 Csd->FileFormatGrouop = (CSD_Tab[14] & 0x80) >> 7;
willybayot 0:4db361f2e6d5 466 Csd->CopyFlag = (CSD_Tab[14] & 0x40) >> 6;
willybayot 0:4db361f2e6d5 467 Csd->PermWrProtect = (CSD_Tab[14] & 0x20) >> 5;
willybayot 0:4db361f2e6d5 468 Csd->TempWrProtect = (CSD_Tab[14] & 0x10) >> 4;
willybayot 0:4db361f2e6d5 469 Csd->FileFormat = (CSD_Tab[14] & 0x0C) >> 2;
willybayot 0:4db361f2e6d5 470 Csd->ECC = (CSD_Tab[14] & 0x03);
willybayot 0:4db361f2e6d5 471
willybayot 0:4db361f2e6d5 472 /* Byte 15 */
willybayot 0:4db361f2e6d5 473 Csd->CSD_CRC = (CSD_Tab[15] & 0xFE) >> 1;
willybayot 0:4db361f2e6d5 474 Csd->Reserved4 = 1;
willybayot 0:4db361f2e6d5 475 }
willybayot 0:4db361f2e6d5 476
willybayot 0:4db361f2e6d5 477 /* Return the reponse */
willybayot 0:4db361f2e6d5 478 return rvalue;
willybayot 0:4db361f2e6d5 479 }
willybayot 0:4db361f2e6d5 480
willybayot 0:4db361f2e6d5 481 /**
willybayot 0:4db361f2e6d5 482 * @brief Reads the SD card CID register.
willybayot 0:4db361f2e6d5 483 * Reading the contents of the CID register in SPI mode is a simple
willybayot 0:4db361f2e6d5 484 * read-block transaction.
willybayot 0:4db361f2e6d5 485 * @param Cid: pointer on an CID register structure
willybayot 0:4db361f2e6d5 486 * @retval SD status
willybayot 0:4db361f2e6d5 487 */
willybayot 0:4db361f2e6d5 488 static uint8_t SD_GetCIDRegister(SD_CID* Cid)
willybayot 0:4db361f2e6d5 489 {
willybayot 0:4db361f2e6d5 490 uint32_t counter = 0;
willybayot 0:4db361f2e6d5 491 uint8_t rvalue = SD_RESPONSE_FAILURE;
willybayot 0:4db361f2e6d5 492 uint8_t CID_Tab[16];
willybayot 0:4db361f2e6d5 493
willybayot 0:4db361f2e6d5 494 /* Send CMD10 (CID register) and Wait for response in the R1 format (0x00 is no errors) */
willybayot 0:4db361f2e6d5 495 if (!SD_IO_WriteCmd(SD_CMD_SEND_CID, 0, 0xFF, SD_RESPONSE_NO_ERROR))
willybayot 0:4db361f2e6d5 496 {
willybayot 0:4db361f2e6d5 497 if (!SD_IO_WaitResponse(SD_START_DATA_SINGLE_BLOCK_READ))
willybayot 0:4db361f2e6d5 498 {
willybayot 0:4db361f2e6d5 499 /* Store CID register value on CID_Tab */
willybayot 0:4db361f2e6d5 500 for (counter = 0; counter < 16; counter++)
willybayot 0:4db361f2e6d5 501 {
willybayot 0:4db361f2e6d5 502 CID_Tab[counter] = SD_IO_ReadByte();
willybayot 0:4db361f2e6d5 503 }
willybayot 0:4db361f2e6d5 504
willybayot 0:4db361f2e6d5 505 /* Get CRC bytes (not really needed by us, but required by SD) */
willybayot 0:4db361f2e6d5 506 SD_IO_WriteByte(SD_DUMMY_BYTE);
willybayot 0:4db361f2e6d5 507 SD_IO_WriteByte(SD_DUMMY_BYTE);
willybayot 0:4db361f2e6d5 508
willybayot 0:4db361f2e6d5 509 /* Set response value to success */
willybayot 0:4db361f2e6d5 510 rvalue = SD_RESPONSE_NO_ERROR;
willybayot 0:4db361f2e6d5 511 }
willybayot 0:4db361f2e6d5 512 }
willybayot 0:4db361f2e6d5 513
willybayot 0:4db361f2e6d5 514 /* Send dummy byte: 8 Clock pulses of delay */
willybayot 0:4db361f2e6d5 515 SD_IO_WriteDummy();
willybayot 0:4db361f2e6d5 516
willybayot 0:4db361f2e6d5 517 if(rvalue == SD_RESPONSE_NO_ERROR)
willybayot 0:4db361f2e6d5 518 {
willybayot 0:4db361f2e6d5 519 /* Byte 0 */
willybayot 0:4db361f2e6d5 520 Cid->ManufacturerID = CID_Tab[0];
willybayot 0:4db361f2e6d5 521
willybayot 0:4db361f2e6d5 522 /* Byte 1 */
willybayot 0:4db361f2e6d5 523 Cid->OEM_AppliID = CID_Tab[1] << 8;
willybayot 0:4db361f2e6d5 524
willybayot 0:4db361f2e6d5 525 /* Byte 2 */
willybayot 0:4db361f2e6d5 526 Cid->OEM_AppliID |= CID_Tab[2];
willybayot 0:4db361f2e6d5 527
willybayot 0:4db361f2e6d5 528 /* Byte 3 */
willybayot 0:4db361f2e6d5 529 Cid->ProdName1 = CID_Tab[3] << 24;
willybayot 0:4db361f2e6d5 530
willybayot 0:4db361f2e6d5 531 /* Byte 4 */
willybayot 0:4db361f2e6d5 532 Cid->ProdName1 |= CID_Tab[4] << 16;
willybayot 0:4db361f2e6d5 533
willybayot 0:4db361f2e6d5 534 /* Byte 5 */
willybayot 0:4db361f2e6d5 535 Cid->ProdName1 |= CID_Tab[5] << 8;
willybayot 0:4db361f2e6d5 536
willybayot 0:4db361f2e6d5 537 /* Byte 6 */
willybayot 0:4db361f2e6d5 538 Cid->ProdName1 |= CID_Tab[6];
willybayot 0:4db361f2e6d5 539
willybayot 0:4db361f2e6d5 540 /* Byte 7 */
willybayot 0:4db361f2e6d5 541 Cid->ProdName2 = CID_Tab[7];
willybayot 0:4db361f2e6d5 542
willybayot 0:4db361f2e6d5 543 /* Byte 8 */
willybayot 0:4db361f2e6d5 544 Cid->ProdRev = CID_Tab[8];
willybayot 0:4db361f2e6d5 545
willybayot 0:4db361f2e6d5 546 /* Byte 9 */
willybayot 0:4db361f2e6d5 547 Cid->ProdSN = CID_Tab[9] << 24;
willybayot 0:4db361f2e6d5 548
willybayot 0:4db361f2e6d5 549 /* Byte 10 */
willybayot 0:4db361f2e6d5 550 Cid->ProdSN |= CID_Tab[10] << 16;
willybayot 0:4db361f2e6d5 551
willybayot 0:4db361f2e6d5 552 /* Byte 11 */
willybayot 0:4db361f2e6d5 553 Cid->ProdSN |= CID_Tab[11] << 8;
willybayot 0:4db361f2e6d5 554
willybayot 0:4db361f2e6d5 555 /* Byte 12 */
willybayot 0:4db361f2e6d5 556 Cid->ProdSN |= CID_Tab[12];
willybayot 0:4db361f2e6d5 557
willybayot 0:4db361f2e6d5 558 /* Byte 13 */
willybayot 0:4db361f2e6d5 559 Cid->Reserved1 |= (CID_Tab[13] & 0xF0) >> 4;
willybayot 0:4db361f2e6d5 560 Cid->ManufactDate = (CID_Tab[13] & 0x0F) << 8;
willybayot 0:4db361f2e6d5 561
willybayot 0:4db361f2e6d5 562 /* Byte 14 */
willybayot 0:4db361f2e6d5 563 Cid->ManufactDate |= CID_Tab[14];
willybayot 0:4db361f2e6d5 564
willybayot 0:4db361f2e6d5 565 /* Byte 15 */
willybayot 0:4db361f2e6d5 566 Cid->CID_CRC = (CID_Tab[15] & 0xFE) >> 1;
willybayot 0:4db361f2e6d5 567 Cid->Reserved2 = 1;
willybayot 0:4db361f2e6d5 568 }
willybayot 0:4db361f2e6d5 569 /* Return the reponse */
willybayot 0:4db361f2e6d5 570 return rvalue;
willybayot 0:4db361f2e6d5 571 }
willybayot 0:4db361f2e6d5 572
willybayot 0:4db361f2e6d5 573 /**
willybayot 0:4db361f2e6d5 574 * @brief Sends 5 bytes command to the SD card and get response
willybayot 0:4db361f2e6d5 575 * @param Cmd: The user expected command to send to SD card.
willybayot 0:4db361f2e6d5 576 * @param Arg: The command argument.
willybayot 0:4db361f2e6d5 577 * @param Crc: The CRC.
willybayot 0:4db361f2e6d5 578 * @param Response: Expected response from the SD card
willybayot 0:4db361f2e6d5 579 * @retval SD status
willybayot 0:4db361f2e6d5 580 */
willybayot 0:4db361f2e6d5 581 static uint8_t SD_SendCmd(uint8_t Cmd, uint32_t Arg, uint8_t Crc, uint8_t Response)
willybayot 0:4db361f2e6d5 582 {
willybayot 0:4db361f2e6d5 583 uint8_t status;
willybayot 0:4db361f2e6d5 584
willybayot 0:4db361f2e6d5 585 status = (uint8_t)SD_IO_WriteCmd(Cmd, Arg, Crc, Response);
willybayot 0:4db361f2e6d5 586
willybayot 0:4db361f2e6d5 587 /* Send Dummy Byte */
willybayot 0:4db361f2e6d5 588 SD_IO_WriteDummy();
willybayot 0:4db361f2e6d5 589
willybayot 0:4db361f2e6d5 590 return status;
willybayot 0:4db361f2e6d5 591 }
willybayot 0:4db361f2e6d5 592
willybayot 0:4db361f2e6d5 593 /**
willybayot 0:4db361f2e6d5 594 * @brief Gets the SD card data response.
willybayot 0:4db361f2e6d5 595 * @param None
willybayot 0:4db361f2e6d5 596 * @retval The SD status: Read data response xxx0<status>1
willybayot 0:4db361f2e6d5 597 * - status 010: Data accecpted
willybayot 0:4db361f2e6d5 598 * - status 101: Data rejected due to a crc error
willybayot 0:4db361f2e6d5 599 * - status 110: Data rejected due to a Write error.
willybayot 0:4db361f2e6d5 600 * - status 111: Data rejected due to other error.
willybayot 0:4db361f2e6d5 601 */
willybayot 0:4db361f2e6d5 602 static uint8_t SD_GetDataResponse(void)
willybayot 0:4db361f2e6d5 603 {
willybayot 0:4db361f2e6d5 604 uint32_t counter = 0;
willybayot 0:4db361f2e6d5 605 uint8_t response = SD_RESPONSE_FAILURE;
willybayot 0:4db361f2e6d5 606 uint8_t rvalue = SD_DATA_OTHER_ERROR;
willybayot 0:4db361f2e6d5 607
willybayot 0:4db361f2e6d5 608 while (counter <= 64)
willybayot 0:4db361f2e6d5 609 {
willybayot 0:4db361f2e6d5 610 /* Read response */
willybayot 0:4db361f2e6d5 611 response = SD_IO_ReadByte();
willybayot 0:4db361f2e6d5 612
willybayot 0:4db361f2e6d5 613 /* Mask unused bits */
willybayot 0:4db361f2e6d5 614 response &= 0x1F;
willybayot 0:4db361f2e6d5 615 switch (response)
willybayot 0:4db361f2e6d5 616 {
willybayot 0:4db361f2e6d5 617 case SD_DATA_OK:
willybayot 0:4db361f2e6d5 618 {
willybayot 0:4db361f2e6d5 619 rvalue = SD_DATA_OK;
willybayot 0:4db361f2e6d5 620 break;
willybayot 0:4db361f2e6d5 621 }
willybayot 0:4db361f2e6d5 622 case SD_DATA_CRC_ERROR:
willybayot 0:4db361f2e6d5 623 return SD_DATA_CRC_ERROR;
willybayot 0:4db361f2e6d5 624 case SD_DATA_WRITE_ERROR:
willybayot 0:4db361f2e6d5 625 return SD_DATA_WRITE_ERROR;
willybayot 0:4db361f2e6d5 626 default:
willybayot 0:4db361f2e6d5 627 {
willybayot 0:4db361f2e6d5 628 rvalue = SD_DATA_OTHER_ERROR;
willybayot 0:4db361f2e6d5 629 break;
willybayot 0:4db361f2e6d5 630 }
willybayot 0:4db361f2e6d5 631 }
willybayot 0:4db361f2e6d5 632 /* Exit loop in case of data ok */
willybayot 0:4db361f2e6d5 633 if (rvalue == SD_DATA_OK)
willybayot 0:4db361f2e6d5 634 break;
willybayot 0:4db361f2e6d5 635
willybayot 0:4db361f2e6d5 636 /* Increment loop counter */
willybayot 0:4db361f2e6d5 637 counter++;
willybayot 0:4db361f2e6d5 638 }
willybayot 0:4db361f2e6d5 639
willybayot 0:4db361f2e6d5 640 /* Wait null data */
willybayot 0:4db361f2e6d5 641 while (SD_IO_ReadByte() == 0);
willybayot 0:4db361f2e6d5 642
willybayot 0:4db361f2e6d5 643 /* Return response */
willybayot 0:4db361f2e6d5 644 return response;
willybayot 0:4db361f2e6d5 645 }
willybayot 0:4db361f2e6d5 646
willybayot 0:4db361f2e6d5 647 /**
willybayot 0:4db361f2e6d5 648 * @brief Returns the SD status.
willybayot 0:4db361f2e6d5 649 * @param None
willybayot 0:4db361f2e6d5 650 * @retval The SD status.
willybayot 0:4db361f2e6d5 651 */
willybayot 0:4db361f2e6d5 652 uint8_t BSP_SD_GetStatus(void)
willybayot 0:4db361f2e6d5 653 {
willybayot 0:4db361f2e6d5 654 uint16_t status = 0;
willybayot 0:4db361f2e6d5 655
willybayot 0:4db361f2e6d5 656 /* Send CMD13 (SD_SEND_STATUS) to get SD status */
willybayot 0:4db361f2e6d5 657 SD_SendCmd(SD_CMD_SEND_STATUS, 0, 0xFF, SD_NO_RESPONSE_EXPECTED);
willybayot 0:4db361f2e6d5 658
willybayot 0:4db361f2e6d5 659 status = SD_IO_ReadByte();
willybayot 0:4db361f2e6d5 660 status |= (uint16_t)(SD_IO_ReadByte() << 8);
willybayot 0:4db361f2e6d5 661
willybayot 0:4db361f2e6d5 662 /* Send Dummy Byte */
willybayot 0:4db361f2e6d5 663 SD_IO_WriteDummy();
willybayot 0:4db361f2e6d5 664
willybayot 0:4db361f2e6d5 665 /* Find SD status according to card state */
willybayot 0:4db361f2e6d5 666 if (status == SD_RESPONSE_NO_ERROR)
willybayot 0:4db361f2e6d5 667 {
willybayot 0:4db361f2e6d5 668 return MSD_OK;
willybayot 0:4db361f2e6d5 669 }
willybayot 0:4db361f2e6d5 670 else
willybayot 0:4db361f2e6d5 671 {
willybayot 0:4db361f2e6d5 672 return MSD_ERROR;
willybayot 0:4db361f2e6d5 673 }
willybayot 0:4db361f2e6d5 674 }
willybayot 0:4db361f2e6d5 675
willybayot 0:4db361f2e6d5 676 /**
willybayot 0:4db361f2e6d5 677 * @brief Put the SD in Idle state.
willybayot 0:4db361f2e6d5 678 * @param None
willybayot 0:4db361f2e6d5 679 * @retval SD status
willybayot 0:4db361f2e6d5 680 */
willybayot 0:4db361f2e6d5 681 static uint8_t SD_GoIdleState(void)
willybayot 0:4db361f2e6d5 682 {
willybayot 0:4db361f2e6d5 683 /* Send CMD0 (SD_CMD_GO_IDLE_STATE) to put SD in SPI mode and
willybayot 0:4db361f2e6d5 684 wait for In Idle State Response (R1 Format) equal to 0x01 */
willybayot 0:4db361f2e6d5 685 if (SD_SendCmd(SD_CMD_GO_IDLE_STATE, 0, 0x95, SD_IN_IDLE_STATE) != SD_RESPONSE_NO_ERROR)
willybayot 0:4db361f2e6d5 686 {
willybayot 0:4db361f2e6d5 687 /* No Idle State Response: return response failue */
willybayot 0:4db361f2e6d5 688 return SD_RESPONSE_FAILURE;
willybayot 0:4db361f2e6d5 689 }
willybayot 0:4db361f2e6d5 690
willybayot 0:4db361f2e6d5 691 /*----------Activates the card initialization process-----------*/
willybayot 0:4db361f2e6d5 692 /* Send CMD1 (Activates the card process) until response equal to 0x0 and
willybayot 0:4db361f2e6d5 693 Wait for no error Response (R1 Format) equal to 0x00 */
willybayot 0:4db361f2e6d5 694 while (SD_SendCmd(SD_CMD_SEND_OP_COND, 0, 0xFF, SD_RESPONSE_NO_ERROR) != SD_RESPONSE_NO_ERROR);
willybayot 0:4db361f2e6d5 695
willybayot 0:4db361f2e6d5 696 return SD_RESPONSE_NO_ERROR;
willybayot 0:4db361f2e6d5 697 }
willybayot 0:4db361f2e6d5 698
willybayot 0:4db361f2e6d5 699 /**
willybayot 0:4db361f2e6d5 700 * @brief Erases the specified memory area of the given SD card.
willybayot 0:4db361f2e6d5 701 * @param StartAddr: Start byte address
willybayot 0:4db361f2e6d5 702 * @param EndAddr: End byte address
willybayot 0:4db361f2e6d5 703 * @retval SD status
willybayot 0:4db361f2e6d5 704 */
willybayot 0:4db361f2e6d5 705 uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr)
willybayot 0:4db361f2e6d5 706 {
willybayot 0:4db361f2e6d5 707 uint8_t rvalue = SD_RESPONSE_FAILURE;
willybayot 0:4db361f2e6d5 708
willybayot 0:4db361f2e6d5 709 /* Send CMD32 (Erase group start) and check if the SD acknowledged the erase command: R1 response (0x00: no errors) */
willybayot 0:4db361f2e6d5 710 if (!SD_SendCmd(SD_CMD_SD_ERASE_GRP_START, StartAddr, 0xFF, SD_RESPONSE_NO_ERROR))
willybayot 0:4db361f2e6d5 711 {
willybayot 0:4db361f2e6d5 712 /* Send CMD33 (Erase group end) and Check if the SD acknowledged the erase command: R1 response (0x00: no errors) */
willybayot 0:4db361f2e6d5 713 if (!SD_SendCmd(SD_CMD_SD_ERASE_GRP_END, EndAddr, 0xFF, SD_RESPONSE_NO_ERROR))
willybayot 0:4db361f2e6d5 714 {
willybayot 0:4db361f2e6d5 715 /* Send CMD38 (Erase) and Check if the SD acknowledged the erase command: R1 response (0x00: no errors) */
willybayot 0:4db361f2e6d5 716 if (!SD_SendCmd(SD_CMD_ERASE, 0, 0xFF, SD_RESPONSE_NO_ERROR))
willybayot 0:4db361f2e6d5 717 {
willybayot 0:4db361f2e6d5 718 /* Verify that SD card is ready to use after the specific command ERASE */
willybayot 0:4db361f2e6d5 719 rvalue = (uint8_t)SD_IO_WaitResponse(SD_RESPONSE_NO_ERROR);
willybayot 0:4db361f2e6d5 720 }
willybayot 0:4db361f2e6d5 721 }
willybayot 0:4db361f2e6d5 722 }
willybayot 0:4db361f2e6d5 723
willybayot 0:4db361f2e6d5 724 /* Return the reponse */
willybayot 0:4db361f2e6d5 725 if (rvalue == SD_RESPONSE_NO_ERROR)
willybayot 0:4db361f2e6d5 726 {
willybayot 0:4db361f2e6d5 727 return MSD_OK;
willybayot 0:4db361f2e6d5 728 }
willybayot 0:4db361f2e6d5 729 else
willybayot 0:4db361f2e6d5 730 {
willybayot 0:4db361f2e6d5 731 return MSD_ERROR;
willybayot 0:4db361f2e6d5 732 }
willybayot 0:4db361f2e6d5 733 }
willybayot 0:4db361f2e6d5 734
willybayot 0:4db361f2e6d5 735 /**
willybayot 0:4db361f2e6d5 736 * @}
willybayot 0:4db361f2e6d5 737 */
willybayot 0:4db361f2e6d5 738
willybayot 0:4db361f2e6d5 739 /**
willybayot 0:4db361f2e6d5 740 * @}
willybayot 0:4db361f2e6d5 741 */
willybayot 0:4db361f2e6d5 742
willybayot 0:4db361f2e6d5 743 /**
willybayot 0:4db361f2e6d5 744 * @}
willybayot 0:4db361f2e6d5 745 */
willybayot 0:4db361f2e6d5 746
willybayot 0:4db361f2e6d5 747 /**
willybayot 0:4db361f2e6d5 748 * @}
willybayot 0:4db361f2e6d5 749 */
willybayot 0:4db361f2e6d5 750
willybayot 0:4db361f2e6d5 751 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/