Use Docker to build firmware and scsi2sd-util6
[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 #include "time.h"
39
40 /* Extern variables ---------------------------------------------------------*/ 
41   
42 extern SD_HandleTypeDef hsd;
43
44 static uint8_t HighSpeedSwitch();
45
46 /**
47   * @brief  Initializes the SD card device.
48   * @param  None
49   * @retval SD status
50   */
51 uint8_t BSP_SD_Init(void)
52 {
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)
56     {
57         return MSD_ERROR;
58     }
59
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;
64
65     SD_state = HAL_SD_Init(&hsd);
66 #ifdef BUS_4BITS
67     if (SD_state == HAL_OK)
68     {
69         if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
70         {
71             SD_state = MSD_ERROR;
72         }
73         else
74         {
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;
78             SD_state = MSD_OK;
79
80 // Clock bypass mode is broken on STM32F205
81 #ifdef STM32F4xx
82             if (hsd.SdCard.CardType == CARD_SDHC_SDXC)
83             {
84                 HighSpeedSwitch();
85             }
86 #endif
87         }
88     }
89 #endif
90     return SD_state;
91 }
92
93 static uint8_t HighSpeedSwitch()
94 {
95     uint8_t SD_state = MSD_OK;
96
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);
106
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);
111
112     // Now we read some status data
113
114     if (errorstate == HAL_SD_ERROR_NONE)
115     {
116         uint32_t statusByteCount = 0;
117         while(!__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND))
118         {
119             if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXFIFOHF) && statusByteCount < 64)
120             {
121                 for ( uint32_t i = 0; i < 8; i++, statusByteCount += 4)
122                 {
123                     SDIO_ReadFIFO(hsd.Instance);
124                 }
125             }
126         }
127
128         if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_DTIMEOUT))
129         {
130             __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_DTIMEOUT);
131             SD_state = MSD_ERROR;
132         }
133         else if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_DCRCFAIL))
134         {
135             __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_DCRCFAIL);
136             SD_state = MSD_ERROR;
137         }
138         else if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXOVERR))
139         {
140             __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_RXOVERR);
141             SD_state = MSD_ERROR;
142         }
143         else
144         {
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))
148             {
149                 SDIO_ReadFIFO(hsd.Instance);
150                 count--;
151             }
152
153             /* Clear all the static flags */
154             __HAL_SD_CLEAR_FLAG(&hsd, SDIO_STATIC_FLAGS);
155
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); 
160
161             // 8 clocks is 160ns at 50Mhz
162             s2s_delay_ns(200);
163         }
164     }
165
166     return SD_state;
167 }
168
169 /**
170   * @brief  Configures Interrupt mode for SD detection pin.
171   * @param  None
172   * @retval Returns 0 in success otherwise 1. 
173   */
174 uint8_t BSP_SD_ITConfig(void)
175 {  
176   /* TBI: add user code here depending on the hardware configuration used */
177   
178   return 0;
179 }
180
181 /** @brief  SD detect IT treatment
182   * @param  None
183   * @retval None
184   */
185 void BSP_SD_DetectIT(void)
186 {
187   /* TBI: add user code here depending on the hardware configuration used */
188 }
189
190 /** @brief  SD detect IT detection callback
191   * @param  None
192   * @retval None
193   */
194 __weak void BSP_SD_DetectCallback(void)
195 {
196   /* NOTE: This function Should not be modified, when the callback is needed,
197   the SD_DetectCallback could be implemented in the user file
198   */ 
199   
200 }
201
202 /**
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 
207   * @retval SD status
208   */
209 /*
210 uint8_t BSP_SD_ReadBlocks(uint8_t *pData, uint64_t BlockAddr, uint32_t NumOfBlocks)
211 {
212   if(HAL_SD_ReadBlocks_DMA(&hsd, pData, BlockAddr, NumOfBlocks) != HAL_OK)  
213   {
214     return MSD_ERROR;
215   }
216   return MSD_OK;
217 }*/
218
219 /**
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
224   * @retval SD status
225   */
226 /*uint8_t BSP_SD_WriteBlocks(uint8_t *pData, uint64_t BlockAddr, uint32_t NumOfBlocks)
227 {
228   if(HAL_SD_WriteBlocks_DMA(&hsd, pData, BlockAddr, NumOfBlocks) != HAL_OK)  
229   {
230     return MSD_ERROR;
231   }
232   return MSD_OK;
233 }*/
234
235 /**
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 
240   * @retval SD status
241   */
242 uint8_t BSP_SD_ReadBlocks_DMA(uint8_t *pData, uint64_t BlockAddr, uint32_t NumOfBlocks)
243 {
244   uint8_t SD_state = MSD_OK;
245   
246   /* Read block(s) in DMA transfer mode */
247   if(HAL_SD_ReadBlocks_DMA(&hsd, pData, BlockAddr, NumOfBlocks) != HAL_OK)  
248   {
249     SD_state = MSD_ERROR;
250   }
251   
252   /* Wait until transfer is complete */
253   if(SD_state == MSD_OK)
254   {
255     while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) {}
256
257     if(HAL_SD_GetState(&hsd) == HAL_SD_STATE_ERROR)
258     {
259       SD_state = MSD_ERROR;
260     }
261     else
262     {
263       SD_state = MSD_OK;
264     }
265
266     HAL_SD_CardStateTypeDef cardState = HAL_SD_GetCardState(&hsd);
267     while (cardState == HAL_SD_CARD_PROGRAMMING || cardState == HAL_SD_CARD_SENDING) 
268     {
269         cardState = HAL_SD_GetCardState(&hsd);
270     }
271   }
272   
273   return SD_state; 
274 }
275
276 /**
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 
281   * @retval SD status
282   */
283 uint8_t BSP_SD_WriteBlocks_DMA(uint8_t *pData, uint64_t BlockAddr, uint32_t NumOfBlocks)
284 {
285   uint8_t SD_state = MSD_OK;
286   
287   /* Write block(s) in DMA transfer mode */
288   if(HAL_SD_WriteBlocks_DMA(&hsd, BlockAddr, NumOfBlocks) != HAL_OK)  
289   {
290     SD_state = MSD_ERROR;
291   }
292   
293   /* Wait until transfer is complete */
294   if(SD_state == MSD_OK)
295   {
296     for (int i = 0; i < NumOfBlocks; ++i)
297     {
298         while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) {}
299
300         // Wait while the SD card has no buffer space
301         while (sdIsBusy()) {}
302
303         HAL_SD_WriteBlocks_Data(&hsd, pData + (i * 512));
304     }
305
306     while (HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY) {} // Wait for DMA to complete
307
308     if (NumOfBlocks > 1)
309     {
310         SDMMC_CmdStopTransfer(hsd.Instance);
311     }
312
313     if(HAL_SD_GetState(&hsd) == HAL_SD_STATE_ERROR)
314     {
315       SD_state = MSD_ERROR;
316     }
317     else
318     {
319       SD_state = MSD_OK;
320     }
321
322     // Wait while the SD card is in the PROGRAMMING state.
323     while (sdIsBusy()) {}
324
325     HAL_SD_CardStateTypeDef cardState = HAL_SD_GetCardState(&hsd);
326     while (cardState == HAL_SD_CARD_PROGRAMMING || cardState == HAL_SD_CARD_RECEIVING) 
327     {
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.
331
332         cardState = HAL_SD_GetCardState(&hsd);
333     }
334   }
335   
336   return SD_state; 
337 }
338
339 /**
340   * @brief  Erases the specified memory area of the given SD card. 
341   * @param  StartAddr: Start byte address
342   * @param  EndAddr: End byte address
343   * @retval SD status
344   */
345 /*
346 uint8_t BSP_SD_Erase(uint64_t StartAddr, uint64_t EndAddr)
347 {
348   if(HAL_SD_Erase(&hsd, StartAddr, EndAddr) != SD_OK)  
349   {
350     return MSD_ERROR;
351   }
352
353   return MSD_OK;
354 }
355 */
356
357 /**
358   * @brief  Handles SD card interrupt request.
359   * @param  None
360   * @retval None
361   */
362 /*void BSP_SD_IRQHandler(void)
363 {
364   HAL_SD_IRQHandler(&hsd);
365 }*/
366
367 /**
368   * @brief  Handles SD DMA Tx transfer interrupt request.
369   * @param  None
370   * @retval None
371   */
372 /*void BSP_SD_DMA_Tx_IRQHandler(void)
373 {
374   HAL_DMA_IRQHandler(hsd.hdmatx); 
375 }*/
376
377 /**
378   * @brief  Handles SD DMA Rx transfer interrupt request.
379   * @param  None
380   * @retval None
381   */
382 /*
383 void BSP_SD_DMA_Rx_IRQHandler(void)
384 {
385   HAL_DMA_IRQHandler(hsd.hdmarx);
386 }*/
387
388 /**
389   * @brief  Gets the current SD card data status.
390   * @param  None
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 
396   */
397 HAL_SD_CardStateTypeDef BSP_SD_GetStatus(void)
398 {
399   return(HAL_SD_GetState(&hsd));
400 }
401
402 /**
403   * @brief  Get SD information about specific SD card.
404   * @param  CardInfo: Pointer to HAL_SD_CardInfoTypeDef structure
405   * @retval None 
406   */
407 void BSP_SD_GetCardInfo(HAL_SD_CardInfoTypeDef* CardInfo)
408 {
409   /* Get SD card Information */
410   HAL_SD_GetCardInfo(&hsd, CardInfo);
411 }
412 /* USER CODE END 0 */
413
414 /**
415  * @brief  Detects if SD card is correctly plugged in the memory slot or not.
416  * @param  None
417  * @retval Returns if SD is detected or not
418  */
419 uint8_t BSP_SD_IsDetected(void)
420 {
421   __IO uint8_t status = SD_PRESENT;
422
423   /* USER CODE BEGIN 1 */
424   /* user code can be inserted here */
425   /* USER CODE END 1 */    
426   
427   return status;
428 }
429
430 /* USER CODE BEGIN AdditionalCode */
431 /* user code can be inserted here */
432 /* USER CODE END AdditionalCode */
433
434 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/