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