e972c98ff818aa38b724cd201774f82fac5ec4c4
[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 /*
196 uint8_t BSP_SD_ReadBlocks(uint8_t *pData, uint64_t BlockAddr, uint32_t NumOfBlocks)
197 {
198   if(HAL_SD_ReadBlocks_DMA(&hsd, pData, BlockAddr, NumOfBlocks) != HAL_OK)  
199   {
200     return MSD_ERROR;
201   }
202   return MSD_OK;
203 }*/
204
205 /**
206   * @brief  Writes block(s) to a specified address in an SD card, in polling mode. 
207   * @param  pData: Pointer to the buffer that will contain the data to transmit
208   * @param  BlockAddr: Address from where data is to be written  
209   * @param  NumOfBlocks: Number of SD blocks to write
210   * @retval SD status
211   */
212 /*uint8_t BSP_SD_WriteBlocks(uint8_t *pData, uint64_t BlockAddr, uint32_t NumOfBlocks)
213 {
214   if(HAL_SD_WriteBlocks_DMA(&hsd, pData, BlockAddr, NumOfBlocks) != HAL_OK)  
215   {
216     return MSD_ERROR;
217   }
218   return MSD_OK;
219 }*/
220
221 /**
222   * @brief  Reads block(s) from a specified address in an SD card, in DMA mode. 
223   * @param  pData: Pointer to the buffer that will contain the data to transmit
224   * @param  BlockAddr: Address from where data is to be read  
225   * @param  NumOfBlocks: Number of SD blocks to read 
226   * @retval SD status
227   */
228 uint8_t BSP_SD_ReadBlocks_DMA(uint8_t *pData, uint64_t BlockAddr, uint32_t NumOfBlocks)
229 {
230   uint8_t SD_state = MSD_OK;
231   
232   /* Read block(s) in DMA transfer mode */
233   if(HAL_SD_ReadBlocks_DMA(&hsd, pData, BlockAddr, NumOfBlocks) != HAL_OK)  
234   {
235     SD_state = MSD_ERROR;
236   }
237   
238   /* Wait until transfer is complete */
239   if(SD_state == MSD_OK)
240   {
241     while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) {}
242
243     if(HAL_SD_GetState(&hsd) == HAL_SD_STATE_ERROR)
244     {
245       SD_state = MSD_ERROR;
246     }
247     else
248     {
249       SD_state = MSD_OK;
250     }
251
252     HAL_SD_CardStateTypeDef cardState = HAL_SD_GetCardState(&hsd);
253     while (cardState == HAL_SD_CARD_PROGRAMMING || cardState == HAL_SD_CARD_SENDING) 
254     {
255         cardState = HAL_SD_GetCardState(&hsd);
256     }
257   }
258   
259   return SD_state; 
260 }
261
262 /**
263   * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.  
264   * @param  pData: Pointer to the buffer that will contain the data to transmit
265   * @param  BlockAddr: Address from where data is to be written  
266   * @param  NumOfBlocks: Number of SD blocks to write 
267   * @retval SD status
268   */
269 uint8_t BSP_SD_WriteBlocks_DMA(uint8_t *pData, uint64_t BlockAddr, uint32_t NumOfBlocks)
270 {
271   uint8_t SD_state = MSD_OK;
272   
273   /* Write block(s) in DMA transfer mode */
274   if(HAL_SD_WriteBlocks_DMA(&hsd, BlockAddr, NumOfBlocks) != HAL_OK)  
275   {
276     SD_state = MSD_ERROR;
277   }
278   
279   /* Wait until transfer is complete */
280   if(SD_state == MSD_OK)
281   {
282     for (int i = 0; i < NumOfBlocks; ++i)
283     {
284         while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) {}
285
286         HAL_SD_CardStateTypeDef cardState = HAL_SD_GetCardState(&hsd);
287         while (cardState == HAL_SD_CARD_PROGRAMMING) 
288         {   
289             // Wait while the SD card is writing buffer to flash
290             // The card may remain in the RECEIVING state (even though it's programming) if
291             // it has buffer space to receive more data available.
292
293             cardState = HAL_SD_GetCardState(&hsd);
294         }
295
296         HAL_SD_WriteBlocks_Data(&hsd, pData + (i * 512));
297     }
298
299     while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) {} // Wait for DMA to complete
300
301     if (NumOfBlocks > 1)
302     {
303         SDMMC_CmdStopTransfer(hsd.Instance);
304     }
305
306     if(HAL_SD_GetState(&hsd) == HAL_SD_STATE_ERROR)
307     {
308       SD_state = MSD_ERROR;
309     }
310     else
311     {
312       SD_state = MSD_OK;
313     }
314
315     HAL_SD_CardStateTypeDef cardState = HAL_SD_GetCardState(&hsd);
316     while (cardState == HAL_SD_CARD_PROGRAMMING || cardState == HAL_SD_CARD_RECEIVING) 
317     {
318         // Wait while the SD card is writing buffer to flash
319         // The card may remain in the RECEIVING state (even though it's programming) if
320         // it has buffer space to receive more data available.
321
322         cardState = HAL_SD_GetCardState(&hsd);
323     }
324   }
325   
326   return SD_state; 
327 }
328
329 /**
330   * @brief  Erases the specified memory area of the given SD card. 
331   * @param  StartAddr: Start byte address
332   * @param  EndAddr: End byte address
333   * @retval SD status
334   */
335 /*
336 uint8_t BSP_SD_Erase(uint64_t StartAddr, uint64_t EndAddr)
337 {
338   if(HAL_SD_Erase(&hsd, StartAddr, EndAddr) != SD_OK)  
339   {
340     return MSD_ERROR;
341   }
342
343   return MSD_OK;
344 }
345 */
346
347 /**
348   * @brief  Handles SD card interrupt request.
349   * @param  None
350   * @retval None
351   */
352 /*void BSP_SD_IRQHandler(void)
353 {
354   HAL_SD_IRQHandler(&hsd);
355 }*/
356
357 /**
358   * @brief  Handles SD DMA Tx transfer interrupt request.
359   * @param  None
360   * @retval None
361   */
362 /*void BSP_SD_DMA_Tx_IRQHandler(void)
363 {
364   HAL_DMA_IRQHandler(hsd.hdmatx); 
365 }*/
366
367 /**
368   * @brief  Handles SD DMA Rx transfer interrupt request.
369   * @param  None
370   * @retval None
371   */
372 /*
373 void BSP_SD_DMA_Rx_IRQHandler(void)
374 {
375   HAL_DMA_IRQHandler(hsd.hdmarx);
376 }*/
377
378 /**
379   * @brief  Gets the current SD card data status.
380   * @param  None
381   * @retval Data transfer state.
382   *          This value can be one of the following values:
383   *            @arg  SD_TRANSFER_OK: No data transfer is acting
384   *            @arg  SD_TRANSFER_BUSY: Data transfer is acting
385   *            @arg  SD_TRANSFER_ERROR: Data transfer error 
386   */
387 HAL_SD_CardStateTypeDef BSP_SD_GetStatus(void)
388 {
389   return(HAL_SD_GetState(&hsd));
390 }
391
392 /**
393   * @brief  Get SD information about specific SD card.
394   * @param  CardInfo: Pointer to HAL_SD_CardInfoTypeDef structure
395   * @retval None 
396   */
397 void BSP_SD_GetCardInfo(HAL_SD_CardInfoTypeDef* CardInfo)
398 {
399   /* Get SD card Information */
400   HAL_SD_GetCardInfo(&hsd, CardInfo);
401 }
402 /* USER CODE END 0 */
403
404 /**
405  * @brief  Detects if SD card is correctly plugged in the memory slot or not.
406  * @param  None
407  * @retval Returns if SD is detected or not
408  */
409 uint8_t BSP_SD_IsDetected(void)
410 {
411   __IO uint8_t status = SD_PRESENT;
412
413   /* USER CODE BEGIN 1 */
414   /* user code can be inserted here */
415   /* USER CODE END 1 */    
416   
417   return status;
418 }
419
420 /* USER CODE BEGIN AdditionalCode */
421 /* user code can be inserted here */
422 /* USER CODE END AdditionalCode */
423
424 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/