1 /**
2   ******************************************************************************
3   * @file    stm32l4xx_hal_sd_ex.c
4   * @author  MCD Application Team
5   * @brief   SD card Extended HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the Secure Digital (SD) peripheral:
8   *           + Extended features functions
9   *
10   @verbatim
11   ==============================================================================
12                         ##### How to use this driver #####
13   ==============================================================================
14   [..]
15    The SD Extension HAL driver can be used as follows:
16    (+) Set card in High Speed mode using HAL_SDEx_HighSpeed() function.
17    (+) Configure Buffer0 and Buffer1 start address and Buffer size using HAL_SDEx_ConfigDMAMultiBuffer() function.
18    (+) Start Read and Write for multibuffer mode using HAL_SDEx_ReadBlocksDMAMultiBuffer() and HAL_SDEx_WriteBlocksDMAMultiBuffer() functions.
19 
20   @endverbatim
21   ******************************************************************************
22   * @attention
23   *
24   * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
25   *
26   * Redistribution and use in source and binary forms, with or without modification,
27   * are permitted provided that the following conditions are met:
28   *   1. Redistributions of source code must retain the above copyright notice,
29   *      this list of conditions and the following disclaimer.
30   *   2. Redistributions in binary form must reproduce the above copyright notice,
31   *      this list of conditions and the following disclaimer in the documentation
32   *      and/or other materials provided with the distribution.
33   *   3. Neither the name of STMicroelectronics nor the names of its contributors
34   *      may be used to endorse or promote products derived from this software
35   *      without specific prior written permission.
36   *
37   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
38   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
41   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
44   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47   *
48   ******************************************************************************
49   */
50 
51 /* Includes ------------------------------------------------------------------*/
52 #include "stm32l4xx_hal.h"
53 
54 #if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
55 
56 /** @addtogroup STM32L4xx_HAL_Driver
57   * @{
58   */
59 
60 /** @defgroup SDEx SDEx
61   * @brief SD HAL extended module driver
62   * @{
63   */
64 
65 #ifdef HAL_SD_MODULE_ENABLED
66 
67 /* Private typedef -----------------------------------------------------------*/
68 /* Private define ------------------------------------------------------------*/
69 /* Private macro -------------------------------------------------------------*/
70 /* Private variables ---------------------------------------------------------*/
71 /* Private function prototypes -----------------------------------------------*/
72 /* Private functions ---------------------------------------------------------*/
73 /* Exported functions --------------------------------------------------------*/
74 /** @addtogroup SDEx_Exported_Functions
75   * @{
76   */
77 
78 /** @addtogroup SDEx_Exported_Functions_Group1
79  *  @brief   High Speed function
80  *
81 @verbatim
82   ==============================================================================
83           ##### High Speed function #####
84   ==============================================================================
85   [..]
86     This section provides function allowing to configure the card in High Speed mode.
87 
88 @endverbatim
89   * @{
90   */
91 
92 /**
93   * @brief  Switches the SD card to High Speed mode.
94   *         This API must be used after "Transfer State"
95   * @note   This operation should be followed by the configuration
96   *         of PLL to have SDMMCCK clock between 50 and 120 MHz
97   * @param  hsd: SD handle
98   * @retval SD Card error state
99   */
HAL_SDEx_HighSpeed(SD_HandleTypeDef * hsd)100 uint32_t HAL_SDEx_HighSpeed(SD_HandleTypeDef *hsd)
101 {
102   uint32_t errorstate = HAL_SD_ERROR_NONE;
103   SDMMC_DataInitTypeDef sdmmc_datainitstructure;
104   uint8_t SD_hs[64]  = {0};
105   uint8_t *tempbuff = SD_hs;
106   uint32_t count, data;
107   uint32_t Timeout = HAL_GetTick();
108 
109   if(hsd->SdCard.CardSpeed == CARD_NORMAL_SPEED)
110   {
111      /* Standard Speed Card <= 12.5Mhz  */
112      return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
113   }
114 
115   if((hsd->SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED) &&
116       (hsd->Init.Transceiver == SDMMC_TRANSCEIVER_ENABLE))
117   {
118     /* Initialize the Data control register */
119     hsd->Instance->DCTRL = 0;
120     errorstate = SDMMC_CmdBlockLength(hsd->Instance, 64);
121 
122     if (errorstate != HAL_SD_ERROR_NONE)
123     {
124       return errorstate;
125     }
126 
127     /* Configure the SD DPSM (Data Path State Machine) */
128     sdmmc_datainitstructure.DataTimeOut   = SDMMC_DATATIMEOUT;
129     sdmmc_datainitstructure.DataLength    = 64;
130     sdmmc_datainitstructure.DataBlockSize = SDMMC_DATABLOCK_SIZE_64B ;
131     sdmmc_datainitstructure.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
132     sdmmc_datainitstructure.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
133     sdmmc_datainitstructure.DPSM          = SDMMC_DPSM_ENABLE;
134     (void)SDMMC_ConfigData(hsd->Instance, &sdmmc_datainitstructure);
135 
136     errorstate = SDMMC_CmdSwitch(hsd->Instance, SDMMC_SDR25_SWITCH_PATTERN);
137     if(errorstate != HAL_SD_ERROR_NONE)
138     {
139       return errorstate;
140     }
141 
142     while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DBCKEND| SDMMC_FLAG_DATAEND ))
143     {
144       if (__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF))
145       {
146         for (count = 0U; count < 8U; count++)
147         {
148           data = SDMMC_ReadFIFO(hsd->Instance);
149           *tempbuff = (uint8_t)(data & 0xFFU);
150           tempbuff++;
151           *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
152           tempbuff++;
153           *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
154           tempbuff++;
155           *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
156           tempbuff++;
157         }
158       }
159 
160       if((HAL_GetTick()-Timeout) >=  SDMMC_DATATIMEOUT)
161       {
162         hsd->ErrorCode = HAL_SD_ERROR_TIMEOUT;
163         hsd->State= HAL_SD_STATE_READY;
164         return HAL_SD_ERROR_TIMEOUT;
165       }
166     }
167 
168     if (__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
169     {
170       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_DTIMEOUT);
171 
172       errorstate = 0;
173 
174       return errorstate;
175     }
176     else if (__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
177     {
178       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_DCRCFAIL);
179 
180       errorstate = SDMMC_ERROR_DATA_CRC_FAIL;
181 
182       return errorstate;
183     }
184     else if (__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
185     {
186       __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_RXOVERR);
187 
188       errorstate = SDMMC_ERROR_RX_OVERRUN;
189 
190       return errorstate;
191     }
192     else
193     {
194       /* No error flag set */
195     }
196 
197     /* Clear all the static flags */
198     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
199 
200     /* Test if the switch mode HS is ok */
201     if ((SD_hs[13U] & 2U) == 0U)
202     {
203       errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
204       return errorstate;
205     }
206     else
207     {
208 #if (USE_HAL_SD_REGISTER_CALLBACKS == 1)
209       hsd->DriveTransceiver_1_8V_Callback(SET);
210 #else
211       HAL_SDEx_DriveTransceiver_1_8V_Callback(SET);
212 #endif
213     }
214 
215     /* Set Block Size for Card */
216     errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
217     if(errorstate != HAL_SD_ERROR_NONE)
218     {
219       hsd->State = HAL_SD_STATE_READY;
220       hsd->ErrorCode |= errorstate;
221       return errorstate;
222     }
223   }
224 
225   return errorstate;
226 }
227 
228 /**
229   * @brief  Enable/Disable the SD Transceiver 1.8V Mode Callback.
230   * @param  status: Voltage Switch State
231   * @retval None
232   */
HAL_SDEx_DriveTransceiver_1_8V_Callback(FlagStatus status)233 __weak void HAL_SDEx_DriveTransceiver_1_8V_Callback(FlagStatus status)
234 {
235   /* Prevent unused argument(s) compilation warning */
236   UNUSED(status);
237 
238   /* NOTE : This function Should not be modified, when the callback is needed,
239             the HAL_SD_EnableTransciver could be implemented in the user file
240    */
241 }
242 
243 /**
244   * @}
245   */
246 
247 /** @addtogroup SDEx_Exported_Functions_Group2
248  *  @brief   Multibuffer functions
249  *
250 @verbatim
251   ==============================================================================
252           ##### Multibuffer functions #####
253   ==============================================================================
254   [..]
255     This section provides functions allowing to configure the multibuffer mode and start read and write
256     multibuffer mode for SD HAL driver.
257 
258 @endverbatim
259   * @{
260   */
261 
262 /**
263   * @brief  Configure DMA Dual Buffer mode. The Data transfer is managed by an Internal DMA.
264   * @param  hsd: SD handle
265   * @param  pDataBuffer0: Pointer to the buffer0 that will contain/receive the transfered data
266   * @param  pDataBuffer1: Pointer to the buffer1 that will contain/receive the transfered data
267   * @param  BufferSize: Size of Buffer0 in Blocks. Buffer0 and Buffer1 must have the same size.
268   * @retval HAL status
269   */
HAL_SDEx_ConfigDMAMultiBuffer(SD_HandleTypeDef * hsd,uint32_t * pDataBuffer0,uint32_t * pDataBuffer1,uint32_t BufferSize)270 HAL_StatusTypeDef HAL_SDEx_ConfigDMAMultiBuffer(SD_HandleTypeDef *hsd, uint32_t *pDataBuffer0, uint32_t *pDataBuffer1, uint32_t BufferSize)
271 {
272   if(hsd->State == HAL_SD_STATE_READY)
273   {
274     hsd->Instance->IDMABASE0 = (uint32_t) pDataBuffer0;
275     hsd->Instance->IDMABASE1 = (uint32_t) pDataBuffer1;
276     hsd->Instance->IDMABSIZE = (uint32_t) (BLOCKSIZE * BufferSize);
277 
278     return HAL_OK;
279   }
280   else
281   {
282     return HAL_BUSY;
283   }
284 }
285 
286 /**
287   * @brief  Reads block(s) from a specified address in a card. The received Data will be stored in Buffer0 and Buffer1.
288   *         Buffer0, Buffer1 and BufferSize need to be configured by function HAL_SDEx_ConfigDMAMultiBuffer before call this function.
289   * @param  hsd: SD handle
290   * @param  BlockAdd: Block Address from where data is to be read
291   * @param  NumberOfBlocks: Total number of blocks to read
292   * @retval HAL status
293   */
HAL_SDEx_ReadBlocksDMAMultiBuffer(SD_HandleTypeDef * hsd,uint32_t BlockAdd,uint32_t NumberOfBlocks)294 HAL_StatusTypeDef HAL_SDEx_ReadBlocksDMAMultiBuffer(SD_HandleTypeDef *hsd, uint32_t BlockAdd, uint32_t NumberOfBlocks)
295 {
296   SDMMC_DataInitTypeDef config;
297   uint32_t errorstate;
298   uint32_t DmaBase0_reg, DmaBase1_reg;
299   uint32_t add = BlockAdd;
300 
301   if(hsd->State == HAL_SD_STATE_READY)
302   {
303     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
304     {
305       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
306       return HAL_ERROR;
307     }
308 
309     DmaBase0_reg = hsd->Instance->IDMABASE0;
310     DmaBase1_reg = hsd->Instance->IDMABASE1;
311     if ((hsd->Instance->IDMABSIZE == 0U) || (DmaBase0_reg == 0U) || (DmaBase1_reg == 0U))
312     {
313       hsd->ErrorCode = HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
314       return HAL_ERROR;
315     }
316 
317     /* Initialize data control register */
318     hsd->Instance->DCTRL = 0;
319 
320     hsd->ErrorCode = HAL_SD_ERROR_NONE;
321     hsd->State = HAL_SD_STATE_BUSY;
322 
323     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
324     {
325       add *= 512U;
326     }
327 
328     /* Configure the SD DPSM (Data Path State Machine) */
329     config.DataTimeOut   = SDMMC_DATATIMEOUT;
330     config.DataLength    = BLOCKSIZE * NumberOfBlocks;
331     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
332     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
333     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
334     config.DPSM          = SDMMC_DPSM_DISABLE;
335     (void)SDMMC_ConfigData(hsd->Instance, &config);
336 
337     hsd->Instance->DCTRL |= SDMMC_DCTRL_FIFORST;
338 
339     /* Set Block Size for Card */
340     errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
341     if(errorstate != HAL_SD_ERROR_NONE)
342     {
343       hsd->State = HAL_SD_STATE_READY;
344       hsd->ErrorCode |= errorstate;
345       return HAL_ERROR;
346     }
347 
348     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
349 
350     hsd->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_DOUBLE_BUFF0;
351 
352      __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND | SDMMC_IT_IDMABTC));
353 
354     /* Read Blocks in DMA mode */
355     hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
356 
357     /* Read Multi Block command */
358     errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
359     if(errorstate != HAL_SD_ERROR_NONE)
360     {
361       hsd->State = HAL_SD_STATE_READY;
362       hsd->ErrorCode |= errorstate;
363       return HAL_ERROR;
364     }
365 
366     return HAL_OK;
367   }
368   else
369   {
370     return HAL_BUSY;
371   }
372 
373 }
374 
375 /**
376   * @brief  Write block(s) to a specified address in a card. The transfered Data are stored in Buffer0 and Buffer1.
377   *         Buffer0, Buffer1 and BufferSize need to be configured by function HAL_SDEx_ConfigDMAMultiBuffer before call this function.
378   * @param  hsd: SD handle
379   * @param  BlockAdd: Block Address from where data is to be read
380   * @param  NumberOfBlocks: Total number of blocks to read
381   * @retval HAL status
382 */
HAL_SDEx_WriteBlocksDMAMultiBuffer(SD_HandleTypeDef * hsd,uint32_t BlockAdd,uint32_t NumberOfBlocks)383 HAL_StatusTypeDef HAL_SDEx_WriteBlocksDMAMultiBuffer(SD_HandleTypeDef *hsd, uint32_t BlockAdd, uint32_t NumberOfBlocks)
384 {
385   SDMMC_DataInitTypeDef config;
386   uint32_t errorstate;
387   uint32_t DmaBase0_reg, DmaBase1_reg;
388   uint32_t add = BlockAdd;
389 
390   if(hsd->State == HAL_SD_STATE_READY)
391   {
392     if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
393     {
394       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
395       return HAL_ERROR;
396     }
397 
398     DmaBase0_reg = hsd->Instance->IDMABASE0;
399     DmaBase1_reg = hsd->Instance->IDMABASE1;
400     if ((hsd->Instance->IDMABSIZE == 0U) || (DmaBase0_reg == 0U) || (DmaBase1_reg == 0U))
401     {
402       hsd->ErrorCode = HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
403       return HAL_ERROR;
404     }
405 
406     /* Initialize data control register */
407     hsd->Instance->DCTRL = 0;
408 
409     hsd->ErrorCode = HAL_SD_ERROR_NONE;
410 
411     hsd->State = HAL_SD_STATE_BUSY;
412 
413     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
414     {
415       add *= 512U;
416     }
417 
418     /* Configure the SD DPSM (Data Path State Machine) */
419     config.DataTimeOut   = SDMMC_DATATIMEOUT;
420     config.DataLength    = BLOCKSIZE * NumberOfBlocks;
421     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
422     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
423     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
424     config.DPSM          = SDMMC_DPSM_DISABLE;
425     (void)SDMMC_ConfigData(hsd->Instance, &config);
426 
427     /* Set Block Size for Card */
428     errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
429     if(errorstate != HAL_SD_ERROR_NONE)
430     {
431       hsd->State = HAL_SD_STATE_READY;
432       hsd->ErrorCode |= errorstate;
433       return HAL_ERROR;
434     }
435 
436     __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
437 
438     hsd->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_DOUBLE_BUFF0;
439 
440     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND | SDMMC_IT_IDMABTC));
441 
442     /* Write Blocks in DMA mode */
443     hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
444 
445     /* Write Multi Block command */
446     errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
447     if(errorstate != HAL_SD_ERROR_NONE)
448     {
449       hsd->State = HAL_SD_STATE_READY;
450       hsd->ErrorCode |= errorstate;
451       return HAL_ERROR;
452     }
453 
454     return HAL_OK;
455   }
456   else
457   {
458     return HAL_BUSY;
459   }
460 }
461 
462 
463 /**
464   * @brief  Change the DMA Buffer0 or Buffer1 address on the fly.
465   * @param  hsd:           pointer to a SD_HandleTypeDef structure.
466   * @param  Buffer:        the buffer to be changed, This parameter can be one of
467   *                        the following values: SD_DMA_BUFFER0 or SD_DMA_BUFFER1
468   * @param  pDataBuffer:   The new address
469   * @note   The BUFFER0 address can be changed only when the current transfer use
470   *         BUFFER1 and the BUFFER1 address can be changed only when the current
471   *         transfer use BUFFER0.
472   * @retval HAL status
473   */
HAL_SDEx_ChangeDMABuffer(SD_HandleTypeDef * hsd,HAL_SDEx_DMABuffer_MemoryTypeDef Buffer,uint32_t * pDataBuffer)474 HAL_StatusTypeDef HAL_SDEx_ChangeDMABuffer(SD_HandleTypeDef *hsd, HAL_SDEx_DMABuffer_MemoryTypeDef Buffer, uint32_t *pDataBuffer)
475 {
476   if(Buffer == SD_DMA_BUFFER0)
477   {
478     /* change the buffer0 address */
479     hsd->Instance->IDMABASE0 = (uint32_t)pDataBuffer;
480   }
481   else
482   {
483     /* change the memory1 address */
484     hsd->Instance->IDMABASE1 = (uint32_t)pDataBuffer;
485   }
486 
487   return HAL_OK;
488 }
489 
490 /**
491   * @brief Read DMA Buffer 0 Transfer completed callbacks
492   * @param hsd: SD handle
493   * @retval None
494   */
HAL_SDEx_Read_DMADoubleBuffer0CpltCallback(SD_HandleTypeDef * hsd)495 __weak void HAL_SDEx_Read_DMADoubleBuffer0CpltCallback(SD_HandleTypeDef *hsd)
496 {
497   /* Prevent unused argument(s) compilation warning */
498   UNUSED(hsd);
499 
500   /* NOTE : This function should not be modified, when the callback is needed,
501             the HAL_SDEx_Read_DMADoubleBuffer0CpltCallback can be implemented in the user file
502    */
503 }
504 
505 /**
506   * @brief Read DMA Buffer 1 Transfer completed callbacks
507   * @param hsd: SD handle
508   * @retval None
509   */
HAL_SDEx_Read_DMADoubleBuffer1CpltCallback(SD_HandleTypeDef * hsd)510 __weak void HAL_SDEx_Read_DMADoubleBuffer1CpltCallback(SD_HandleTypeDef *hsd)
511 {
512   /* Prevent unused argument(s) compilation warning */
513   UNUSED(hsd);
514 
515   /* NOTE : This function should not be modified, when the callback is needed,
516             the HAL_SDEx_Read_DMADoubleBuffer1CpltCallback can be implemented in the user file
517    */
518 }
519 
520 /**
521   * @brief Write DMA Buffer 0 Transfer completed callbacks
522   * @param hsd: SD handle
523   * @retval None
524   */
HAL_SDEx_Write_DMADoubleBuffer0CpltCallback(SD_HandleTypeDef * hsd)525 __weak void HAL_SDEx_Write_DMADoubleBuffer0CpltCallback(SD_HandleTypeDef *hsd)
526 {
527   /* Prevent unused argument(s) compilation warning */
528   UNUSED(hsd);
529 
530   /* NOTE : This function should not be modified, when the callback is needed,
531             the HAL_SDEx_Write_DMADoubleBuffer0CpltCallback can be implemented in the user file
532    */
533 }
534 
535 /**
536   * @brief Write DMA Buffer 1 Transfer completed callbacks
537   * @param hsd: SD handle
538   * @retval None
539   */
HAL_SDEx_Write_DMADoubleBuffer1CpltCallback(SD_HandleTypeDef * hsd)540 __weak void HAL_SDEx_Write_DMADoubleBuffer1CpltCallback(SD_HandleTypeDef *hsd)
541 {
542   /* Prevent unused argument(s) compilation warning */
543   UNUSED(hsd);
544 
545   /* NOTE : This function should not be modified, when the callback is needed,
546             the HAL_SDEx_Write_DMADoubleBuffer0CpltCallback can be implemented in the user file
547    */
548 }
549 
550 /**
551   * @}
552   */
553 
554 /**
555   * @}
556   */
557 
558 #endif /* HAL_SD_MODULE_ENABLED */
559 
560 /**
561   * @}
562   */
563 
564 /**
565   * @}
566   */
567 
568 #endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */
569 
570 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
571