2 ******************************************************************************
3 * @file bsp_driver_sd.c (based on stm324x9i_eval_sd.c)
4 * @brief This file includes a generic uSD card driver.
5 ******************************************************************************
7 * COPYRIGHT(c) 2016 STMicroelectronics
9 * Redistribution and use in source and binary forms, with or without modification,
10 * are permitted provided that the following conditions are met:
11 * 1. Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 * 3. Neither the name of STMicroelectronics nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 ******************************************************************************
34 /* USER CODE BEGIN 0 */
35 /* Includes ------------------------------------------------------------------*/
36 #include "bsp_driver_sd.h"
40 /* Extern variables ---------------------------------------------------------*/
42 extern SD_HandleTypeDef hsd;
44 static uint8_t HighSpeedSwitch();
47 * @brief Initializes the SD card device.
51 uint8_t BSP_SD_Init(void)
53 uint8_t SD_state = MSD_OK;
54 /* Check if the SD card is plugged in the slot */
55 if (BSP_SD_IsDetected() != SD_PRESENT)
60 // Reset defaults. High-speed mode can be incorrectly set if user removed then
61 // inserted a new SD card and we re-run initialisation.
62 hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
63 hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
65 SD_state = HAL_SD_Init(&hsd);
67 if (SD_state == HAL_OK)
69 if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
75 // Save the wide mode setting for when we call SDIO_Init again
76 // for high speed mode.
77 hsd.Init.BusWide = SDIO_BUS_WIDE_4B;
80 // Clock bypass mode is broken on STM32F205
82 if (hsd.SdCard.CardType == CARD_SDHC_SDXC)
93 static uint8_t HighSpeedSwitch()
95 uint8_t SD_state = MSD_OK;
97 // Prepare to read 64 bytes status data
98 SDIO_DataInitTypeDef config;
99 config.DataTimeOut = SDMMC_DATATIMEOUT;
100 config.DataLength = 64;
101 config.DataBlockSize = SDIO_DATABLOCK_SIZE_64B;
102 config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
103 config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
104 config.DPSM = SDIO_DPSM_ENABLE;
105 (void)SDIO_ConfigData(hsd.Instance, &config);
107 // High speed switch.
108 // SDR25 (25MB/s) mode 0x80FFFF01
109 // Which is the max without going to 1.8v
110 uint32_t errorstate = SDMMC_CmdSwitch(hsd.Instance, 0x80FFFFF1);
112 // Now we read some status data
114 if (errorstate == HAL_SD_ERROR_NONE)
116 uint32_t statusByteCount = 0;
117 while(!__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND))
119 if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXFIFOHF) && statusByteCount < 64)
121 for ( uint32_t i = 0; i < 8; i++, statusByteCount += 4)
123 SDIO_ReadFIFO(hsd.Instance);
128 if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_DTIMEOUT))
130 __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_DTIMEOUT);
131 SD_state = MSD_ERROR;
133 else if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_DCRCFAIL))
135 __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_DCRCFAIL);
136 SD_state = MSD_ERROR;
138 else if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXOVERR))
140 __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_RXOVERR);
141 SD_state = MSD_ERROR;
145 // Read remaining data, could be the CRC bytes.
146 uint32_t count = SD_DATATIMEOUT;
147 while ((__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXDAVL)) && (count > 0))
149 SDIO_ReadFIFO(hsd.Instance);
153 /* Clear all the static flags */
154 __HAL_SD_CLEAR_FLAG(&hsd, SDIO_STATIC_FLAGS);
156 // After 8 "SD" clocks we can change speed
157 // Low-level init for the bypass. Changes registers only
158 hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_ENABLE;
159 SDIO_Init(hsd.Instance, hsd.Init);
161 // 8 clocks is 160ns at 50Mhz
170 * @brief Configures Interrupt mode for SD detection pin.
172 * @retval Returns 0 in success otherwise 1.
174 uint8_t BSP_SD_ITConfig(void)
176 /* TBI: add user code here depending on the hardware configuration used */
181 /** @brief SD detect IT treatment
185 void BSP_SD_DetectIT(void)
187 /* TBI: add user code here depending on the hardware configuration used */
190 /** @brief SD detect IT detection callback
194 __weak void BSP_SD_DetectCallback(void)
196 /* NOTE: This function Should not be modified, when the callback is needed,
197 the SD_DetectCallback could be implemented in the user file
203 * @brief Reads block(s) from a specified address in an SD card, in polling mode.
204 * @param pData: Pointer to the buffer that will contain the data to transmit
205 * @param BlockAddr: Address from where data is to be read
206 * @param NumOfBlocks: Number of SD blocks to read
210 uint8_t BSP_SD_ReadBlocks(uint8_t *pData, uint64_t BlockAddr, uint32_t NumOfBlocks)
212 if(HAL_SD_ReadBlocks_DMA(&hsd, pData, BlockAddr, NumOfBlocks) != HAL_OK)
220 * @brief Writes block(s) to a specified address in an SD card, in polling mode.
221 * @param pData: Pointer to the buffer that will contain the data to transmit
222 * @param BlockAddr: Address from where data is to be written
223 * @param NumOfBlocks: Number of SD blocks to write
226 /*uint8_t BSP_SD_WriteBlocks(uint8_t *pData, uint64_t BlockAddr, uint32_t NumOfBlocks)
228 if(HAL_SD_WriteBlocks_DMA(&hsd, pData, BlockAddr, NumOfBlocks) != HAL_OK)
236 * @brief Reads block(s) from a specified address in an SD card, in DMA mode.
237 * @param pData: Pointer to the buffer that will contain the data to transmit
238 * @param BlockAddr: Address from where data is to be read
239 * @param NumOfBlocks: Number of SD blocks to read
242 uint8_t BSP_SD_ReadBlocks_DMA(uint8_t *pData, uint64_t BlockAddr, uint32_t NumOfBlocks)
244 uint8_t SD_state = MSD_OK;
246 /* Read block(s) in DMA transfer mode */
247 if(HAL_SD_ReadBlocks_DMA(&hsd, pData, BlockAddr, NumOfBlocks) != HAL_OK)
249 SD_state = MSD_ERROR;
252 /* Wait until transfer is complete */
253 if(SD_state == MSD_OK)
255 while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) {}
257 if(HAL_SD_GetState(&hsd) == HAL_SD_STATE_ERROR)
259 SD_state = MSD_ERROR;
266 HAL_SD_CardStateTypeDef cardState = HAL_SD_GetCardState(&hsd);
267 while (cardState == HAL_SD_CARD_PROGRAMMING || cardState == HAL_SD_CARD_SENDING)
269 cardState = HAL_SD_GetCardState(&hsd);
277 * @brief Writes block(s) to a specified address in an SD card, in DMA mode.
278 * @param pData: Pointer to the buffer that will contain the data to transmit
279 * @param BlockAddr: Address from where data is to be written
280 * @param NumOfBlocks: Number of SD blocks to write
283 uint8_t BSP_SD_WriteBlocks_DMA(uint8_t *pData, uint64_t BlockAddr, uint32_t NumOfBlocks)
285 uint8_t SD_state = MSD_OK;
287 /* Write block(s) in DMA transfer mode */
288 if(HAL_SD_WriteBlocks_DMA(&hsd, BlockAddr, NumOfBlocks) != HAL_OK)
290 SD_state = MSD_ERROR;
293 /* Wait until transfer is complete */
294 if(SD_state == MSD_OK)
296 for (int i = 0; i < NumOfBlocks; ++i)
298 while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) {}
300 // Wait while the SD card has no buffer space
301 while (sdIsBusy()) {}
303 HAL_SD_WriteBlocks_Data(&hsd, pData + (i * 512));
306 while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) {} // Wait for DMA to complete
310 SDMMC_CmdStopTransfer(hsd.Instance);
313 if(HAL_SD_GetState(&hsd) == HAL_SD_STATE_ERROR)
315 SD_state = MSD_ERROR;
322 // Wait while the SD card is in the PROGRAMMING state.
323 while (sdIsBusy()) {}
325 HAL_SD_CardStateTypeDef cardState = HAL_SD_GetCardState(&hsd);
326 while (cardState == HAL_SD_CARD_PROGRAMMING || cardState == HAL_SD_CARD_RECEIVING)
328 // Wait while the SD card is writing buffer to flash
329 // The card may remain in the RECEIVING state (even though it's programming) if
330 // it has buffer space to receive more data available.
332 cardState = HAL_SD_GetCardState(&hsd);
340 * @brief Erases the specified memory area of the given SD card.
341 * @param StartAddr: Start byte address
342 * @param EndAddr: End byte address
346 uint8_t BSP_SD_Erase(uint64_t StartAddr, uint64_t EndAddr)
348 if(HAL_SD_Erase(&hsd, StartAddr, EndAddr) != SD_OK)
358 * @brief Handles SD card interrupt request.
362 /*void BSP_SD_IRQHandler(void)
364 HAL_SD_IRQHandler(&hsd);
368 * @brief Handles SD DMA Tx transfer interrupt request.
372 /*void BSP_SD_DMA_Tx_IRQHandler(void)
374 HAL_DMA_IRQHandler(hsd.hdmatx);
378 * @brief Handles SD DMA Rx transfer interrupt request.
383 void BSP_SD_DMA_Rx_IRQHandler(void)
385 HAL_DMA_IRQHandler(hsd.hdmarx);
389 * @brief Gets the current SD card data status.
391 * @retval Data transfer state.
392 * This value can be one of the following values:
393 * @arg SD_TRANSFER_OK: No data transfer is acting
394 * @arg SD_TRANSFER_BUSY: Data transfer is acting
395 * @arg SD_TRANSFER_ERROR: Data transfer error
397 HAL_SD_CardStateTypeDef BSP_SD_GetStatus(void)
399 return(HAL_SD_GetState(&hsd));
403 * @brief Get SD information about specific SD card.
404 * @param CardInfo: Pointer to HAL_SD_CardInfoTypeDef structure
407 void BSP_SD_GetCardInfo(HAL_SD_CardInfoTypeDef* CardInfo)
409 /* Get SD card Information */
410 HAL_SD_GetCardInfo(&hsd, CardInfo);
412 /* USER CODE END 0 */
415 * @brief Detects if SD card is correctly plugged in the memory slot or not.
417 * @retval Returns if SD is detected or not
419 uint8_t BSP_SD_IsDetected(void)
421 __IO uint8_t status = SD_PRESENT;
423 /* USER CODE BEGIN 1 */
424 /* user code can be inserted here */
425 /* USER CODE END 1 */
430 /* USER CODE BEGIN AdditionalCode */
431 /* user code can be inserted here */
432 /* USER CODE END AdditionalCode */
434 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/