fe2601c43d29abd2236267d722a2c6437789d14a
[SCSI2SD-V6.git] / src / firmware / bsp_driver_sd.c
1 /**
2  ******************************************************************************
3   * @file    bsp_driver_sd.c (based on stm324x9i_eval_sd.c)
4   * @brief   This file includes a generic uSD card driver.
5   ******************************************************************************
6   *
7   * COPYRIGHT(c) 2016 STMicroelectronics
8   *
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.
19   *
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.
30   *
31   ******************************************************************************
32   */
33 #define BUS_4BITS 1
34 /* USER CODE BEGIN 0 */
35 /* Includes ------------------------------------------------------------------*/
36 #include "bsp_driver_sd.h"
37
38 /* Extern variables ---------------------------------------------------------*/ 
39   
40 extern SD_HandleTypeDef hsd;
41
42 /**
43   * @brief  Initializes the SD card device.
44   * @param  None
45   * @retval SD status
46   */
47 uint8_t BSP_SD_Init(void)
48 {
49   uint8_t SD_state = MSD_OK;
50   /* Check if the SD card is plugged in the slot */
51   if (BSP_SD_IsDetected() != SD_PRESENT)
52   {
53     return MSD_ERROR;
54   }
55   SD_state = HAL_SD_Init(&hsd);
56 #ifdef BUS_4BITS
57   if (SD_state == MSD_OK)
58   {
59     if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
60     {
61       SD_state = MSD_ERROR;
62     }
63     else
64     {
65       SD_state = MSD_OK;
66
67 // Clock bypass mode is broken on STM32F205
68 // This just corrupts data for now.
69 //#ifdef STM32F4xx
70 #if 0
71       uint8_t SD_hs[64]  = {0};
72       //uint32_t SD_scr[2] = {0, 0};
73       //uint32_t SD_SPEC   = 0 ;
74       uint32_t count = 0;
75       uint32_t *tempbuff = (uint32_t *)SD_hs;
76
77       // Prepare to read 64 bytes training data
78       SDIO_DataInitTypeDef config;
79       config.DataTimeOut   = SDMMC_DATATIMEOUT;
80       config.DataLength    = 64;
81       config.DataBlockSize = SDIO_DATABLOCK_SIZE_64B;
82       config.TransferDir   = SDIO_TRANSFER_DIR_TO_SDIO;
83       config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
84       config.DPSM          = SDIO_DPSM_ENABLE;
85       (void)SDIO_ConfigData(hsd.Instance, &config);
86
87       // High speed switch.
88       // SDR25 (25MB/s) mode 0x80FFFF01
89       // Which is the max without going to 1.8v
90       uint32_t errorstate = SDMMC_CmdSwitch(hsd.Instance, 0x80FFFF01);
91
92       // Low-level init for the bypass. Changes registers only
93       hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_ENABLE;
94       SDIO_Init(hsd.Instance, hsd.Init); 
95
96       // Now we read some training data
97
98       if (errorstate == HAL_SD_ERROR_NONE)
99       {
100         while(!__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND/* | SDIO_FLAG_STBITERR*/))
101         {
102           if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXFIFOHF))
103           {
104             for (count = 0; count < 8; count++)
105             {
106               *(tempbuff + count) = SDIO_ReadFIFO(hsd.Instance);
107             }
108
109             tempbuff += 8;
110           }
111         }
112
113         if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_DTIMEOUT))
114         {
115           __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_DTIMEOUT);
116           SD_state = MSD_ERROR;
117         }
118         else if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_DCRCFAIL))
119         {
120           __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_DCRCFAIL);
121           SD_state = MSD_ERROR;
122         }
123         else if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXOVERR))
124         {
125           __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_RXOVERR);
126           SD_state = MSD_ERROR;
127         }
128         /*else if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_STBITERR))
129         {
130           __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_STBITERR);
131           SD_state = MSD_ERROR;
132         }*/
133         else
134         {
135           count = SD_DATATIMEOUT;
136
137           while ((__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXDAVL)) && (count > 0))
138           {
139             *tempbuff = SDIO_ReadFIFO(hsd.Instance);
140             tempbuff++;
141             count--;
142           }
143
144           /* Clear all the static flags */
145           __HAL_SD_CLEAR_FLAG(&hsd, SDIO_STATIC_FLAGS);
146         }
147       }
148 #endif
149     }
150   }
151 #endif
152   return SD_state;
153 }
154
155 /**
156   * @brief  Configures Interrupt mode for SD detection pin.
157   * @param  None
158   * @retval Returns 0 in success otherwise 1. 
159   */
160 uint8_t BSP_SD_ITConfig(void)
161 {  
162   /* TBI: add user code here depending on the hardware configuration used */
163   
164   return 0;
165 }
166
167 /** @brief  SD detect IT treatment
168   * @param  None
169   * @retval None
170   */
171 void BSP_SD_DetectIT(void)
172 {
173   /* TBI: add user code here depending on the hardware configuration used */
174 }
175
176 /** @brief  SD detect IT detection callback
177   * @param  None
178   * @retval None
179   */
180 __weak void BSP_SD_DetectCallback(void)
181 {
182   /* NOTE: This function Should not be modified, when the callback is needed,
183   the SD_DetectCallback could be implemented in the user file
184   */ 
185   
186 }
187
188 /**
189   * @brief  Reads block(s) from a specified address in an SD card, in polling mode. 
190   * @param  pData: Pointer to the buffer that will contain the data to transmit
191   * @param  BlockAddr: Address from where data is to be read  
192   * @param  NumOfBlocks: Number of SD blocks to read 
193   * @retval SD status
194   */
195 uint8_t BSP_SD_ReadBlocks(uint8_t *pData, uint64_t BlockAddr, uint32_t NumOfBlocks)
196 {
197   if(HAL_SD_ReadBlocks_DMA(&hsd, pData, BlockAddr, NumOfBlocks) != HAL_OK)  
198   {
199     return MSD_ERROR;
200   }
201   return MSD_OK;
202 }
203
204 /**
205   * @brief  Writes block(s) to a specified address in an SD card, in polling mode. 
206   * @param  pData: Pointer to the buffer that will contain the data to transmit
207   * @param  BlockAddr: Address from where data is to be written  
208   * @param  NumOfBlocks: Number of SD blocks to write
209   * @retval SD status
210   */
211 uint8_t BSP_SD_WriteBlocks(uint8_t *pData, uint64_t BlockAddr, uint32_t NumOfBlocks)
212 {
213   if(HAL_SD_WriteBlocks_DMA(&hsd, pData, BlockAddr, NumOfBlocks) != HAL_OK)  
214   {
215     return MSD_ERROR;
216   }
217   return MSD_OK;
218 }
219
220 /**
221   * @brief  Reads block(s) from a specified address in an SD card, in DMA mode. 
222   * @param  pData: Pointer to the buffer that will contain the data to transmit
223   * @param  BlockAddr: Address from where data is to be read  
224   * @param  NumOfBlocks: Number of SD blocks to read 
225   * @retval SD status
226   */
227 uint8_t BSP_SD_ReadBlocks_DMA(uint8_t *pData, uint64_t BlockAddr, uint32_t NumOfBlocks)
228 {
229   uint8_t SD_state = MSD_OK;
230   
231   /* Read block(s) in DMA transfer mode */
232   if(HAL_SD_ReadBlocks_DMA(&hsd, pData, BlockAddr, NumOfBlocks) != HAL_OK)  
233   {
234     SD_state = MSD_ERROR;
235   }
236   
237   /* Wait until transfer is complete */
238   if(SD_state == MSD_OK)
239   {
240     while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) {}
241
242     if(HAL_SD_GetState(&hsd) == HAL_SD_STATE_ERROR)
243     {
244       SD_state = MSD_ERROR;
245     }
246     else
247     {
248       SD_state = MSD_OK;
249     }
250   }
251   
252   return SD_state; 
253 }
254
255 /**
256   * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.  
257   * @param  pData: Pointer to the buffer that will contain the data to transmit
258   * @param  BlockAddr: Address from where data is to be written  
259   * @param  NumOfBlocks: Number of SD blocks to write 
260   * @retval SD status
261   */
262 uint8_t BSP_SD_WriteBlocks_DMA(uint8_t *pData, uint64_t BlockAddr, uint32_t NumOfBlocks)
263 {
264   uint8_t SD_state = MSD_OK;
265   
266   /* Write block(s) in DMA transfer mode */
267   if(HAL_SD_WriteBlocks_DMA(&hsd, pData, BlockAddr, NumOfBlocks) != HAL_OK)  
268   {
269     SD_state = MSD_ERROR;
270   }
271   
272   /* Wait until transfer is complete */
273   if(SD_state == MSD_OK)
274   {
275     while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) {}
276
277     if(HAL_SD_GetState(&hsd) == HAL_SD_STATE_ERROR)
278     {
279       SD_state = MSD_ERROR;
280     }
281     else
282     {
283       SD_state = MSD_OK;
284     }
285
286     while (HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_PROGRAMMING) {}
287   }
288   
289   return SD_state; 
290 }
291
292 /**
293   * @brief  Erases the specified memory area of the given SD card. 
294   * @param  StartAddr: Start byte address
295   * @param  EndAddr: End byte address
296   * @retval SD status
297   */
298 /*
299 uint8_t BSP_SD_Erase(uint64_t StartAddr, uint64_t EndAddr)
300 {
301   if(HAL_SD_Erase(&hsd, StartAddr, EndAddr) != SD_OK)  
302   {
303     return MSD_ERROR;
304   }
305
306   return MSD_OK;
307 }
308 */
309
310 /**
311   * @brief  Handles SD card interrupt request.
312   * @param  None
313   * @retval None
314   */
315 /*void BSP_SD_IRQHandler(void)
316 {
317   HAL_SD_IRQHandler(&hsd);
318 }*/
319
320 /**
321   * @brief  Handles SD DMA Tx transfer interrupt request.
322   * @param  None
323   * @retval None
324   */
325 /*void BSP_SD_DMA_Tx_IRQHandler(void)
326 {
327   HAL_DMA_IRQHandler(hsd.hdmatx); 
328 }*/
329
330 /**
331   * @brief  Handles SD DMA Rx transfer interrupt request.
332   * @param  None
333   * @retval None
334   */
335 /*
336 void BSP_SD_DMA_Rx_IRQHandler(void)
337 {
338   HAL_DMA_IRQHandler(hsd.hdmarx);
339 }*/
340
341 /**
342   * @brief  Gets the current SD card data status.
343   * @param  None
344   * @retval Data transfer state.
345   *          This value can be one of the following values:
346   *            @arg  SD_TRANSFER_OK: No data transfer is acting
347   *            @arg  SD_TRANSFER_BUSY: Data transfer is acting
348   *            @arg  SD_TRANSFER_ERROR: Data transfer error 
349   */
350 HAL_SD_CardStateTypeDef BSP_SD_GetStatus(void)
351 {
352   return(HAL_SD_GetState(&hsd));
353 }
354
355 /**
356   * @brief  Get SD information about specific SD card.
357   * @param  CardInfo: Pointer to HAL_SD_CardInfoTypeDef structure
358   * @retval None 
359   */
360 void BSP_SD_GetCardInfo(HAL_SD_CardInfoTypeDef* CardInfo)
361 {
362   /* Get SD card Information */
363   HAL_SD_GetCardInfo(&hsd, CardInfo);
364 }
365 /* USER CODE END 0 */
366
367 /**
368  * @brief  Detects if SD card is correctly plugged in the memory slot or not.
369  * @param  None
370  * @retval Returns if SD is detected or not
371  */
372 uint8_t BSP_SD_IsDetected(void)
373 {
374   __IO uint8_t status = SD_PRESENT;
375
376   /* USER CODE BEGIN 1 */
377   /* user code can be inserted here */
378   /* USER CODE END 1 */    
379   
380   return status;
381 }
382
383 /* USER CODE BEGIN AdditionalCode */
384 /* user code can be inserted here */
385 /* USER CODE END AdditionalCode */
386
387 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/