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>© 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