Fix issue with SCSI timeouts if writes take too long
[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   
253   return SD_state; 
254 }
255
256 /**
257   * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.  
258   * @param  pData: Pointer to the buffer that will contain the data to transmit
259   * @param  BlockAddr: Address from where data is to be written  
260   * @param  NumOfBlocks: Number of SD blocks to write 
261   * @retval SD status
262   */
263 uint8_t BSP_SD_WriteBlocks_DMA(uint8_t *pData, uint64_t BlockAddr, uint32_t NumOfBlocks)
264 {
265   uint8_t SD_state = MSD_OK;
266   
267   /* Write block(s) in DMA transfer mode */
268   if(HAL_SD_WriteBlocks_DMA(&hsd, pData, BlockAddr, NumOfBlocks) != HAL_OK)  
269   {
270     SD_state = MSD_ERROR;
271   }
272   
273   /* Wait until transfer is complete */
274   if(SD_state == MSD_OK)
275   {
276     while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) {}
277
278     if(HAL_SD_GetState(&hsd) == HAL_SD_STATE_ERROR)
279     {
280       SD_state = MSD_ERROR;
281     }
282     else
283     {
284       SD_state = MSD_OK;
285     }
286
287     HAL_SD_CardStateTypeDef cardState = HAL_SD_GetCardState(&hsd);
288     while (cardState == HAL_SD_CARD_PROGRAMMING || cardState == HAL_SD_CARD_RECEIVING) 
289     {
290         // Wait while the SD card is writing buffer to flash
291         // The card may remain in the RECEIVING state (even though it's programming) if
292         // it has buffer space to receive more data available.
293
294         cardState = HAL_SD_GetCardState(&hsd);
295     }
296
297   }
298   
299   return SD_state; 
300 }
301
302 /**
303   * @brief  Erases the specified memory area of the given SD card. 
304   * @param  StartAddr: Start byte address
305   * @param  EndAddr: End byte address
306   * @retval SD status
307   */
308 /*
309 uint8_t BSP_SD_Erase(uint64_t StartAddr, uint64_t EndAddr)
310 {
311   if(HAL_SD_Erase(&hsd, StartAddr, EndAddr) != SD_OK)  
312   {
313     return MSD_ERROR;
314   }
315
316   return MSD_OK;
317 }
318 */
319
320 /**
321   * @brief  Handles SD card interrupt request.
322   * @param  None
323   * @retval None
324   */
325 /*void BSP_SD_IRQHandler(void)
326 {
327   HAL_SD_IRQHandler(&hsd);
328 }*/
329
330 /**
331   * @brief  Handles SD DMA Tx transfer interrupt request.
332   * @param  None
333   * @retval None
334   */
335 /*void BSP_SD_DMA_Tx_IRQHandler(void)
336 {
337   HAL_DMA_IRQHandler(hsd.hdmatx); 
338 }*/
339
340 /**
341   * @brief  Handles SD DMA Rx transfer interrupt request.
342   * @param  None
343   * @retval None
344   */
345 /*
346 void BSP_SD_DMA_Rx_IRQHandler(void)
347 {
348   HAL_DMA_IRQHandler(hsd.hdmarx);
349 }*/
350
351 /**
352   * @brief  Gets the current SD card data status.
353   * @param  None
354   * @retval Data transfer state.
355   *          This value can be one of the following values:
356   *            @arg  SD_TRANSFER_OK: No data transfer is acting
357   *            @arg  SD_TRANSFER_BUSY: Data transfer is acting
358   *            @arg  SD_TRANSFER_ERROR: Data transfer error 
359   */
360 HAL_SD_CardStateTypeDef BSP_SD_GetStatus(void)
361 {
362   return(HAL_SD_GetState(&hsd));
363 }
364
365 /**
366   * @brief  Get SD information about specific SD card.
367   * @param  CardInfo: Pointer to HAL_SD_CardInfoTypeDef structure
368   * @retval None 
369   */
370 void BSP_SD_GetCardInfo(HAL_SD_CardInfoTypeDef* CardInfo)
371 {
372   /* Get SD card Information */
373   HAL_SD_GetCardInfo(&hsd, CardInfo);
374 }
375 /* USER CODE END 0 */
376
377 /**
378  * @brief  Detects if SD card is correctly plugged in the memory slot or not.
379  * @param  None
380  * @retval Returns if SD is detected or not
381  */
382 uint8_t BSP_SD_IsDetected(void)
383 {
384   __IO uint8_t status = SD_PRESENT;
385
386   /* USER CODE BEGIN 1 */
387   /* user code can be inserted here */
388   /* USER CODE END 1 */    
389   
390   return status;
391 }
392
393 /* USER CODE BEGIN AdditionalCode */
394 /* user code can be inserted here */
395 /* USER CODE END AdditionalCode */
396
397 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/