1 /**
2   ******************************************************************************
3   * @file    stm32u5xx_hal_sdio.c
4   * @author  MCD Application Team
5   * @brief   SDIO HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the Secure Digital Input Output (SDIO) peripheral:
8   *           + Initialization and de-initialization functions
9   *           + IO operation functions
10   *           + Peripheral Control functions
11   *           + Peripheral State functions
12   *
13   ******************************************************************************
14   * @attention
15   *
16   * Copyright (c) 2021 STMicroelectronics.
17   * All rights reserved.
18   *
19   * This software is licensed under terms that can be found in the LICENSE file
20   * in the root directory of this software component.
21   * If no LICENSE file comes with this software, it is provided AS-IS.
22   *
23   ******************************************************************************
24   @verbatim
25   ==============================================================================
26                         ##### How to use this driver #####
27   ==============================================================================
28   [..]
29     This driver implements a high level communication layer for read and write from/to
30     this SDIO card. The needed STM32 hardware resources (SDMMC and GPIO) are performed by
31     the user in HAL_SDIO_MspInit() function (MSP layer).
32     Basically, the MSP layer configuration should be the same as we provide in the
33     examples.
34     You can easily tailor this configuration according to hardware resources.
35 
36   [..]
37     This driver is a generic layered driver for SDMMC memories which uses the HAL
38     SDMMC driver functions to interface with SDIO cards devices.
39     It is used as follows:
40 
41     (#)Initialize the SDMMC low level resources by implementing the HAL_SDIO_MspInit() API:
42         (##) Enable the SDMMC interface clock using __HAL_RCC_SDMMC_CLK_ENABLE();
43         (##) SDMMC pins configuration for SDIO card
44             (+++) Enable the clock for the SDMMC GPIOs using the functions __HAL_RCC_GPIOx_CLK_ENABLE();
45             (+++) Configure these SDMMC pins as alternate function pull-up using HAL_GPIO_Init()
46                   and according to your pin assignment;
47         (##) NVIC configuration if you need to use interrupt process (HAL_SDIO_ReadExtended_DMA()
48              and HAL_SDIO_WriteExtended_DMA() APIs).
49             (+++) Configure the SDMMC interrupt priorities using function HAL_NVIC_SetPriority();
50             (+++) Enable the NVIC SDMMC IRQs using function HAL_NVIC_EnableIRQ()
51             (+++) SDMMC interrupts are managed using the macros __HAL_SDIO_ENABLE_IT()
52                   and __HAL_SDIO_DISABLE_IT() inside the communication process.
53             (+++) SDMMC interrupts pending bits are managed using the macros __HAL_SDIO_GET_IT().
54         (##) No general propose DMA Configuration is needed, an Internal DMA for SDMMC Peripheral are used.
55 
56     (#) At this stage, you can perform SDIO read/write/erase operations after SDIO card initialization.
57 
58   *** SDIO Card Initialization and configuration ***
59   ================================================
60   [..]
61     To initialize the SDIO Card, use the HAL_SDIO_Init() function. It Initializes
62     SDMMC Peripheral(STM32 side) and the SDIO Card, and put it into StandBy State (Ready for data transfer).
63     This function provide the following operations:
64 
65     (#) Apply the SDIO Card initialization process at 400KHz. You can change or adapt this
66         frequency by adjusting the "ClockDiv" field.
67         The SDIO Card frequency (SDMMC_CK) is computed as follows:
68 
69            SDMMC_CK = SDMMCCLK / (2 * ClockDiv)
70 
71         In initialization mode and according to the SDIO Card standard,
72         make sure that the SDMMC_CK frequency doesn't exceed 400KHz.
73 
74         This phase of initialization is done through SDMMC_Init() and
75         SDMMC_PowerState_ON() SDMMC low level APIs.
76 
77     (#) Initialize the SDIO card. The API used is HAL_SDIO_Init().
78         This phase allows the card initialization and identification.
79 
80     (#) Configure the SDIO Card Data transfer frequency. You can change or adapt this
81         frequency by adjusting the "ClockDiv" field by the API HAL_SDIO_ConfigFrequency().
82 
83     (#) Configure the SDIO Card in wide bus mode: 4-bits data by the API HAL_SDIO_SetDataBusWidth().
84 
85     (#) Configure the SDIO Card data block size by the API : HAL_SDIO_SetBlockSize().
86 
87     (#) Configure the SDIO Card speed mode by the API : HAL_SDIO_SetSpeedMode().
88 
89     (#) To custumize the SDIO Init card function for the enumeration card sequence, you can register a user callback
90         function by calling the HAL_SDIO_RegisterIdentifyCardCallback before the HAL_SDIO_Init() function.
91 
92   *** SDIO Card Read operation ***
93   ==============================
94   [..]
95     (+) You can read from SDIO card in polling mode by using function HAL_SDIO_ReadExtended().
96         This function support only 2048-bytes block length (the block size should be
97         chosen by using the API HAL_SDIO_SetBlockSize).
98 
99     (+) You can read from SDIO card in DMA mode by using function HAL_SDIO_ReadExtended_DMA().
100         This function support only 2048-bytes block length (the block size should be
101         chosen by using the API HAL_SDIO_SetBlockSize).
102         After this, you have to ensure that the transfer is done correctly.
103         You could also check the DMA transfer process through the SDIO Rx interrupt event.
104 
105   *** SDIO Card Write operation ***
106   ===============================
107   [..]
108     (+) You can write to SDIO card in polling mode by using function HAL_SDIO_WriteExtended().
109         This function support only 2048-bytes block length (the block size should be
110         chosen by using the API HAL_SDIO_SetBlockSize).
111 
112     (+) You can write to SDIO card in DMA mode by using function HAL_SDIO_WriteExtended_DMA().
113         This function support only 2048-bytes block length (the block size should be
114         chosen by using the API HAL_SDIO_SetBlockSize).
115         You could also check the DMA transfer process through the SDIO Tx interrupt event.
116 
117 
118   *** SDIO card common control register (CCCR) ***
119   ======================
120   [..]
121     (+) The SDIO CCCR allow for quick host checking and control of an IO card's enable and interrupts on a per card and
122         per function basis.
123         To get the Card common control registers field, you can use the API HAL_SDIO_GetCardCommonControlRegister().
124 
125   *** SDIO card Function basic register (FBR) ***
126   ===========================
127   [..]
128     (+) The SDIO card function basic register are used to allow the host to quickly determine the abilities and
129         requirements of each function.
130     (+) To get the SDIO function basic register information, you can use the API HAL_SDIO_GetCardFBRRegister().
131 
132   *** SDIO HAL driver macros list ***
133   ==================================
134   [..]
135     Below the list of most used macros in SDIO HAL driver.
136 
137     (+) __HAL_SDIO_ENABLE_IT: Enable the SDIO device interrupt
138     (+) __HAL_SDIO_DISABLE_IT: Disable the SDIO device interrupt
139     (+) __HAL_SDIO_GET_FLAG: Check whether the specified SDIO flag is set or not
140     (+) __HAL_SDIO_CLEAR_FLAG: Clear the SDIO's pending flags
141     (+) __HAL_SDIO_GET_IT: Check whether the specified SDIO interrupt has occurred or not
142     (+) __HAL_SDIO_GET_IT_SOURCE: Checks whether the specified SDIO interrupt is enabled or not
143 
144     (@) You can refer to the SDIO HAL driver header file for more useful macros
145 
146   *** Callback registration ***
147   =============================================
148   [..]
149     The compilation define USE_HAL_SDIO_REGISTER_CALLBACKS when set to 1
150     allows the user to configure dynamically the driver callbacks.
151 
152     Use Functions HAL_SDIO_RegisterCallback() to register a user callback,
153     it allows to register following callbacks:
154       (+) TxCpltCallback : callback when a transmission transfer is completed.
155       (+) RxCpltCallback : callback when a reception transfer is completed.
156       (+) ErrorCallback : callback when error occurs.
157       (+) MspInitCallback    : SDIO MspInit.
158       (+) MspDeInitCallback  : SDIO MspDeInit.
159     This function takes as parameters the HAL peripheral handle, the Callback ID
160     and a pointer to the user callback function.
161     For specific callbacks TransceiverCallback use dedicated register callbacks:
162     respectively HAL_SDIO_RegisterTransceiverCallback().
163 
164     Use function HAL_SDIO_UnRegisterCallback() to reset a callback to the default
165     weak (overridden) function. It allows to reset following callbacks:
166       (+) TxCpltCallback : callback when a transmission transfer is completed.
167       (+) RxCpltCallback : callback when a reception transfer is completed.
168       (+) ErrorCallback : callback when error occurs.
169       (+) MspInitCallback    : SDIO MspInit.
170       (+) MspDeInitCallback  : SDIO MspDeInit.
171     This function) takes as parameters the HAL peripheral handle and the Callback ID.
172     For specific callbacks TransceiverCallback use dedicated unregister callbacks:
173     respectively HAL_SDIO_UnRegisterTransceiverCallback().
174 
175     By default, after the HAL_SDIO_Init and if the state is HAL_SDIO_STATE_RESET
176     all callbacks are reset to the corresponding legacy weak (overridden) functions.
177     Exception done for MspInit and MspDeInit callbacks that are respectively
178     reset to the legacy weak (overridden) functions in the HAL_SDIO_Init
179     and HAL_SDIO_DeInit only when these callbacks are null (not registered beforehand).
180     If not, MspInit or MspDeInit are not null, the HAL_SDIO_Init and HAL_SDIO_DeInit
181     keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
182 
183     Callbacks can be registered/unregistered in READY state only.
184     Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
185     in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
186     during the Init/DeInit.
187     In that case first register the MspInit/MspDeInit user callbacks
188     using HAL_SDIO_RegisterCallback before calling HAL_SDIO_DeInit
189     or HAL_SDIO_Init function.
190 
191     When The compilation define USE_HAL_SDIO_REGISTER_CALLBACKS is set to 0 or
192     not defined, the callback registering feature is not available
193     and weak (overridden) callbacks are used.
194 
195   *** SDIO peripheral IO interrupt ***
196   =============================================
197   [..]
198   (+) Below the list of most used SDIO function to check and control the IO card's enable and interrupts on a per
199       functions basis.
200 
201     (+) HAL_SDIO_EnableIOFunctionInterrupt: Enable SDIO IO interrupt.
202     (+) HAL_SDIO_DisableIOFunctionInterrupt: Disable SDIO IO interrupt.
203     (+) HAL_SDIO_EnableIOFunction: Enable Function number(0-7)
204     (+) HAL_SDIO_DisableIOFunction: Disable Function number(0-7)
205     (+) HAL_SDIO_SelectIOFunction: Select a function number(0-7)
206     (+) HAL_SDIO_AbortIOFunction: Abort an IO read or write operation and free the SDIO bus.
207     (+) HAL_SDIO_EnableIOAsynInterrupt: Enable Bit of asynchronous interrupt
208     (+) HAL_SDIO_DisableIOAsynInterrupt: Disable Bit of asynchronous interrupt
209 
210   @endverbatim
211   ******************************************************************************
212   */
213 
214 /* Includes ----------------------------------------------------------------------------------------------------------*/
215 #include "stm32u5xx_hal.h"
216 
217 /** @addtogroup STM32U5xx_HAL_Driver
218   * @{
219   */
220 
221 /** @addtogroup SDIO
222   * @{
223   */
224 #if defined (SDMMC1) || defined (SDMMC2)
225 #ifdef HAL_SDIO_MODULE_ENABLED
226 
227 /* Private define ----------------------------------------------------------------------------------------------------*/
228 /** @addtogroup SDIO_Private_Defines
229   * @{
230   */
231 #define SDIO_INIT_FREQ         400000U /*!< Initialization phase : 400 kHz max */
232 #define SDIO_TIMEOUT           1000U   /*!< SDIO timeout millisecond           */
233 
234 #define SDIO_FUNCTION_0        0x00U   /*!< SDIO_Functions 0                   */
235 #define SDIO_FUNCTION_1        0x01U   /*!< SDIO_Functions 1                   */
236 
237 #define SDIO_READ              0x0U    /*!< Read flag for cmd52 and cmd53      */
238 #define SDIO_WRITE             0x1U    /*!< Write flag for cmd52 and cmd53     */
239 
240 #define SDIO_BUS_SPEED_SDR12   0x00U   /*!< SDIO bus speed mode SDR12          */
241 #define SDIO_BUS_SPEED_SDR25   0x02U   /*!< SDIO bus speed mode SDR25          */
242 #define SDIO_BUS_SPEED_SDR50   0x04U   /*!< SDIO bus speed mode SDR50          */
243 #define SDIO_BUS_SPEED_DDR50   0x08U   /*!< SDIO bus speed mode DDR50          */
244 
245 #define SDIO_CCCR_REG_NUMBER   0x16U   /*!< SDIO card cccr register number     */
246 
247 #define SDIO_OCR_VDD_32_33     (1U << 20U)
248 #define SDIO_OCR_SDIO_S18R     (1U << 24U)
249 /**
250   * @}
251   */
252 
253 /* Private macro -----------------------------------------------------------------------------------------------------*/
254 #define IS_SDIO_RAW_FLAG(ReadAfterWrite)   (((ReadAfterWrite) == HAL_SDIO_WRITE_ONLY) || \
255                                             ((ReadAfterWrite) == HAL_SDIO_READ_AFTER_WRITE))
256 
257 #define IS_SDIO_FUNCTION(FN)        (((FN) >= HAL_SDIO_FUNCTION_1) && ((FN) <= HAL_SDIO_FUNCTION_7))
258 
259 #define IS_SDIO_SUPPORTED_BLOCK_SIZE(BLOCKSIZE) (((BLOCKSIZE) == HAL_SDIO_DATA_BLOCK_SIZE_1BYTE)    || \
260                                                  ((BLOCKSIZE) == HAL_SDIO_DATA_BLOCK_SIZE_2BYTE)    || \
261                                                  ((BLOCKSIZE) == HAL_SDIO_DATA_BLOCK_SIZE_4BYTE)    || \
262                                                  ((BLOCKSIZE) == HAL_SDIO_DATA_BLOCK_SIZE_8BYTE)    || \
263                                                  ((BLOCKSIZE) == HAL_SDIO_DATA_BLOCK_SIZE_16BYTE)   || \
264                                                  ((BLOCKSIZE) == HAL_SDIO_DATA_BLOCK_SIZE_32BYTE)   || \
265                                                  ((BLOCKSIZE) == HAL_SDIO_DATA_BLOCK_SIZE_64BYTE)   || \
266                                                  ((BLOCKSIZE) == HAL_SDIO_DATA_BLOCK_SIZE_128BYTE)  || \
267                                                  ((BLOCKSIZE) == HAL_SDIO_DATA_BLOCK_SIZE_256BYTE)  || \
268                                                  ((BLOCKSIZE) == HAL_SDIO_DATA_BLOCK_SIZE_512BYTE)  || \
269                                                  ((BLOCKSIZE) == HAL_SDIO_DATA_BLOCK_SIZE_1024BYTE) || \
270                                                  ((BLOCKSIZE) == HAL_SDIO_DATA_BLOCK_SIZE_2048BYTE))
271 
272 /* Private functions -------------------------------------------------------------------------------------------------*/
273 /** @defgroup SDIO_Private_Functions SDIO Private Functions
274   * @{
275   */
276 static HAL_StatusTypeDef SDIO_InitCard(SDIO_HandleTypeDef *hsdio);
277 static HAL_StatusTypeDef SDIO_ReadDirect(SDIO_HandleTypeDef *hsdio, uint32_t addr, uint32_t raw, uint32_t function_nbr,
278                                          uint8_t *pData);
279 static HAL_StatusTypeDef SDIO_WriteDirect(SDIO_HandleTypeDef *hsdio, uint32_t addr, uint32_t raw, uint32_t function_nbr,
280                                           uint8_t *pData);
281 static HAL_StatusTypeDef SDIO_WriteExtended(SDIO_HandleTypeDef *hsdio, HAL_SDIO_ExtendedCmd_TypeDef *cmd_arg,
282                                             uint8_t *pData, uint16_t Size_byte);
283 static uint8_t SDIO_Convert_Block_Size(SDIO_HandleTypeDef *hsdio, uint32_t block_size);
284 static HAL_StatusTypeDef SDIO_IOFunction_IRQHandler(SDIO_HandleTypeDef *hsdio);
285 /**
286   * @}
287   */
288 
289 /* Exported functions --------------------------------------------------------*/
290 /** @addtogroup SDIO_Exported_Functions
291   * @{
292   */
293 /** @addtogroup SDIO_Exported_Functions_Group1
294   *  @brief   Initialization and de-initialization functions
295   *
296 @verbatim
297   ==============================================================================
298           ##### Initialization and de-initialization functions #####
299   ==============================================================================
300   [..]
301     This section provides functions allowing to initialize/de-initialize the SDIO
302     device to be ready for use.
303 
304 @endverbatim
305   * @{
306   */
307 /**
308   * @brief  Initializes the SDIO according to the specified parameters in the
309             SDIO_HandleTypeDef and create the associated handle.
310   * @param  hsdio: Pointer to the SDIO handle
311   * @retval HAL status
312   */
HAL_SDIO_Init(SDIO_HandleTypeDef * hsdio)313 HAL_StatusTypeDef HAL_SDIO_Init(SDIO_HandleTypeDef *hsdio)
314 {
315   SDIO_InitTypeDef Init;
316   uint32_t sdmmc_clk;
317   uint8_t data;
318 
319   /* Check the parameters */
320   assert_param(hsdio != NULL);
321   assert_param(IS_SDMMC_ALL_INSTANCE(hsdio->Instance));
322   assert_param(IS_SDMMC_CLOCK_EDGE(hsdio->Init.ClockEdge));
323   assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hsdio->Init.ClockPowerSave));
324   assert_param(IS_SDMMC_BUS_WIDE(hsdio->Init.BusWide));
325   assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hsdio->Init.HardwareFlowControl));
326   assert_param(IS_SDMMC_CLKDIV(hsdio->Init.ClockDiv));
327 
328   /* Check the SDIO handle allocation */
329   if (hsdio == NULL)
330   {
331     return HAL_ERROR;
332   }
333 
334   if (hsdio->State == HAL_SDIO_STATE_RESET)
335   {
336 #if defined (USE_HAL_SDIO_REGISTER_CALLBACKS) && (USE_HAL_SDIO_REGISTER_CALLBACKS == 1U)
337     /* Reset Callback pointers in HAL_SDIO_STATE_RESET only */
338     hsdio->TxCpltCallback = HAL_SDIO_TxCpltCallback;
339     hsdio->RxCpltCallback = HAL_SDIO_RxCpltCallback;
340     hsdio->ErrorCallback  = HAL_SDIO_ErrorCallback;
341 #if (USE_SDIO_TRANSCEIVER != 0U)
342     if (hsdio->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
343     {
344       hsdio->DriveTransceiver_1_8V_Callback = HAL_SDIO_DriveTransceiver_1_8V_Callback;
345     }
346 #endif /* USE_SDIO_TRANSCEIVER */
347 
348     if (hsdio->MspInitCallback == NULL)
349     {
350       hsdio->MspInitCallback = HAL_SDIO_MspInit;
351     }
352     /* Init the low level hardware */
353     hsdio->MspInitCallback(hsdio);
354 #else
355     /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
356     HAL_SDIO_MspInit(hsdio);
357 #endif /* USE_HAL_SDIO_REGISTER_CALLBACKS */
358   }
359 
360   Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;
361   Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;
362   Init.BusWide             = SDMMC_BUS_WIDE_1B;
363   Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
364 
365   sdmmc_clk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC);
366   if (sdmmc_clk == 0U)
367   {
368     hsdio->ErrorCode = SDMMC_ERROR_INVALID_PARAMETER;
369     return HAL_ERROR;
370   }
371   Init.ClockDiv = sdmmc_clk / (2U * SDIO_INIT_FREQ);
372   /* Initialize SDMMC peripheral interface with default configuration */
373   (void)SDMMC_Init(hsdio->Instance, Init);
374 
375   /* Set Power State to ON */
376   (void)SDMMC_PowerState_ON(hsdio->Instance);
377 
378   /* wait 74 Cycles: required power up waiting time before starting the SDIO initialization sequence */
379   sdmmc_clk = sdmmc_clk / (2U * Init.ClockDiv);
380   HAL_Delay(1U + (74U * 1000U / (sdmmc_clk)));
381 
382   if (hsdio->SDIO_IdentifyCard == NULL)
383   {
384     hsdio->SDIO_IdentifyCard = SDIO_InitCard;
385   }
386   /* SDIO enumeration sequence */
387   if (hsdio->SDIO_IdentifyCard(hsdio) != HAL_OK)
388   {
389     hsdio->State = HAL_SDIO_STATE_RESET;
390     return HAL_ERROR;
391   }
392 
393   /* Configure the SDMMC user parameters */
394   Init.ClockEdge           = hsdio->Init.ClockEdge;
395   Init.ClockPowerSave      = hsdio->Init.ClockPowerSave;
396   Init.BusWide             = hsdio->Init.BusWide;
397   Init.HardwareFlowControl = hsdio->Init.HardwareFlowControl;
398   Init.ClockDiv            = hsdio->Init.ClockDiv;
399   (void)SDMMC_Init(hsdio->Instance, Init);
400 
401   data = (hsdio->Init.BusWide == HAL_SDIO_4_WIRES_MODE) ? 2U : 0U;
402   if (SDIO_WriteDirect(hsdio, SDMMC_SDIO_CCCR4_SD_BYTE3, HAL_SDIO_WRITE_ONLY, SDIO_FUNCTION_0, &data) != HAL_OK)
403   {
404     return HAL_ERROR;
405   }
406 
407   hsdio->Context = SDIO_CONTEXT_NONE;
408   hsdio->State = HAL_SDIO_STATE_READY;
409 
410   return HAL_OK;
411 }
412 
413 /**
414   * @brief  De-Initializes the SDIO device.
415   * @param  hsdio: Pointer to the SDIO handle
416   * @retval HAL status
417   */
HAL_SDIO_DeInit(SDIO_HandleTypeDef * hsdio)418 HAL_StatusTypeDef HAL_SDIO_DeInit(SDIO_HandleTypeDef *hsdio)
419 {
420   /* Check the parameters */
421   assert_param(IS_SDMMC_ALL_INSTANCE(hsdio->Instance));
422 
423   /* Check the SDIO handle allocation */
424   if (hsdio == NULL)
425   {
426     return HAL_ERROR;
427   }
428 
429   /* Set Power State to OFF */
430   (void)SDMMC_PowerState_OFF(hsdio->Instance);
431 
432 #if defined (USE_HAL_SDIO_REGISTER_CALLBACKS) && (USE_HAL_SDIO_REGISTER_CALLBACKS == 1U)
433   if (hsdio->MspDeInitCallback == NULL)
434   {
435     hsdio->MspDeInitCallback = HAL_SDIO_MspDeInit;
436   }
437 
438   /* DeInit the low level hardware */
439   hsdio->MspDeInitCallback(hsdio);
440 #else
441   /* De-Initialize the MSP layer */
442   HAL_SDIO_MspDeInit(hsdio);
443 #endif /* USE_HAL_SDIO_REGISTER_CALLBACKS */
444 
445   hsdio->ErrorCode = HAL_SDIO_ERROR_NONE;
446   hsdio->State = HAL_SDIO_STATE_RESET;
447 
448   return HAL_OK;
449 }
450 
451 /**
452   * @brief  Initializes the SDIO MSP.
453   * @param  hsdio: Pointer to SDIO handle
454   * @retval None
455   */
HAL_SDIO_MspInit(SDIO_HandleTypeDef * hsdio)456 __weak void HAL_SDIO_MspInit(SDIO_HandleTypeDef *hsdio)
457 {
458   /* Prevent unused argument(s) compilation warning */
459   UNUSED(hsdio);
460 
461   /* NOTE : This function should not be modified, when the callback is needed,
462             the HAL_SDIO_MspInit could be implemented in the user file
463    */
464 }
465 
466 /**
467   * @brief  De-Initialize SDIO MSP.
468   * @param  hsdio: Pointer to SDIO handle
469   * @retval None
470   */
HAL_SDIO_MspDeInit(SDIO_HandleTypeDef * hsdio)471 __weak void HAL_SDIO_MspDeInit(SDIO_HandleTypeDef *hsdio)
472 {
473   /* Prevent unused argument(s) compilation warning */
474   UNUSED(hsdio);
475 
476   /* NOTE : This function should not be modified, when the callback is needed,
477             the HAL_SDIO_MspDeInit could be implemented in the user file
478    */
479 }
480 /**
481   * @}
482   */
483 
484 /** @addtogroup SDIO_Exported_Functions_Group2
485   *  @brief
486   *
487 @verbatim
488   ==============================================================================
489           ##### Initialization and de-initialization functions #####
490   ==============================================================================
491   [..]
492     This subsection provides a set of functions allowing to re-configure the SDIO peripheral.
493 
494 @endverbatim
495   * @{
496   */
497 /**
498   * @brief  Enables wide bus operation for the requested card if supported by card.
499   * @param  hsdio: Pointer to SDIO handle
500   * @param  BusWide: Specifies the SDIO card wide bus mode
501   *          This parameter can be one of the following values:
502   *            @arg SDMMC_BUS_WIDE_8B: 8-bit data transfer
503   *            @arg SDMMC_BUS_WIDE_4B: 4-bit data transfer
504   *            @arg SDMMC_BUS_WIDE_1B: 1-bit data transfer
505   * @retval HAL status
506   */
HAL_SDIO_SetDataBusWidth(SDIO_HandleTypeDef * hsdio,uint32_t BusWide)507 HAL_StatusTypeDef HAL_SDIO_SetDataBusWidth(SDIO_HandleTypeDef *hsdio, uint32_t BusWide)
508 {
509   uint8_t data;
510   HAL_StatusTypeDef error_state = HAL_OK;
511 
512   /* Check the parameters */
513   assert_param(hsdio != NULL);
514 
515   /* Check the SDIO peripheral handle parameter */
516   if (hsdio == NULL)
517   {
518     return HAL_ERROR;
519   }
520 
521   if (hsdio->State == HAL_SDIO_STATE_READY)
522   {
523     data = (BusWide == HAL_SDIO_4_WIRES_MODE) ? 2U : 0U;
524     MODIFY_REG(hsdio->Instance->CLKCR, SDMMC_CLKCR_WIDBUS,
525                (BusWide == HAL_SDIO_4_WIRES_MODE) ? SDMMC_BUS_WIDE_4B : SDMMC_BUS_WIDE_1B);
526 
527     if (SDIO_WriteDirect(hsdio, SDMMC_SDIO_CCCR4_SD_BYTE3, HAL_SDIO_WRITE_ONLY, SDIO_FUNCTION_0, &data) != HAL_OK)
528     {
529       error_state =  HAL_ERROR;
530     }
531   }
532   else
533   {
534     error_state =  HAL_ERROR;
535   }
536 
537   return error_state;
538 }
539 
540 /**
541   * @brief  Update the SDIO Clock.
542   * @param  hsdio: Pointer to SDIO handle.
543   * @param  ClockSpeed: SDIO Clock speed.
544   * @retval HAL status
545   */
HAL_SDIO_ConfigFrequency(SDIO_HandleTypeDef * hsdio,uint32_t ClockSpeed)546 HAL_StatusTypeDef HAL_SDIO_ConfigFrequency(SDIO_HandleTypeDef *hsdio, uint32_t ClockSpeed)
547 {
548   uint32_t ClockDiv;
549 
550   /* Check the parameters */
551   assert_param(hsdio != NULL);
552 
553   /* Check the SDIO peripheral handle parameter */
554   if (hsdio == NULL)
555   {
556     return HAL_ERROR;
557   }
558 
559   if (hsdio->State == HAL_SDIO_STATE_READY)
560   {
561     ClockDiv = (HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC)) / (2U * ClockSpeed);
562     MODIFY_REG(hsdio->Instance->CLKCR, SDMMC_CLKCR_CLKDIV, ClockDiv);
563   }
564   else
565   {
566     return HAL_ERROR;
567   }
568 
569   return HAL_OK;
570 }
571 
572 /**
573   * @brief  Set the SDIO block size.
574   * @param  hsdio: Pointer to SDIO handle
575   * @param  function_nbr: Specifies the SDIO function number.
576   * @param  BlockSize: Specifies the SDIO Block size to set.
577   *         This parameter can be one of the following values @ref SDIO_Exported_Constansts_Group7.
578   * @retval HAL status
579   */
HAL_SDIO_SetBlockSize(SDIO_HandleTypeDef * hsdio,uint8_t function_nbr,uint16_t BlockSize)580 HAL_StatusTypeDef HAL_SDIO_SetBlockSize(SDIO_HandleTypeDef *hsdio, uint8_t function_nbr, uint16_t BlockSize)
581 {
582   HAL_SDIO_ExtendedCmd_TypeDef cmd53;
583 
584   /* Check the parameters */
585   assert_param(hsdio != NULL);
586   assert_param(IS_SDIO_FUNCTION(function_nbr));
587   assert_param(IS_SDIO_SUPPORTED_BLOCK_SIZE(BlockSize));
588 
589   /* Check the SDIO peripheral handle parameter */
590   if (hsdio == NULL)
591   {
592     return HAL_ERROR;
593   }
594 
595   /* Set SDIO F1 block size */
596   cmd53.IOFunctionNbr = SDIO_FUNCTION_0;
597   cmd53.OpCode = HAL_SDIO_OP_CODE_AUTO_INC;
598   cmd53.Block_Mode = HAL_SDIO_MODE_BYTE;
599   cmd53.Reg_Addr = (function_nbr * 0x100UL) + 0x10UL;
600   if (SDIO_WriteExtended(hsdio, &cmd53, (uint8_t *)(&BlockSize), 2U) != HAL_OK)
601   {
602     return HAL_ERROR;
603   }
604 
605   hsdio->block_size = BlockSize;
606 
607   return HAL_OK;
608 }
609 
610 /**
611   * @brief  Configure the data rate.
612   * @param  hsdio: Pointer to SDIO handle
613   * @param  DataRate: Specifies the SDIO data rate to set.
614   * @retval HAL status
615   */
HAL_SDIO_SetSpeedMode(SDIO_HandleTypeDef * hsdio,uint32_t DataRate)616 HAL_StatusTypeDef HAL_SDIO_SetSpeedMode(SDIO_HandleTypeDef *hsdio, uint32_t DataRate)
617 {
618   HAL_StatusTypeDef errorstate = HAL_OK;
619   uint8_t data;
620 
621   /* Check the parameters */
622   assert_param(hsdio != NULL);
623 
624   /* Check the SDIO peripheral handle parameter */
625   if (hsdio == NULL)
626   {
627     return HAL_ERROR;
628   }
629 
630   switch (DataRate)
631   {
632     case HAL_SDIOS_DATA_RATE_SDR25:
633       data = SDIO_BUS_SPEED_SDR25;
634       errorstate = SDIO_WriteDirect(hsdio, SDMMC_SDIO_CCCR16_SD_BYTE3, HAL_SDIO_WRITE_ONLY, SDIO_FUNCTION_0, &data);
635       break;
636 
637     case HAL_SDIOS_DATA_RATE_SDR50:
638       data = SDIO_BUS_SPEED_SDR50;
639       errorstate = SDIO_WriteDirect(hsdio, ((SDIO_FUNCTION_0 << 2U) | (SDIO_FUNCTION_0 << 1U) | (SDIO_FUNCTION_0 << 14U)
640                                             | SDMMC_SDIO_CCCR16_SD_BYTE3), HAL_SDIO_WRITE_ONLY, SDIO_FUNCTION_0, &data);
641       MODIFY_REG(hsdio->Instance->CLKCR, SDMMC_CLKCR_BUSSPEED, SDMMC_CLKCR_BUSSPEED);
642       break;
643 
644     case HAL_SDIOS_DATA_RATE_DDR50:
645       data = SDIO_BUS_SPEED_DDR50;
646       errorstate = SDIO_WriteDirect(hsdio, ((SDIO_FUNCTION_0 << 2) | (SDIO_FUNCTION_0 << 1) | (SDIO_FUNCTION_0 << 14) |
647                                             SDMMC_SDIO_CCCR16_SD_BYTE3), HAL_SDIO_WRITE_ONLY, SDIO_FUNCTION_0, &data);
648       MODIFY_REG(hsdio->Instance->CLKCR, SDMMC_CLKCR_DDR | SDMMC_CLKCR_BUSSPEED,
649                  SDMMC_CLKCR_DDR | SDMMC_CLKCR_BUSSPEED);
650       break;
651     default: /* SDR12 */
652       break;
653   }
654 
655   return (errorstate != HAL_OK) ? HAL_ERROR : HAL_OK;
656 }
657 
658 /**
659   * @brief  Reset SDIO Card
660   * @param  hsdio: Pointer to SDIO handle
661   * @retval HAL status
662   */
HAL_SDIO_CardReset(SDIO_HandleTypeDef * hsdio)663 HAL_StatusTypeDef HAL_SDIO_CardReset(SDIO_HandleTypeDef *hsdio)
664 {
665   uint8_t data = 0U;
666 
667   /* Check the parameters */
668   assert_param(hsdio != NULL);
669 
670   /* Check the SDIO peripheral handle parameter */
671   if (hsdio == NULL)
672   {
673     return HAL_ERROR;
674   }
675 
676   /**  To reset the SDIO module by CMD52 with writing to RES in CCCR or send CMD0 the card shall change the speed mode
677     *  default speed mode.
678     *  The reset cmd (cmd0) is only used for memory. In order to reset an I/O card or the I/O portion of a combo card,
679     *  Use CMD52 to write 1 to the RES bit in the CCC(bit3 of register 6).
680     */
681   if (SDIO_WriteDirect(hsdio, ((SDIO_FUNCTION_0 << 2) | (SDIO_FUNCTION_0 << 1) | (SDIO_FUNCTION_0 << 14) |
682                                SDMMC_SDIO_CCCR4_SD_BYTE2),
683                        HAL_SDIO_WRITE_ONLY,
684                        0U,
685                        &data) != HAL_OK)
686   {
687     return HAL_ERROR;
688   }
689 
690   hsdio->State = HAL_SDIO_STATE_RESET;
691 
692   return HAL_OK;
693 }
694 
695 /**
696   * @brief  Get Card Common Control register (CCCR).
697   * @param  hsdio: Pointer to SDIO handle.
698   * @param  pCccr: Pointer to Cccr register.
699   * @retval HAL status
700   */
HAL_SDIO_GetCardCommonControlRegister(SDIO_HandleTypeDef * hsdio,HAL_SDIO_CCCR_TypeDef * pCccr)701 HAL_StatusTypeDef HAL_SDIO_GetCardCommonControlRegister(SDIO_HandleTypeDef *hsdio, HAL_SDIO_CCCR_TypeDef *pCccr)
702 {
703   uint8_t tempBuffer[256] = {0U};
704   uint32_t count;
705 
706   assert_param(hsdio != NULL);
707   assert_param(pCccr != NULL);
708 
709   if ((hsdio == NULL) || (pCccr == NULL))
710   {
711     return HAL_ERROR;
712   }
713 
714   for (count = 0U; count <= SDIO_CCCR_REG_NUMBER; count++)
715   {
716     if (SDIO_ReadDirect(hsdio, SDMMC_SDIO_CCCR0 + count, HAL_SDIO_WRITE_ONLY, SDIO_FUNCTION_0, &tempBuffer[count]) !=
717         HAL_OK)
718     {
719       return HAL_ERROR;
720     }
721   }
722 
723   pCccr->cccr_revision = tempBuffer[0] & 0x0FU;
724   pCccr->sdio_revision = (tempBuffer[0] & 0xF0U) >> 4U;
725   pCccr->sd_spec_revision = tempBuffer[0x01U] & 0x0FU;
726   pCccr->bus_width_8Bit = ((tempBuffer[0x07U] & 0x04U) != 0U) ? HAL_SDIO_BUS_WIDTH_8BIT_SUPPORTED
727                           : HAL_SDIO_BUS_WIDTH_8BIT_NOT_SUPPORTED;
728   pCccr->card_capability = (tempBuffer[0x08U] & 0xDFUL);
729   /* common CIS pointer */
730   pCccr->commonCISPointer = tempBuffer[0x09U] | ((uint32_t)tempBuffer[(uint32_t)0x09U + 1U] << 8U) |
731                             ((uint32_t)tempBuffer[(uint32_t)0x09U + 2U] << 16U);
732 
733   return HAL_OK;
734 }
735 
736 /**
737   * @brief  Get Card Function Basic register(FBR).
738   * @param  hsdio: Pointer to SDIO handle.
739   * @param  pFbr: Pointer to Fbr register.
740   * @retval HAL status
741   */
HAL_SDIO_GetCardFBRRegister(SDIO_HandleTypeDef * hsdio,HAL_SDIO_FBR_t * pFbr)742 HAL_StatusTypeDef HAL_SDIO_GetCardFBRRegister(SDIO_HandleTypeDef *hsdio, HAL_SDIO_FBR_t *pFbr)
743 {
744   uint8_t tempBuffer[256] = {0U};
745   uint32_t count;
746   uint8_t func_idx;
747 
748   assert_param(hsdio != NULL);
749   assert_param(pFbr != NULL);
750 
751   if ((hsdio == NULL) || (pFbr == NULL))
752   {
753     return HAL_ERROR;
754   }
755 
756   for (func_idx = 2U; func_idx <= SDIO_MAX_IO_NUMBER; func_idx++)
757   {
758     for (count = 0U; count <= SDIO_CCCR_REG_NUMBER; count++)
759     {
760       if (SDIO_ReadDirect(hsdio, (((uint32_t)SDMMC_SDIO_F1BR0 * (uint32_t)func_idx) + count),
761                           HAL_SDIO_WRITE_ONLY, SDIO_FUNCTION_0, &tempBuffer[count]) != HAL_OK)
762       {
763         return HAL_ERROR;
764       }
765     }
766     pFbr[(uint32_t)func_idx - 1U].ioStdFunctionCode = tempBuffer[0U] & 0x0FU;
767     pFbr[(uint32_t)func_idx - 1U].ioExtFunctionCode = tempBuffer[1U];
768     pFbr[(uint32_t)func_idx - 1U].ioPointerToCIS = tempBuffer[9U] | ((uint32_t)tempBuffer[10U] << 8U) |
769                                                    ((uint32_t)tempBuffer[11U] << 16U);
770     pFbr[(uint32_t)func_idx - 1U].ioPointerToCSA = tempBuffer[12U] | ((uint32_t)tempBuffer[13U] << 8U) |
771                                                    ((uint32_t)tempBuffer[14U] << 16U);
772     if ((tempBuffer[2U] & 0x01U) != 0U)
773     {
774       pFbr[(uint32_t)func_idx - 1U].flags |= (uint8_t)HAL_SDIO_FBR_SUPPORT_POWER_SELECTION;
775     }
776     if ((tempBuffer[0U] & 0x40U) != 0U)
777     {
778       pFbr[(uint32_t)func_idx - 1U].flags |= (uint8_t)HAL_SDIO_FBR_SUPPORT_CSA;
779     }
780   }
781 
782   return HAL_OK;
783 }
784 /**
785   * @}
786   */
787 
788 /** @addtogroup SDIO_Exported_Functions_Group3
789   *  @brief
790   *
791 @verbatim
792   ==============================================================================
793           ##### Data management functions #####
794   ==============================================================================
795   [..]
796     This subsection provides a set of functions allowing to manage the data transfer from/to SDIO card.
797 
798 @endverbatim
799   * @{
800   */
801 /**
802   * @brief  Read data from a specified address using the direct mode through cmd52.
803   * @param  hsdio: Pointer to SDIO handle
804   * @param  Argument: Specifies the SDIO Argument.
805   * @param  pData: pointer to the buffer that will contain the received data.
806   * @retval HAL status
807   */
HAL_SDIO_ReadDirect(SDIO_HandleTypeDef * hsdio,HAL_SDIO_DirectCmd_TypeDef * Argument,uint8_t * pData)808 HAL_StatusTypeDef HAL_SDIO_ReadDirect(SDIO_HandleTypeDef *hsdio, HAL_SDIO_DirectCmd_TypeDef *Argument, uint8_t *pData)
809 {
810   uint32_t cmd;
811   uint32_t errorstate;
812 
813   /* Check the parameters */
814   assert_param(hsdio != NULL);
815   assert_param(Argument != NULL);
816   assert_param(pData != NULL);
817   assert_param(IS_SDIO_RAW_FLAG(Argument->ReadAfterWrite));
818 
819   if ((hsdio == NULL) || (Argument == NULL) || (NULL == pData))
820   {
821     return HAL_ERROR;
822   }
823 
824   if (hsdio->State == HAL_SDIO_STATE_READY)
825   {
826     hsdio->ErrorCode = HAL_SDIO_ERROR_NONE;
827     hsdio->State = HAL_SDIO_STATE_BUSY;
828 
829     cmd = SDIO_READ << 31U;
830     cmd |= (((uint32_t)Argument->IOFunctionNbr) << 28U);
831     cmd |= (((uint32_t)Argument->ReadAfterWrite) << 27U);
832     cmd |= (Argument->Reg_Addr & 0x1FFFFU) << 9U;
833     cmd |= 0U;
834     errorstate = SDMMC_SDIO_CmdReadWriteDirect(hsdio->Instance, cmd, pData);
835 
836     if (errorstate != HAL_SDIO_ERROR_NONE)
837     {
838       hsdio->ErrorCode |= errorstate;
839       if (errorstate != (SDMMC_ERROR_ADDR_OUT_OF_RANGE | SDMMC_ERROR_ILLEGAL_CMD | SDMMC_ERROR_COM_CRC_FAILED |
840                          SDMMC_ERROR_GENERAL_UNKNOWN_ERR))
841       {
842         /* Clear all the static flags */
843         __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
844         hsdio->State = HAL_SDIO_STATE_READY;
845         hsdio->Context = SDIO_CONTEXT_NONE;
846         return HAL_ERROR;
847       }
848     }
849 
850     __SDMMC_CMDTRANS_DISABLE(hsdio->Instance);
851 
852     /* Clear all the static flags */
853     __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_DATA_FLAGS);
854 
855     hsdio->State = HAL_SDIO_STATE_READY;
856   }
857   else
858   {
859     return HAL_BUSY;
860   }
861 
862   return HAL_OK;
863 }
864 
865 
866 /**
867   * @brief  Read data from a specified address using the direct mode through cmd52.
868   * @param  hsdio: Pointer to SDIO handle
869   * @param  Argument: Specifies the SDIO Argument.
870   * @param  Data: pointer to the buffer that will contain the received data.
871   * @retval HAL status
872   */
HAL_SDIO_WriteDirect(SDIO_HandleTypeDef * hsdio,HAL_SDIO_DirectCmd_TypeDef * Argument,uint8_t Data)873 HAL_StatusTypeDef HAL_SDIO_WriteDirect(SDIO_HandleTypeDef *hsdio, HAL_SDIO_DirectCmd_TypeDef *Argument, uint8_t Data)
874 {
875   uint32_t cmd;
876   uint32_t errorstate;
877 
878   /* Check the parameters */
879   assert_param(hsdio != NULL);
880   assert_param(Argument != NULL);
881   assert_param(IS_SDIO_RAW_FLAG(Argument->ReadAfterWrite));
882 
883   if ((hsdio == NULL) || (Argument == NULL))
884   {
885     return HAL_ERROR;
886   }
887 
888   if (hsdio->State == HAL_SDIO_STATE_READY)
889   {
890     hsdio->ErrorCode = HAL_SDIO_ERROR_NONE;
891     hsdio->State = HAL_SDIO_STATE_BUSY;
892 
893     cmd = SDIO_WRITE << 31U;
894     cmd |= ((uint32_t)Argument->IOFunctionNbr) << 28U;
895     cmd |= ((uint32_t)Argument->ReadAfterWrite) << 27U;
896     cmd |= (Argument->Reg_Addr & 0x1FFFFU) << 9U;
897     cmd |= Data;
898     errorstate = SDMMC_SDIO_CmdReadWriteDirect(hsdio->Instance, cmd, &Data);
899     if (errorstate != HAL_SDIO_ERROR_NONE)
900     {
901       hsdio->ErrorCode |= errorstate;
902       if (errorstate != (SDMMC_ERROR_ADDR_OUT_OF_RANGE | SDMMC_ERROR_ILLEGAL_CMD | SDMMC_ERROR_COM_CRC_FAILED |
903                          SDMMC_ERROR_GENERAL_UNKNOWN_ERR))
904       {
905         /* Clear all the static flags */
906         __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
907         hsdio->State = HAL_SDIO_STATE_READY;
908         hsdio->Context = SDIO_CONTEXT_NONE;
909         return HAL_ERROR;
910       }
911     }
912 
913     __SDMMC_CMDTRANS_DISABLE(hsdio->Instance);
914 
915     /* Clear all the static flags */
916     __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_DATA_FLAGS);
917 
918     hsdio->State = HAL_SDIO_STATE_READY;
919   }
920   else
921   {
922     return HAL_BUSY;
923   }
924 
925   return HAL_OK;
926 }
927 
928 /**
929   * @brief  Read data from a specified address using extended mode through cmd53.
930   * @param  hsdio: Pointer to SDIO handle
931   * @param  Argument: Pointer to SDIO argument
932   * @param  pData:  pointer to the buffer that will contain the data to transmit
933   * @param  Size_byte:   size to read.
934   * @param  Timeout_Ms:  Specify timeout value
935   * @retval HAL status
936   */
HAL_SDIO_ReadExtended(SDIO_HandleTypeDef * hsdio,HAL_SDIO_ExtendedCmd_TypeDef * Argument,uint8_t * pData,uint32_t Size_byte,uint32_t Timeout_Ms)937 HAL_StatusTypeDef HAL_SDIO_ReadExtended(SDIO_HandleTypeDef *hsdio, HAL_SDIO_ExtendedCmd_TypeDef *Argument,
938                                         uint8_t *pData, uint32_t Size_byte, uint32_t Timeout_Ms)
939 {
940   uint32_t cmd;
941   SDMMC_DataInitTypeDef config;
942   uint32_t errorstate;
943   uint32_t tickstart = HAL_GetTick();
944   uint32_t regCount;
945   uint8_t byteCount;
946   uint32_t data;
947   uint32_t dataremaining;
948   uint8_t *tempbuff = pData;
949   uint32_t nbr_of_block;
950 
951   /* Check the parameters */
952   assert_param(hsdio != NULL);
953   assert_param(Argument != NULL);
954   assert_param(pData != NULL);
955 
956   if ((hsdio == NULL) || (Argument == NULL) || (pData == NULL))
957   {
958     return HAL_ERROR;
959   }
960 
961   if (hsdio->State == HAL_SDIO_STATE_READY)
962   {
963     hsdio->ErrorCode = HAL_SDIO_ERROR_NONE;
964     hsdio->State = HAL_SDIO_STATE_BUSY;
965 
966     /* Compute how many blocks are to be send for pData of length data_size to be send */
967     nbr_of_block = (Size_byte & ~(hsdio->block_size & 1U)) >> __CLZ(__RBIT(hsdio->block_size));
968 
969     /* Initialize data control register */
970     if ((hsdio->Instance->DCTRL & SDMMC_DCTRL_SDIOEN) != 0U)
971     {
972       hsdio->Instance->DCTRL = SDMMC_DCTRL_SDIOEN;
973     }
974     else
975     {
976       hsdio->Instance->DCTRL = 0U;
977     }
978 
979     /* Configure the SDIO DPSM (Data Path State Machine) */
980     config.DataTimeOut   = SDMMC_DATATIMEOUT;
981     /* (HAL_SDIO_MODE_BLOCK << 27) corresponds to the block mode bit of the CMD argument */
982     if (Argument->Block_Mode == HAL_SDIO_MODE_BLOCK)
983     {
984       /* (Argument & 0x1FFU) is to get the 9 bits of Block/Byte counts */
985       config.DataLength    = (uint32_t)(nbr_of_block * hsdio->block_size);
986       config.DataBlockSize = SDIO_Convert_Block_Size(hsdio, hsdio->block_size);
987     }
988     else
989     {
990       /* (Argument & 0x1FFU) is to get the 9 bits of Block/Byte counts */
991       config.DataLength    = (Size_byte > 0U) ? Size_byte : HAL_SDIO_DATA_BLOCK_SIZE_512BYTE;
992       config.DataBlockSize = SDMMC_DATABLOCK_SIZE_1B;
993     }
994 
995     config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC ;
996     /* (HAL_SDIO_MODE_BLOCK << 27) corresponds to the block mode bit of the CMD argument */
997     config.TransferMode = (Argument->Block_Mode == HAL_SDIO_MODE_BLOCK) ? SDMMC_TRANSFER_MODE_BLOCK :
998                           SDMMC_TRANSFER_MODE_SDIO;
999     config.DPSM         = SDMMC_DPSM_DISABLE;
1000     (void)SDMMC_ConfigData(hsdio->Instance, &config);
1001     __SDMMC_CMDTRANS_ENABLE(hsdio->Instance);
1002 
1003     /* Correspond to the write or read bit of the CMD argument */
1004     /* Read */
1005     hsdio->Context = (Argument->Block_Mode == HAL_SDIO_MODE_BLOCK) ? SDIO_CONTEXT_READ_MULTIPLE_BLOCK :
1006                      SDIO_CONTEXT_READ_SINGLE_BLOCK;
1007     cmd = SDIO_READ << 31U;
1008     cmd |= Argument->IOFunctionNbr << 28U;
1009     cmd |= Argument->Block_Mode << 27U;
1010     cmd |= Argument->OpCode << 26U;
1011     cmd |= (Argument->Reg_Addr & 0x1FFFFU) << 9U;
1012     cmd |= (Size_byte & 0x1FFU);
1013     errorstate = SDMMC_SDIO_CmdReadWriteExtended(hsdio->Instance, cmd);
1014     if (errorstate != HAL_SDIO_ERROR_NONE)
1015     {
1016       hsdio->ErrorCode |= errorstate;
1017       if (errorstate != (SDMMC_ERROR_ADDR_OUT_OF_RANGE | SDMMC_ERROR_ILLEGAL_CMD | SDMMC_ERROR_COM_CRC_FAILED |
1018                          SDMMC_ERROR_GENERAL_UNKNOWN_ERR))
1019       {
1020         MODIFY_REG(hsdio->Instance->DCTRL, SDMMC_DCTRL_FIFORST, SDMMC_DCTRL_FIFORST);
1021         __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
1022         __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_DATA_FLAGS);
1023         hsdio->State = HAL_SDIO_STATE_READY;
1024         hsdio->Context = SDIO_CONTEXT_NONE;
1025         return HAL_ERROR;
1026       }
1027     }
1028     /* (SDIO_WRITE << 31) correspond to the write or read bit of the CMD argument */
1029     /* Poll on SDMMC flags */
1030     dataremaining = config.DataLength;
1031 
1032     while (!__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL |
1033                                 SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
1034     {
1035       if (__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= 32U))
1036       {
1037         /* Read data from SDMMC Rx FIFO */
1038         for (regCount = 0U; regCount < 8U; regCount++)
1039         {
1040           data = SDMMC_ReadFIFO(hsdio->Instance);
1041           *tempbuff = (uint8_t)(data & 0xFFU);
1042           tempbuff++;
1043           *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
1044           tempbuff++;
1045           *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
1046           tempbuff++;
1047           *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
1048           tempbuff++;
1049         }
1050         dataremaining -= 32U;
1051       }
1052       else if (dataremaining < 32U)
1053       {
1054         while ((dataremaining > 0U) && !(__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_RXFIFOE)))
1055         {
1056           data = SDMMC_ReadFIFO(hsdio->Instance);
1057           for (byteCount = 0U; byteCount < 4U; byteCount++)
1058           {
1059             if (dataremaining > 0U)
1060             {
1061               *tempbuff = (uint8_t)((data >> (byteCount * 8U)) & 0xFFU);
1062               tempbuff++;
1063               dataremaining--;
1064             }
1065           }
1066         }
1067       }
1068       else
1069       {
1070         /* Nothing to do */
1071       }
1072       if ((HAL_GetTick() - tickstart) >=  Timeout_Ms)
1073       {
1074         /* Clear all the static flags */
1075         __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
1076         hsdio->ErrorCode |= HAL_SDIO_ERROR_TIMEOUT;
1077         hsdio->State = HAL_SDIO_STATE_READY;
1078         hsdio->Context = SDIO_CONTEXT_NONE;
1079         return HAL_TIMEOUT;
1080       }
1081     }
1082     __SDMMC_CMDTRANS_DISABLE(hsdio->Instance);
1083     /* Get error state */
1084     if (__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_DTIMEOUT))
1085     {
1086       /* Clear all the static flags */
1087       __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
1088       hsdio->ErrorCode |= HAL_SDIO_ERROR_DATA_TIMEOUT;
1089       hsdio->State = HAL_SDIO_STATE_READY;
1090       hsdio->Context = SDIO_CONTEXT_NONE;
1091       return HAL_ERROR;
1092     }
1093     else if (__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_DCRCFAIL))
1094     {
1095       /* Clear all the static flags */
1096       __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
1097       hsdio->ErrorCode |= HAL_SDIO_ERROR_DATA_CRC_FAIL;
1098       hsdio->State = HAL_SDIO_STATE_READY;
1099       hsdio->Context = SDIO_CONTEXT_NONE;
1100       return HAL_ERROR;
1101     }
1102     else if (__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_RXOVERR))
1103     {
1104       /* Clear all the static flags */
1105       __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
1106       /* (SDIO_WRITE << 31) correspond to the write or read bit of the CMD argument */
1107       hsdio->ErrorCode |= HAL_SDIO_ERROR_RX_OVERRUN;
1108       hsdio->State = HAL_SDIO_STATE_READY;
1109       hsdio->Context = SDIO_CONTEXT_NONE;
1110       return HAL_ERROR;
1111     }
1112     else if (hsdio->ErrorCode == SDMMC_ERROR_INVALID_PARAMETER)
1113     {
1114       __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_DATA_FLAGS);
1115       hsdio->State = HAL_SDIO_STATE_READY;
1116       hsdio->Context = SDIO_CONTEXT_NONE;
1117       return HAL_ERROR;
1118     }
1119     else
1120     {
1121       /* Nothing to do */
1122     }
1123 
1124     /* Clear all the static flags */
1125     __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_DATA_FLAGS);
1126 
1127     hsdio->State = HAL_SDIO_STATE_READY;
1128   }
1129   else
1130   {
1131     return HAL_BUSY;
1132   }
1133 
1134   return HAL_OK;
1135 }
1136 
1137 /**
1138   * @brief  Write data from a specified address using extended mode through cmd53.
1139   * @param  hsdio: Pointer to SDIO handle
1140   * @param  Argument: Pointer to SDIO argument
1141   * @param  pData:  pointer to the buffer that will contain the data to transmit
1142   * @param  Size_byte:  Block size to write.
1143   * @param  Timeout_Ms:  Specify timeout value
1144   * @retval HAL status
1145   */
HAL_SDIO_WriteExtended(SDIO_HandleTypeDef * hsdio,HAL_SDIO_ExtendedCmd_TypeDef * Argument,uint8_t * pData,uint32_t Size_byte,uint32_t Timeout_Ms)1146 HAL_StatusTypeDef HAL_SDIO_WriteExtended(SDIO_HandleTypeDef *hsdio, HAL_SDIO_ExtendedCmd_TypeDef *Argument,
1147                                          uint8_t *pData, uint32_t Size_byte, uint32_t Timeout_Ms)
1148 {
1149   uint32_t cmd;
1150   SDMMC_DataInitTypeDef config;
1151   uint32_t errorstate;
1152   uint32_t tickstart = HAL_GetTick();
1153   uint32_t regCount;
1154   uint8_t byteCount;
1155   uint32_t data;
1156   uint32_t dataremaining;
1157   uint8_t *u32tempbuff = pData;
1158   uint32_t nbr_of_block;
1159 
1160   /* Check the parameters */
1161   assert_param(hsdio != NULL);
1162   assert_param(Argument != NULL);
1163   assert_param(pData != NULL);
1164 
1165   if ((hsdio == NULL) || (Argument == NULL) || (pData == NULL))
1166   {
1167     return HAL_ERROR;
1168   }
1169 
1170   if (hsdio->State == HAL_SDIO_STATE_READY)
1171   {
1172     hsdio->ErrorCode = HAL_SDIO_ERROR_NONE;
1173     hsdio->State = HAL_SDIO_STATE_BUSY;
1174 
1175     /* Compute how many blocks are to be send for pData of length data_size to be send */
1176     nbr_of_block = (Size_byte & ~(hsdio->block_size & 1U)) >> __CLZ(__RBIT(hsdio->block_size));
1177 
1178     /* Initialize data control register */
1179     if ((hsdio->Instance->DCTRL & SDMMC_DCTRL_SDIOEN) != 0U)
1180     {
1181       hsdio->Instance->DCTRL = SDMMC_DCTRL_SDIOEN;
1182     }
1183     else
1184     {
1185       hsdio->Instance->DCTRL = 0U;
1186     }
1187 
1188     /* Configure the SDIO DPSM (Data Path State Machine) */
1189     config.DataTimeOut   = SDMMC_DATATIMEOUT;
1190     if (Argument->Block_Mode == HAL_SDIO_MODE_BLOCK)
1191     {
1192       config.DataLength    = (uint32_t)(nbr_of_block * hsdio->block_size);
1193       config.DataBlockSize = SDIO_Convert_Block_Size(hsdio, hsdio->block_size);
1194     }
1195     else
1196     {
1197       config.DataLength    = (Size_byte > 0U) ? Size_byte : HAL_SDIO_DATA_BLOCK_SIZE_512BYTE;
1198       config.DataBlockSize = SDMMC_DATABLOCK_SIZE_1B;
1199     }
1200 
1201     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
1202     /* (HAL_SDIO_MODE_BLOCK << 27) corresponds to the block mode bit of the CMD argument */
1203     config.TransferMode  = (Argument->Block_Mode == HAL_SDIO_MODE_BLOCK) ? SDMMC_TRANSFER_MODE_BLOCK :
1204                            SDMMC_TRANSFER_MODE_SDIO;
1205     config.DPSM          = SDMMC_DPSM_DISABLE;
1206     (void)SDMMC_ConfigData(hsdio->Instance, &config);
1207     __SDMMC_CMDTRANS_ENABLE(hsdio->Instance);
1208 
1209     /* Correspond to the write or read bit of the CMD argument */
1210     hsdio->Context = (Argument->Block_Mode == HAL_SDIO_MODE_BLOCK) ? SDIO_CONTEXT_WRITE_MULTIPLE_BLOCK :
1211                      SDIO_CONTEXT_WRITE_SINGLE_BLOCK;
1212     cmd = SDIO_WRITE << 31U;
1213     cmd |= Argument->IOFunctionNbr << 28U;
1214     cmd |= Argument->Block_Mode << 27U;
1215     cmd |= Argument->OpCode << 26U;
1216     cmd |= (Argument->Reg_Addr & 0x1FFFFU) << 9U;
1217     cmd |= (Size_byte & 0x1FFU);
1218     errorstate = SDMMC_SDIO_CmdReadWriteExtended(hsdio->Instance, cmd);
1219     if (errorstate != HAL_SDIO_ERROR_NONE)
1220     {
1221       hsdio->ErrorCode |= errorstate;
1222       if (errorstate != (SDMMC_ERROR_ADDR_OUT_OF_RANGE | SDMMC_ERROR_ILLEGAL_CMD | SDMMC_ERROR_COM_CRC_FAILED |
1223                          SDMMC_ERROR_GENERAL_UNKNOWN_ERR))
1224       {
1225         MODIFY_REG(hsdio->Instance->DCTRL, SDMMC_DCTRL_FIFORST, SDMMC_DCTRL_FIFORST);
1226         __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
1227         __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_DATA_FLAGS);
1228         hsdio->State = HAL_SDIO_STATE_READY;
1229         hsdio->Context = SDIO_CONTEXT_NONE;
1230         return HAL_ERROR;
1231       }
1232     }
1233     /* Write block(s) in polling mode */
1234     dataremaining = config.DataLength;
1235     while (!__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT |
1236                                 SDMMC_FLAG_DATAEND))
1237     {
1238 
1239       if (__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U))
1240       {
1241         /* Read data from SDMMC Rx FIFO */
1242         for (regCount = 0U; regCount < 8U; regCount++)
1243         {
1244           hsdio->Instance->FIFO = *u32tempbuff;
1245           u32tempbuff++;
1246         }
1247         dataremaining -= 32U;
1248       }
1249       else if ((dataremaining < 32U) && (__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_TXFIFOHE | SDMMC_FLAG_TXFIFOE)))
1250       {
1251         uint8_t *u8buff = (uint8_t *)u32tempbuff;
1252         while (dataremaining > 0U)
1253         {
1254           data = 0U;
1255           for (byteCount = 0U; (byteCount < 4U) && (dataremaining > 0U); byteCount++)
1256           {
1257             data |= ((uint32_t)(*u8buff) << (byteCount << 3U));
1258             u8buff++;
1259             dataremaining--;
1260           }
1261           hsdio->Instance->FIFO = data;
1262         }
1263       }
1264       if (((HAL_GetTick() - tickstart) >=  Timeout_Ms))
1265       {
1266         /* Clear all the static flags */
1267         __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
1268         hsdio->ErrorCode |= HAL_SDIO_ERROR_TIMEOUT;
1269         hsdio->State = HAL_SDIO_STATE_READY;
1270         hsdio->Context = SDIO_CONTEXT_NONE;
1271         return HAL_TIMEOUT;
1272       }
1273     }
1274 
1275     __SDMMC_CMDTRANS_DISABLE(hsdio->Instance);
1276     /* Get error state */
1277     if (__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_DTIMEOUT))
1278     {
1279       /* Clear all the static flags */
1280       __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
1281       hsdio->ErrorCode |= HAL_SDIO_ERROR_DATA_TIMEOUT;
1282       hsdio->State = HAL_SDIO_STATE_READY;
1283       hsdio->Context = SDIO_CONTEXT_NONE;
1284       return HAL_ERROR;
1285     }
1286     else if (__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_DCRCFAIL))
1287     {
1288       /* Clear all the static flags */
1289       __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
1290       hsdio->ErrorCode |= HAL_SDIO_ERROR_DATA_CRC_FAIL;
1291       hsdio->State = HAL_SDIO_STATE_READY;
1292       hsdio->Context = SDIO_CONTEXT_NONE;
1293       return HAL_ERROR;
1294     }
1295     else if (__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_TXUNDERR))
1296     {
1297       /* Clear all the static flags */
1298       __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
1299       /* (SDIO_WRITE << 31) correspond to the write or read bit of the CMD argument */
1300       hsdio->ErrorCode |= HAL_SDIO_ERROR_TX_UNDERRUN;
1301       hsdio->State = HAL_SDIO_STATE_READY;
1302       hsdio->Context = SDIO_CONTEXT_NONE;
1303       return HAL_ERROR;
1304     }
1305     else if (hsdio->ErrorCode == SDMMC_ERROR_INVALID_PARAMETER)
1306     {
1307       __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_DATA_FLAGS);
1308       hsdio->State = HAL_SDIO_STATE_READY;
1309       hsdio->Context = SDIO_CONTEXT_NONE;
1310       return HAL_ERROR;
1311     }
1312     else
1313     {
1314       /* Nothing to do */
1315     }
1316 
1317     /* Clear all the static flags */
1318     __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_DATA_FLAGS);
1319 
1320     hsdio->State = HAL_SDIO_STATE_READY;
1321   }
1322   else
1323   {
1324     return HAL_BUSY;
1325   }
1326 
1327   return HAL_OK;
1328 }
1329 
1330 /**
1331   * @brief  Read data from a specified address using extended mode through cmd53 in DMA mode.
1332   * @param  hsdio: Pointer to SDIO handle
1333   * @param  Argument: Pointer to SDIO argument
1334   * @param  pData:  pointer to the buffer that will contain the data to transmit
1335   * @param  Size_byte:  Block size to write.
1336   * @retval HAL status
1337   */
HAL_SDIO_ReadExtended_DMA(SDIO_HandleTypeDef * hsdio,HAL_SDIO_ExtendedCmd_TypeDef * Argument,uint8_t * pData,uint32_t Size_byte)1338 HAL_StatusTypeDef HAL_SDIO_ReadExtended_DMA(SDIO_HandleTypeDef *hsdio, HAL_SDIO_ExtendedCmd_TypeDef *Argument,
1339                                             uint8_t *pData, uint32_t Size_byte)
1340 {
1341   SDMMC_DataInitTypeDef config;
1342   uint32_t errorstate;
1343   uint8_t *p_dma_buffer;
1344   uint32_t cmd;
1345   uint32_t nbr_of_block;
1346 
1347   /* Check the parameters */
1348   assert_param(hsdio != NULL);
1349   assert_param(Argument != NULL);
1350   assert_param(pData != NULL);
1351 
1352   if ((hsdio == NULL) || (Argument == NULL) || (pData == NULL))
1353   {
1354     return HAL_ERROR;
1355   }
1356 
1357   if (hsdio->State == HAL_SDIO_STATE_READY)
1358   {
1359     hsdio->ErrorCode = HAL_SDIO_ERROR_NONE;
1360     hsdio->State = HAL_SDIO_STATE_BUSY;
1361 
1362     /* Initialize data control register */
1363     if ((hsdio->Instance->DCTRL & SDMMC_DCTRL_SDIOEN) != 0U)
1364     {
1365       hsdio->Instance->DCTRL = SDMMC_DCTRL_SDIOEN;
1366     }
1367     else
1368     {
1369       hsdio->Instance->DCTRL = 0U;
1370     }
1371 
1372     p_dma_buffer = (uint8_t *)pData;
1373     hsdio->pRxBuffPtr = (uint8_t *)pData;
1374     hsdio->RxXferSize = Size_byte;
1375     hsdio->next_data_addr = (uint32_t)pData;
1376 
1377     /* Compute how many blocks are to be send for pData of length data_size to be send */
1378     nbr_of_block = (Size_byte & ~(hsdio->block_size & 1U)) >> __CLZ(__RBIT(hsdio->block_size));
1379 
1380     if (nbr_of_block != 0U)
1381     {
1382       hsdio->remaining_data = (Size_byte - (hsdio->block_size * nbr_of_block));
1383       hsdio->next_reg_addr = (Argument->Reg_Addr) | ((((nbr_of_block * hsdio->block_size) >> 1U) & 0x3FFFU) << 1U)
1384                              | ((hsdio->remaining_data <= HAL_SDIO_DATA_BLOCK_SIZE_512BYTE) ? 1U : 0U);
1385       hsdio->next_data_addr += (nbr_of_block * hsdio->block_size);
1386     }
1387     else
1388     {
1389       hsdio->next_data_addr += (Size_byte < HAL_SDIO_DATA_BLOCK_SIZE_512BYTE) ? Size_byte :
1390                                HAL_SDIO_DATA_BLOCK_SIZE_512BYTE;
1391       if (hsdio->remaining_data != 0U)
1392       {
1393         hsdio->remaining_data = (Size_byte >= HAL_SDIO_DATA_BLOCK_SIZE_512BYTE) ?
1394                                 (Size_byte - HAL_SDIO_DATA_BLOCK_SIZE_512BYTE) :
1395                                 (Size_byte - hsdio->remaining_data);
1396         hsdio->next_reg_addr += (Size_byte >= HAL_SDIO_DATA_BLOCK_SIZE_512BYTE) ? \
1397                                 (HAL_SDIO_DATA_BLOCK_SIZE_512BYTE + 1U) : (Size_byte + 1U);
1398       }
1399     }
1400 
1401     /* DMA configuration (use single buffer) */
1402     hsdio->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
1403     hsdio->Instance->IDMABASER = (uint32_t)p_dma_buffer;
1404 
1405     /* Configure the SD DPSM (Data Path State Machine) */
1406     config.DataTimeOut   = SDMMC_DATATIMEOUT;
1407     if (Argument->Block_Mode == HAL_SDIO_MODE_BLOCK)
1408     {
1409       config.DataLength    = (uint32_t)(nbr_of_block * hsdio->block_size);
1410       config.DataBlockSize = SDIO_Convert_Block_Size(hsdio, hsdio->block_size);
1411     }
1412     else
1413     {
1414       config.DataLength    = (Size_byte > 0U) ? Size_byte : HAL_SDIO_DATA_BLOCK_SIZE_512BYTE;
1415       config.DataBlockSize = SDMMC_DATABLOCK_SIZE_1B;
1416     }
1417 
1418     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC ;
1419     config.TransferMode  = (Argument->Block_Mode == HAL_SDIO_MODE_BLOCK) ? SDMMC_TRANSFER_MODE_BLOCK :
1420                            SDMMC_TRANSFER_MODE_SDIO;
1421     config.DPSM          = SDMMC_DPSM_DISABLE;
1422     (void)SDMMC_ConfigData(hsdio->Instance, &config);
1423 
1424     __SDMMC_CMDTRANS_ENABLE(hsdio->Instance);
1425 
1426     /* Read */
1427     hsdio->Context = (uint32_t)((Argument->Block_Mode == HAL_SDIO_MODE_BLOCK) ? SDIO_CONTEXT_READ_MULTIPLE_BLOCK :
1428                                 SDIO_CONTEXT_READ_SINGLE_BLOCK) | SDIO_CONTEXT_DMA;
1429 
1430     cmd = SDIO_READ << 31U;
1431     cmd |= Argument->IOFunctionNbr << 28U;
1432     cmd |= Argument->Block_Mode << 27U;
1433     cmd |= Argument->OpCode << 26U;
1434     cmd |= (Argument->Reg_Addr & 0x1FFFFU) << 9U;
1435     cmd |= ((nbr_of_block == 0U) ? Size_byte :  nbr_of_block) & 0x1FFU;
1436     errorstate = SDMMC_SDIO_CmdReadWriteExtended(hsdio->Instance, cmd);
1437     if (errorstate != HAL_SDIO_ERROR_NONE)
1438     {
1439       hsdio->ErrorCode |= errorstate;
1440       if (errorstate != (SDMMC_ERROR_ADDR_OUT_OF_RANGE | SDMMC_ERROR_ILLEGAL_CMD | SDMMC_ERROR_COM_CRC_FAILED |
1441                          SDMMC_ERROR_GENERAL_UNKNOWN_ERR))
1442       {
1443         MODIFY_REG(hsdio->Instance->DCTRL, SDMMC_DCTRL_FIFORST, SDMMC_DCTRL_FIFORST);
1444         __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
1445         __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_DATA_FLAGS);
1446         hsdio->State = HAL_SDIO_STATE_READY;
1447         hsdio->Context = SDIO_CONTEXT_NONE;
1448         return HAL_ERROR;
1449       }
1450     }
1451     /* Enable interrupt */
1452     __HAL_SDIO_ENABLE_IT(hsdio, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));
1453   }
1454   else
1455   {
1456     return HAL_BUSY;
1457   }
1458 
1459   return HAL_OK;
1460 }
1461 
1462 /**
1463   * @brief  Write data from a specified address using extended mode through cmd53 in DMA mode.
1464   * @param  hsdio: Pointer to SDIO handle
1465   * @param  Argument: Pointer to SDIO argument
1466   * @param  pData:  pointer to the buffer that will contain the data to transmit
1467   * @param  Size_byte:  Block size to write.
1468   * @retval HAL status
1469   */
HAL_SDIO_WriteExtended_DMA(SDIO_HandleTypeDef * hsdio,HAL_SDIO_ExtendedCmd_TypeDef * Argument,uint8_t * pData,uint32_t Size_byte)1470 HAL_StatusTypeDef HAL_SDIO_WriteExtended_DMA(SDIO_HandleTypeDef *hsdio, HAL_SDIO_ExtendedCmd_TypeDef *Argument,
1471                                              uint8_t *pData, uint32_t Size_byte)
1472 {
1473   uint32_t cmd;
1474   SDMMC_DataInitTypeDef config;
1475   uint32_t errorstate;
1476   uint8_t *p_dma_buffer;
1477   uint32_t nbr_of_block;
1478 
1479   /* Check the parameters */
1480   assert_param(hsdio != NULL);
1481   assert_param(Argument != NULL);
1482   assert_param(pData != NULL);
1483 
1484   if ((hsdio == NULL) || (Argument == NULL) || (pData == NULL))
1485   {
1486     return HAL_ERROR;
1487   }
1488 
1489   if (hsdio->State == HAL_SDIO_STATE_READY)
1490   {
1491     hsdio->ErrorCode = HAL_SDIO_ERROR_NONE;
1492     hsdio->State = HAL_SDIO_STATE_BUSY;
1493 
1494     /* Initialize data control register */
1495     if ((hsdio->Instance->DCTRL & SDMMC_DCTRL_SDIOEN) != 0U)
1496     {
1497       hsdio->Instance->DCTRL = SDMMC_DCTRL_SDIOEN;
1498     }
1499     else
1500     {
1501       hsdio->Instance->DCTRL = 0U;
1502     }
1503 
1504     p_dma_buffer = (uint8_t *)pData;
1505     hsdio->pTxBuffPtr = (uint8_t *)pData;
1506     hsdio->TxXferSize = Size_byte;
1507     hsdio->next_data_addr = (uint32_t)pData;
1508 
1509     nbr_of_block = (Size_byte & ~(hsdio->block_size & 1U)) >> __CLZ(__RBIT(hsdio->block_size));
1510 
1511     if (nbr_of_block != 0U)
1512     {
1513       hsdio->remaining_data = (Size_byte - (hsdio->block_size * nbr_of_block));
1514       if (hsdio->block_size <= 128U)
1515       {
1516         hsdio->next_reg_addr = (Argument->Reg_Addr) |
1517                                ((((nbr_of_block * hsdio->block_size) >> 1U) & 0x3FFFU) << 1U) |
1518                                ((hsdio->remaining_data <= HAL_SDIO_DATA_BLOCK_SIZE_512BYTE) ? 1U : 0U);
1519       }
1520       else
1521       {
1522         hsdio->next_reg_addr = (nbr_of_block * hsdio->block_size) >> 1U;
1523       }
1524       hsdio->next_data_addr += (nbr_of_block * hsdio->block_size);
1525     }
1526     else
1527     {
1528       hsdio->remaining_data = (Size_byte >= HAL_SDIO_DATA_BLOCK_SIZE_512BYTE) ?
1529                               (Size_byte - HAL_SDIO_DATA_BLOCK_SIZE_512BYTE) :
1530                               (Size_byte - hsdio->remaining_data);
1531       if (hsdio->remaining_data != 0U)
1532       {
1533         hsdio->remaining_data = (Size_byte >= HAL_SDIO_DATA_BLOCK_SIZE_512BYTE) ?
1534                                 (Size_byte - HAL_SDIO_DATA_BLOCK_SIZE_512BYTE) :
1535                                 (Size_byte - hsdio->remaining_data);
1536         hsdio->next_reg_addr += ((Size_byte >= HAL_SDIO_DATA_BLOCK_SIZE_512BYTE) ? \
1537                                  (HAL_SDIO_DATA_BLOCK_SIZE_512BYTE >> 1U) : (Size_byte >> 1U)) |
1538                                 (((hsdio->remaining_data > 0U) ? 0U : 1U));
1539       }
1540       hsdio->next_data_addr += (Size_byte < HAL_SDIO_DATA_BLOCK_SIZE_512BYTE) ? Size_byte :
1541                                HAL_SDIO_DATA_BLOCK_SIZE_512BYTE;
1542     }
1543 
1544     /* DMA configuration (use single buffer) */
1545     hsdio->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
1546     hsdio->Instance->IDMABASER = (uint32_t)p_dma_buffer;
1547 
1548     /* Configure the SDIO DPSM (Data Path State Machine) */
1549     config.DataTimeOut   = SDMMC_DATATIMEOUT;
1550     if (Argument->Block_Mode == HAL_SDIO_MODE_BLOCK)
1551     {
1552       config.DataLength    = (uint32_t)(nbr_of_block * hsdio->block_size);
1553       config.DataBlockSize = SDIO_Convert_Block_Size(hsdio, hsdio->block_size);
1554     }
1555     else
1556     {
1557       config.DataLength = (Size_byte > HAL_SDIO_DATA_BLOCK_SIZE_512BYTE) ? HAL_SDIO_DATA_BLOCK_SIZE_512BYTE : Size_byte;
1558       config.DataBlockSize = SDMMC_DATABLOCK_SIZE_1B;
1559     }
1560 
1561     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
1562     config.TransferMode  = (Argument->Block_Mode == HAL_SDIO_MODE_BLOCK) ? SDMMC_TRANSFER_MODE_BLOCK
1563                            : SDMMC_TRANSFER_MODE_SDIO;
1564     config.DPSM          = SDMMC_DPSM_DISABLE;
1565     (void)SDMMC_ConfigData(hsdio->Instance, &config);
1566 
1567     __SDMMC_CMDTRANS_ENABLE(hsdio->Instance);
1568 
1569     /* Write */
1570     hsdio->Context = (uint32_t)((Argument->Block_Mode == HAL_SDIO_MODE_BLOCK) ?
1571                                 SDIO_CONTEXT_WRITE_MULTIPLE_BLOCK :
1572                                 SDIO_CONTEXT_WRITE_SINGLE_BLOCK) | SDIO_CONTEXT_DMA;
1573     cmd = SDIO_WRITE << 31U;
1574     cmd |= Argument->IOFunctionNbr << 28U;
1575     cmd |= Argument->Block_Mode << 27U;
1576     cmd |= Argument->OpCode << 26U;
1577     cmd |= (Argument->Reg_Addr & 0x1FFFFU) << 9U;
1578     cmd |= ((nbr_of_block == 0U) ? ((Size_byte > HAL_SDIO_DATA_BLOCK_SIZE_512BYTE) ?
1579                                     HAL_SDIO_DATA_BLOCK_SIZE_512BYTE : Size_byte) : nbr_of_block) & 0x1FFU;
1580     errorstate = SDMMC_SDIO_CmdReadWriteExtended(hsdio->Instance, cmd);
1581     if (errorstate != HAL_SDIO_ERROR_NONE)
1582     {
1583       hsdio->ErrorCode |= errorstate;
1584       if (errorstate != (SDMMC_ERROR_ADDR_OUT_OF_RANGE | SDMMC_ERROR_ILLEGAL_CMD | SDMMC_ERROR_COM_CRC_FAILED |
1585                          SDMMC_ERROR_GENERAL_UNKNOWN_ERR))
1586       {
1587         MODIFY_REG(hsdio->Instance->DCTRL, SDMMC_DCTRL_FIFORST, SDMMC_DCTRL_FIFORST);
1588         __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
1589         __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_DATA_FLAGS);
1590         hsdio->State = HAL_SDIO_STATE_READY;
1591         hsdio->Context = SDIO_CONTEXT_NONE;
1592         return HAL_ERROR;
1593       }
1594     }
1595     /* Enable interrupt */
1596     __HAL_SDIO_ENABLE_IT(hsdio, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));
1597   }
1598   else
1599   {
1600     return HAL_BUSY;
1601   }
1602 
1603   return HAL_OK;
1604 }
1605 
1606 /**
1607   * @}
1608   */
1609 
1610 /** @addtogroup SDIO_Exported_Functions_Group4
1611   *  @brief
1612   *
1613 @verbatim
1614   ==============================================================================
1615           ##### IO operation functions #####
1616   ==============================================================================
1617   [..]
1618     This subsection provides a set callback functions allowing to manage the data transfer from/to SDIO card.
1619 
1620 @endverbatim
1621   * @{
1622   */
1623 /**
1624   * @brief  This function handles SDIO device interrupt request.
1625   * @param  hsdio: Pointer to SDIO handle
1626   * @retval None
1627   */
HAL_SDIO_IRQHandler(SDIO_HandleTypeDef * hsdio)1628 void HAL_SDIO_IRQHandler(SDIO_HandleTypeDef *hsdio)
1629 {
1630   HAL_SDIO_ExtendedCmd_TypeDef CMD53_desc;
1631   HAL_StatusTypeDef errorstate;
1632   uint32_t ctx = hsdio->Context;
1633   uint32_t flags;
1634 
1635   flags   = READ_REG(((SDMMC_TypeDef *)((uint32_t)(hsdio)->Instance))->STA);
1636 
1637   if (READ_BIT(flags, SDMMC_FLAG_SDIOIT) != 0U)
1638   {
1639     (void)SDIO_IOFunction_IRQHandler(hsdio);
1640   }
1641 
1642   if (READ_BIT(flags, SDMMC_FLAG_DATAEND) != 0U)
1643   {
1644     __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_FLAG_DATAEND);
1645 
1646     hsdio->State = HAL_SDIO_STATE_READY;
1647 
1648     __HAL_SDIO_DISABLE_IT(hsdio, SDMMC_IT_DATAEND  | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR |
1649                           SDMMC_IT_RXOVERR  | SDMMC_IT_TXFIFOHE | SDMMC_IT_RXFIFOHF);
1650 
1651     __HAL_SDIO_DISABLE_IT(hsdio, SDMMC_IT_IDMABTC);
1652     __SDMMC_CMDTRANS_DISABLE(hsdio->Instance);
1653 
1654     if ((ctx & SDIO_CONTEXT_DMA) != 0U)
1655     {
1656       hsdio->Instance->DLEN = 0;
1657       hsdio->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
1658       if ((hsdio->Instance->DCTRL & SDMMC_DCTRL_SDIOEN) != 0U)
1659       {
1660         hsdio->Instance->DCTRL = SDMMC_DCTRL_SDIOEN;
1661       }
1662       else
1663       {
1664         hsdio->Instance->DCTRL = 0U;
1665       }
1666 
1667       hsdio->Context = SDIO_CONTEXT_NONE;
1668       hsdio->State = HAL_SDIO_STATE_READY;
1669     }
1670 
1671     if (hsdio->remaining_data != 0U)
1672     {
1673       CMD53_desc.Block_Mode = HAL_SDIO_MODE_BYTE;
1674       CMD53_desc.Reg_Addr = hsdio->next_reg_addr;
1675       CMD53_desc.IOFunctionNbr = 1;
1676       CMD53_desc.OpCode = 1;
1677       if (((ctx & SDIO_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((ctx & SDIO_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
1678       {
1679         hsdio->pRxBuffPtr = (uint8_t *)hsdio->next_data_addr;
1680         errorstate =  HAL_SDIO_ReadExtended_DMA(hsdio, &CMD53_desc, hsdio->pRxBuffPtr, hsdio->remaining_data);
1681       }
1682       else
1683       {
1684         hsdio->pTxBuffPtr = (uint8_t *)hsdio->next_data_addr;
1685         errorstate =  HAL_SDIO_WriteExtended_DMA(hsdio, &CMD53_desc, hsdio->pTxBuffPtr, hsdio->remaining_data);
1686       }
1687       if (errorstate != HAL_OK)
1688       {
1689 #if defined (USE_HAL_SDIO_REGISTER_CALLBACKS) && (USE_HAL_SDIO_REGISTER_CALLBACKS == 1)
1690         hsdio->ErrorCallback(hsdio);
1691 #else
1692         HAL_SDIO_ErrorCallback(hsdio);
1693 #endif /* USE_HAL_SDIO_REGISTER_CALLBACKS */
1694       }
1695     }
1696     else if (((ctx & SDIO_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((ctx & SDIO_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
1697     {
1698 #if defined (USE_HAL_SDIO_REGISTER_CALLBACKS) && (USE_HAL_SDIO_REGISTER_CALLBACKS == 1U)
1699       hsdio->RxCpltCallback(hsdio);
1700 #else
1701       HAL_SDIO_RxCpltCallback(hsdio);
1702 #endif /* USE_HAL_SDIO_REGISTER_CALLBACKS */
1703     }
1704     else
1705     {
1706 #if defined (USE_HAL_SDIO_REGISTER_CALLBACKS) && (USE_HAL_SDIO_REGISTER_CALLBACKS == 1U)
1707       hsdio->TxCpltCallback(hsdio);
1708 #else
1709       HAL_SDIO_TxCpltCallback(hsdio);
1710 #endif /* USE_HAL_SDIO_REGISTER_CALLBACKS */
1711     }
1712   }
1713 
1714   if (__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_RXOVERR | SDMMC_FLAG_TXUNDERR))
1715   {
1716 #if defined (USE_HAL_SDIO_REGISTER_CALLBACKS) && (USE_HAL_SDIO_REGISTER_CALLBACKS == 1)
1717     hsdio->ErrorCallback(hsdio);
1718 #else
1719     HAL_SDIO_ErrorCallback(hsdio);
1720 #endif /* USE_HAL_SDIO_REGISTER_CALLBACKS */
1721   }
1722 }
1723 
1724 /**
1725   * @brief Tx Transfer completed callbacks
1726   * @param hsdio: Pointer to SDIO handle
1727   * @retval None
1728   */
HAL_SDIO_TxCpltCallback(SDIO_HandleTypeDef * hsdio)1729 __weak void HAL_SDIO_TxCpltCallback(SDIO_HandleTypeDef *hsdio)
1730 {
1731   /* Prevent unused argument(s) compilation warning */
1732   UNUSED(hsdio);
1733 
1734   /* NOTE : This function should not be modified, when the callback is needed,
1735             the HAL_SDIO_TxCpltCallback can be implemented in the user file
1736    */
1737 }
1738 
1739 /**
1740   * @brief Rx Transfer completed callbacks
1741   * @param hsdio: Pointer SDIO handle
1742   * @retval None
1743   */
HAL_SDIO_RxCpltCallback(SDIO_HandleTypeDef * hsdio)1744 __weak void HAL_SDIO_RxCpltCallback(SDIO_HandleTypeDef *hsdio)
1745 {
1746   /* Prevent unused argument(s) compilation warning */
1747   UNUSED(hsdio);
1748 
1749   /* NOTE : This function should not be modified, when the callback is needed,
1750             the HAL_SDIO_RxCpltCallback can be implemented in the user file
1751    */
1752 }
1753 
1754 /**
1755   * @brief SDIO error callbacks
1756   * @param hsdio: Pointer SDIO handle
1757   * @retval None
1758   */
HAL_SDIO_ErrorCallback(SDIO_HandleTypeDef * hsdio)1759 __weak void HAL_SDIO_ErrorCallback(SDIO_HandleTypeDef *hsdio)
1760 {
1761   /* Prevent unused argument(s) compilation warning */
1762   UNUSED(hsdio);
1763 
1764   /* NOTE : This function should not be modified, when the callback is needed,
1765             the HAL_SDIO_ErrorCallback can be implemented in the user file
1766    */
1767 }
1768 
1769 /**
1770   * @brief SDIO IO Function complete callback
1771   * @param hsdio: Pointer SDIO handle
1772   * @param func: SDIO IO Function
1773   * @retval None
1774   */
HAL_SDIO_IOFunctionCallback(SDIO_HandleTypeDef * hsdio,uint32_t func)1775 __weak void HAL_SDIO_IOFunctionCallback(SDIO_HandleTypeDef *hsdio, uint32_t func)
1776 {
1777   /* Prevent unused argument(s) compilation warning */
1778   UNUSED(hsdio);
1779   UNUSED(func);
1780 
1781   /* NOTE : This function should not be modified, when the callback is needed,
1782             the HAL_SDIO_ErrorCallback can be implemented in the user file
1783    */
1784 }
1785 
1786 #if (USE_SDIO_TRANSCEIVER != 0U)
1787 /**
1788   * @brief  Enable/Disable the SDIO Transceiver 1.8V Mode Callback.
1789   * @param  hsdio: Pointer SDIO handle
1790   * @param  status: Voltage Switch State
1791   * @retval None
1792   */
HAL_SDIO_DriveTransceiver_1_8V_Callback(SDIO_HandleTypeDef * hsdio,FlagStatus status)1793 __weak  void HAL_SDIO_DriveTransceiver_1_8V_Callback(SDIO_HandleTypeDef *hsdio, FlagStatus status)
1794 {
1795   /* Prevent unused argument(s) compilation warning */
1796   UNUSED(hsdio);
1797   UNUSED(status);
1798   /* NOTE : This function should not be modified, when the callback is needed,
1799             the HAL_SDIO_EnableTransceiver could be implemented in the user file
1800    */
1801 }
1802 #endif /* USE_SDIO_TRANSCEIVER  */
1803 
1804 #if defined (USE_HAL_SDIO_REGISTER_CALLBACKS) && (USE_HAL_SDIO_REGISTER_CALLBACKS == 1U)
1805 /**
1806   * @brief  Register a User SDIO Callback
1807   *         To be used instead of the weak (overridden) predefined callback
1808   * @param hsdio : SDIO handle
1809   * @param CallbackID : ID of the callback to be registered
1810   *        This parameter can be one of the following values:
1811   *          @arg @ref HAL_SDIO_TX_CPLT_CB_ID                 SDIO Tx Complete Callback ID
1812   *          @arg @ref HAL_SDIO_RX_CPLT_CB_ID                 SDIO Rx Complete Callback ID
1813   *          @arg @ref HAL_SDIO_ERROR_CB_ID                   SDIO Error Callback ID
1814   *          @arg @ref HAL_SDIO_MSP_INIT_CB_ID                SDIO MspInit Callback ID
1815   *          @arg @ref HAL_SDIO_MSP_DEINIT_CB_ID              SDIO MspDeInit Callback ID
1816   * @param pCallback : pointer to the Callback function
1817   * @retval status
1818   */
HAL_SDIO_RegisterCallback(SDIO_HandleTypeDef * hsdio,HAL_SDIO_CallbackIDTypeDef CallbackID,pSDIO_CallbackTypeDef pCallback)1819 HAL_StatusTypeDef HAL_SDIO_RegisterCallback(SDIO_HandleTypeDef *hsdio, HAL_SDIO_CallbackIDTypeDef CallbackID,
1820                                             pSDIO_CallbackTypeDef pCallback)
1821 {
1822   HAL_StatusTypeDef status = HAL_OK;
1823 
1824   /* Check the parameters */
1825   assert_param(hsdio != NULL);
1826   assert_param(pCallback != NULL);
1827 
1828   if (pCallback == NULL)
1829   {
1830     /* Update the error code */
1831     hsdio->ErrorCode |= HAL_SDIO_ERROR_INVALID_CALLBACK;
1832     return HAL_ERROR;
1833   }
1834 
1835   if (hsdio->State == HAL_SDIO_STATE_READY)
1836   {
1837     switch (CallbackID)
1838     {
1839       case HAL_SDIO_TX_CPLT_CB_ID :
1840         hsdio->TxCpltCallback = pCallback;
1841         break;
1842       case HAL_SDIO_RX_CPLT_CB_ID :
1843         hsdio->RxCpltCallback = pCallback;
1844         break;
1845       case HAL_SDIO_ERROR_CB_ID :
1846         hsdio->ErrorCallback = pCallback;
1847         break;
1848       case HAL_SDIO_MSP_INIT_CB_ID :
1849         hsdio->MspInitCallback = pCallback;
1850         break;
1851       case HAL_SDIO_MSP_DEINIT_CB_ID :
1852         hsdio->MspDeInitCallback = pCallback;
1853         break;
1854       default :
1855         /* Update the error code */
1856         hsdio->ErrorCode |= HAL_SDIO_ERROR_INVALID_CALLBACK;
1857         /* update return status */
1858         status =  HAL_ERROR;
1859         break;
1860     }
1861   }
1862   else if (hsdio->State == HAL_SDIO_STATE_RESET)
1863   {
1864     switch (CallbackID)
1865     {
1866       case HAL_SDIO_MSP_INIT_CB_ID :
1867         hsdio->MspInitCallback = pCallback;
1868         break;
1869       case HAL_SDIO_MSP_DEINIT_CB_ID :
1870         hsdio->MspDeInitCallback = pCallback;
1871         break;
1872       default :
1873         /* Update the error code */
1874         hsdio->ErrorCode |= HAL_SDIO_ERROR_INVALID_CALLBACK;
1875         /* update return status */
1876         status =  HAL_ERROR;
1877         break;
1878     }
1879   }
1880   else
1881   {
1882     /* Update the error code */
1883     hsdio->ErrorCode |= HAL_SDIO_ERROR_INVALID_CALLBACK;
1884     /* update return status */
1885     status =  HAL_ERROR;
1886   }
1887 
1888   return status;
1889 }
1890 
1891 /**
1892   * @brief  Unregister a User SDIO Callback
1893   *         SDIO Callback is redirected to the weak (overridden) predefined callback.
1894   * @note   The HAL_SDIO_UnRegisterCallback() may be called before HAL_SDIO_Init() in
1895   *         HAL_SDIO_STATE_RESET to register callbacks for HAL_SDIO_MSP_INIT_CB_ID
1896   *         and HAL_SDIO_MSP_DEINIT_CB_ID.
1897   * @param hsdio : SDIO handle
1898   * @param CallbackID : ID of the callback to be unregistered
1899   *        This parameter can be one of the following values @ref SDIO_Exported_Types_Group3.
1900   * @retval status
1901   */
HAL_SDIO_UnRegisterCallback(SDIO_HandleTypeDef * hsdio,HAL_SDIO_CallbackIDTypeDef CallbackID)1902 HAL_StatusTypeDef HAL_SDIO_UnRegisterCallback(SDIO_HandleTypeDef *hsdio, HAL_SDIO_CallbackIDTypeDef CallbackID)
1903 {
1904   HAL_StatusTypeDef status = HAL_OK;
1905 
1906   assert_param(hsdio != NULL);
1907 
1908   /* Check the SDIO peripheral handle parameter */
1909   if (hsdio == NULL)
1910   {
1911     return HAL_ERROR;
1912   }
1913 
1914   if (hsdio->State == HAL_SDIO_STATE_READY)
1915   {
1916     switch (CallbackID)
1917     {
1918       case HAL_SDIO_TX_CPLT_CB_ID :
1919         hsdio->TxCpltCallback = HAL_SDIO_TxCpltCallback;
1920         break;
1921       case HAL_SDIO_RX_CPLT_CB_ID :
1922         hsdio->RxCpltCallback = HAL_SDIO_RxCpltCallback;
1923         break;
1924       case HAL_SDIO_ERROR_CB_ID :
1925         hsdio->ErrorCallback = HAL_SDIO_ErrorCallback;
1926         break;
1927       case HAL_SDIO_MSP_INIT_CB_ID :
1928         hsdio->MspInitCallback = HAL_SDIO_MspInit;
1929         break;
1930       case HAL_SDIO_MSP_DEINIT_CB_ID :
1931         hsdio->MspDeInitCallback = HAL_SDIO_MspDeInit;
1932         break;
1933       default :
1934         hsdio->ErrorCode |= HAL_SDIO_ERROR_INVALID_CALLBACK;
1935         status =  HAL_ERROR;
1936         break;
1937     }
1938   }
1939   else if (hsdio->State == HAL_SDIO_STATE_RESET)
1940   {
1941     switch (CallbackID)
1942     {
1943       case HAL_SDIO_MSP_INIT_CB_ID :
1944         hsdio->MspInitCallback = HAL_SDIO_MspInit;
1945         break;
1946       case HAL_SDIO_MSP_DEINIT_CB_ID :
1947         hsdio->MspDeInitCallback = HAL_SDIO_MspDeInit;
1948         break;
1949       default :
1950         hsdio->ErrorCode |= HAL_SDIO_ERROR_INVALID_CALLBACK;
1951         status =  HAL_ERROR;
1952         break;
1953     }
1954   }
1955   else
1956   {
1957     hsdio->ErrorCode |= HAL_SDIO_ERROR_INVALID_CALLBACK;
1958     status =  HAL_ERROR;
1959   }
1960 
1961   return status;
1962 }
1963 #endif /* USE_HAL_SDIO_REGISTER_CALLBACKS */
1964 
1965 #if (USE_SDIO_TRANSCEIVER != 0U)
1966 /**
1967   * @brief  Register a User SDIO Transceiver Callback
1968   *         To be used instead of the weak (overridden) predefined callback
1969   * @param hsdio : SDIO handle
1970   * @param pCallback : pointer to the Callback function
1971   * @retval status
1972   */
HAL_SDIO_RegisterTransceiverCallback(SDIO_HandleTypeDef * hsdio,pSDIO_TransceiverCallbackTypeDef pCallback)1973 HAL_StatusTypeDef HAL_SDIO_RegisterTransceiverCallback(SDIO_HandleTypeDef *hsdio,
1974                                                        pSDIO_TransceiverCallbackTypeDef pCallback)
1975 {
1976   HAL_StatusTypeDef status = HAL_OK;
1977 
1978   if (pCallback == NULL)
1979   {
1980     /* Update the error code */
1981     hsdio->ErrorCode |= HAL_SDIO_ERROR_INVALID_CALLBACK;
1982     return HAL_ERROR;
1983   }
1984 
1985   if (hsdio->State == HAL_SDIO_STATE_READY)
1986   {
1987     hsdio->DriveTransceiver_1_8V_Callback = pCallback;
1988   }
1989   else
1990   {
1991     /* Update the error code */
1992     hsdio->ErrorCode |= HAL_SDIO_ERROR_INVALID_CALLBACK;
1993     /* update return status */
1994     status =  HAL_ERROR;
1995   }
1996 
1997   return status;
1998 }
1999 
2000 /**
2001   * @brief  Unregister a User SDIO Transceiver Callback
2002   *         SDIO Callback is redirected to the weak (overridden) predefined callback
2003   * @param hsdio : SDIO handle
2004   * @retval status
2005   */
HAL_SDIO_UnRegisterTransceiverCallback(SDIO_HandleTypeDef * hsdio)2006 HAL_StatusTypeDef HAL_SDIO_UnRegisterTransceiverCallback(SDIO_HandleTypeDef *hsdio)
2007 {
2008   HAL_StatusTypeDef status = HAL_OK;
2009 
2010   if (hsdio->State == HAL_SDIO_STATE_READY)
2011   {
2012     hsdio->DriveTransceiver_1_8V_Callback = HAL_SDIO_DriveTransceiver_1_8V_Callback;
2013   }
2014   else
2015   {
2016     /* Update the error code */
2017     hsdio->ErrorCode |= HAL_SDIO_ERROR_INVALID_CALLBACK;
2018     /* update return status */
2019     status =  HAL_ERROR;
2020   }
2021 
2022   return status;
2023 }
2024 #endif /* USE_SDIO_TRANSCEIVER */
2025 
2026 /**
2027   * @brief Register a User SDIO Identification Callback
2028   * @param hsdio: Pointer to SDIO handle
2029   * @param pCallback: pointer to the Callback function
2030   * @retval status
2031   */
HAL_SDIO_RegisterIdentifyCardCallback(SDIO_HandleTypeDef * hsdio,pSDIO_IdentifyCardCallbackTypeDef pCallback)2032 HAL_StatusTypeDef HAL_SDIO_RegisterIdentifyCardCallback(SDIO_HandleTypeDef *hsdio,
2033                                                         pSDIO_IdentifyCardCallbackTypeDef pCallback)
2034 {
2035   /* Check the parameters */
2036   assert_param(hsdio != NULL);
2037   assert_param(pCallback != NULL);
2038 
2039   if (pCallback == NULL)
2040   {
2041     /* Update the error code */
2042     hsdio->ErrorCode |= HAL_SDIO_ERROR_INVALID_CALLBACK;
2043     return HAL_ERROR;
2044   }
2045 
2046   hsdio->SDIO_IdentifyCard = pCallback;
2047 
2048   return HAL_OK;
2049 }
2050 /**
2051   * @}
2052   */
2053 
2054 /** @addtogroup SDIO_Exported_Functions_Group5
2055   *  @brief
2056   *
2057 @verbatim
2058   ==============================================================================
2059           ##### Peripheral State and Errors functions #####
2060   ==============================================================================
2061   [..]
2062     This subsection provides a set of functions allowing to control the SDIO card operations.
2063 
2064 @endverbatim
2065   * @{
2066   */
2067 /**
2068   * @brief return the SDIO state
2069   * @param hsdio: Pointer to SDIO handle
2070   * @retval HAL state
2071   */
HAL_SDIO_GetState(const SDIO_HandleTypeDef * hsdio)2072 HAL_SDIO_StateTypeDef HAL_SDIO_GetState(const SDIO_HandleTypeDef *hsdio)
2073 {
2074   return hsdio->State;
2075 }
2076 
2077 /**
2078   * @brief  Return the SDIO error code
2079   * @param  hsdio : Pointer to a SDIO_HandleTypeDef structure that contains the configuration information.
2080   * @retval SDIO Error Code
2081   */
HAL_SDIO_GetError(const SDIO_HandleTypeDef * hsdio)2082 uint32_t HAL_SDIO_GetError(const SDIO_HandleTypeDef *hsdio)
2083 {
2084   return hsdio->ErrorCode;
2085 }
2086 
2087 /**
2088   * @}
2089   */
2090 
2091 /** @addtogroup SDIO_Exported_Functions_Group6
2092   *  @brief
2093   *
2094 @verbatim
2095   ==============================================================================
2096           ##### Peripheral IO interrupt #####
2097   ==============================================================================
2098   [..]
2099     This subsection provides a set functions allowing to enable/disable IO functions interrupt features
2100     on the SDIO card.
2101 
2102 @endverbatim
2103   * @{
2104   */
2105 /**
2106   * @brief  Enable SDIO IO interrupt.
2107   * @param  hsdio: Pointer to SDIO handle
2108   * @param  IOFunction: Specifies the SDIO IO function.
2109   * @retval HAL status
2110   */
HAL_SDIO_EnableIOFunctionInterrupt(SDIO_HandleTypeDef * hsdio,uint32_t IOFunction)2111 HAL_StatusTypeDef HAL_SDIO_EnableIOFunctionInterrupt(SDIO_HandleTypeDef *hsdio, uint32_t IOFunction)
2112 {
2113   uint8_t intEn  = 0U;
2114 
2115   /* Check the parameters */
2116   assert_param(hsdio != NULL);
2117   assert_param(IS_SDIO_FUNCTION(IOFunction));
2118 
2119   /* Check the SDIO peripheral handle parameter */
2120   if (hsdio == NULL)
2121   {
2122     return HAL_ERROR;
2123   }
2124 
2125   if (SDIO_ReadDirect(hsdio, SDMMC_SDIO_CCCR4, HAL_SDIO_WRITE_ONLY, SDIO_FUNCTION_0, &intEn) != HAL_OK)
2126   {
2127     return HAL_ERROR;
2128   }
2129 
2130   /* if already enable , do not need enable again */
2131   if ((((intEn >> (uint32_t)IOFunction) & 0x01U) == 0x01U) && ((intEn & 0x01U) != 0U))
2132   {
2133     return HAL_OK;
2134   }
2135   else
2136   {
2137     intEn |= (1U << (uint32_t)IOFunction) | 0x01U;
2138     hsdio->IOInterruptNbr++;
2139   }
2140 
2141   if (SDIO_WriteDirect(hsdio, SDMMC_SDIO_CCCR4, HAL_SDIO_WRITE_ONLY, SDIO_FUNCTION_0,
2142                        &intEn) != HAL_OK)
2143   {
2144     return HAL_ERROR;
2145   }
2146 
2147   __HAL_SDIO_ENABLE_IT(hsdio, SDMMC_IT_SDIOIT);
2148 
2149   /* Enable host SDIO interrupt operations */
2150   __SDMMC_OPERATION_ENABLE(hsdio->Instance);
2151 
2152   return HAL_OK;
2153 }
2154 
2155 /**
2156   * @brief  Enable SDIO IO interrupt.
2157   * @param  hsdio: Pointer to SDIO handle
2158   * @param  IOFunction: Specifies the SDIO IO function.
2159   * @retval HAL status
2160   */
HAL_SDIO_DisableIOFunctionInterrupt(SDIO_HandleTypeDef * hsdio,uint32_t IOFunction)2161 HAL_StatusTypeDef HAL_SDIO_DisableIOFunctionInterrupt(SDIO_HandleTypeDef *hsdio, uint32_t IOFunction)
2162 {
2163   uint8_t intEn  = 0U;
2164 
2165   /* Check the parameters */
2166   assert_param(hsdio != NULL);
2167   assert_param(IS_SDIO_FUNCTION(IOFunction));
2168 
2169   /* Check the SDIO peripheral handle parameter */
2170   if (hsdio == NULL)
2171   {
2172     return HAL_ERROR;
2173   }
2174 
2175   if (SDIO_ReadDirect(hsdio, SDMMC_SDIO_CCCR4, HAL_SDIO_WRITE_ONLY, SDIO_FUNCTION_0, &intEn) != HAL_OK)
2176   {
2177     return HAL_ERROR;
2178   }
2179 
2180   /* if already disable , do not need enable again */
2181   if (((intEn >> (uint32_t)IOFunction) & 0x01U) == 0x00U)
2182   {
2183     return HAL_OK;
2184   }
2185   else
2186   {
2187     /* disable the interrupt, don't disable the interrupt master here */
2188     intEn &= ~(1U << (uint32_t)IOFunction);
2189   }
2190 
2191   if (SDIO_WriteDirect(hsdio, SDMMC_SDIO_CCCR4, HAL_SDIO_READ_AFTER_WRITE, SDIO_FUNCTION_0,
2192                        &intEn) != HAL_OK)
2193   {
2194     return HAL_ERROR;
2195   }
2196 
2197   if (hsdio->IOInterruptNbr > 1U)
2198   {
2199     hsdio->IOInterruptNbr--;
2200   }
2201   else
2202   {
2203     hsdio->IOInterruptNbr = 0U;
2204     __HAL_SDIO_DISABLE_IT(hsdio, SDMMC_IT_SDIOIT);
2205   }
2206   return HAL_OK;
2207 }
2208 
2209 /**
2210   * @brief  Enable SDIO IO Enable.
2211   * @param  hsdio: Pointer to SDIO handle
2212   * @param  IOFunction: Specifies the SDIO IO function.
2213   * @retval HAL status
2214   */
HAL_SDIO_EnableIOFunction(SDIO_HandleTypeDef * hsdio,uint32_t IOFunction)2215 HAL_StatusTypeDef HAL_SDIO_EnableIOFunction(SDIO_HandleTypeDef *hsdio, uint32_t IOFunction)
2216 {
2217   uint8_t ioEn  = 0U;
2218   uint8_t ioReady = 0U;
2219 
2220   /* Check the parameters */
2221   assert_param(hsdio != NULL);
2222   assert_param(IS_SDIO_FUNCTION(IOFunction));
2223 
2224   /* Check the SDIO peripheral handle parameter */
2225   if (hsdio == NULL)
2226   {
2227     return HAL_ERROR;
2228   }
2229 
2230   if (SDIO_ReadDirect(hsdio, SDMMC_SDIO_CCCR0_SD_BYTE2, HAL_SDIO_WRITE_ONLY, SDIO_FUNCTION_0, &ioEn) != HAL_OK)
2231   {
2232     return HAL_ERROR;
2233   }
2234 
2235   /* if already enable , do not need to enable again */
2236   if (((ioEn >> (uint32_t)IOFunction) & 0x01U) == 0x01U)
2237   {
2238     return HAL_OK;
2239   }
2240   else
2241   {
2242     ioEn |= (1U << (uint32_t)IOFunction);
2243   }
2244 
2245   if (SDIO_WriteDirect(hsdio, SDMMC_SDIO_CCCR0_SD_BYTE2, HAL_SDIO_READ_AFTER_WRITE, SDIO_FUNCTION_0, &ioEn) != HAL_OK)
2246   {
2247     return HAL_ERROR;
2248   }
2249 
2250   if (SDIO_ReadDirect(hsdio, SDMMC_SDIO_CCCR0_SD_BYTE3, HAL_SDIO_WRITE_ONLY, SDIO_FUNCTION_0, &ioReady) != HAL_OK)
2251   {
2252     return HAL_ERROR;
2253   }
2254   /* check if IO ready */
2255   if ((ioReady & (1U << (uint32_t)IOFunction)) != 0U)
2256   {
2257     return HAL_OK;
2258   }
2259 
2260   return HAL_ERROR;
2261 }
2262 
2263 /**
2264   * @brief  Disable SDIO IO Enable.
2265   * @param  hsdio: Pointer to SDIO handle
2266   * @param  IOFunction: Specifies the SDIO IO function.
2267   * @retval HAL status
2268   */
HAL_SDIO_DisableIOFunction(SDIO_HandleTypeDef * hsdio,uint32_t IOFunction)2269 HAL_StatusTypeDef HAL_SDIO_DisableIOFunction(SDIO_HandleTypeDef *hsdio, uint32_t IOFunction)
2270 {
2271   uint8_t ioEn  = 0U;
2272 
2273   /* Check the parameters */
2274   assert_param(hsdio != NULL);
2275   assert_param(IS_SDIO_FUNCTION(IOFunction));
2276 
2277   /* Check the SDIO peripheral handle parameter */
2278   if (hsdio == NULL)
2279   {
2280     return HAL_ERROR;
2281   }
2282 
2283   if (SDIO_ReadDirect(hsdio, SDMMC_SDIO_CCCR0_SD_BYTE2, HAL_SDIO_WRITE_ONLY, SDIO_FUNCTION_0, &ioEn) != HAL_OK)
2284   {
2285     return HAL_ERROR;
2286   }
2287 
2288   /* if already enable , do not need enable again */
2289   if (((ioEn >> (uint32_t)IOFunction) & 0x01U) == 0x00U)
2290   {
2291     return HAL_OK;
2292   }
2293   else
2294   {
2295     ioEn &= ~(1U << (uint32_t)IOFunction);
2296   }
2297 
2298   if (SDIO_WriteDirect(hsdio, SDMMC_SDIO_CCCR0_SD_BYTE2, HAL_SDIO_READ_AFTER_WRITE, SDIO_FUNCTION_0, &ioEn) != HAL_OK)
2299   {
2300     return HAL_ERROR;
2301   }
2302 
2303   return HAL_OK;
2304 }
2305 
2306 /**
2307   * @brief  Select SDIO IO Enable.
2308   * @param  hsdio: Pointer to SDIO handle
2309   * @param  IOFunction: Specifies the SDIO IO function.
2310   * @retval HAL status
2311   */
HAL_SDIO_SelectIOFunction(SDIO_HandleTypeDef * hsdio,uint32_t IOFunction)2312 HAL_StatusTypeDef HAL_SDIO_SelectIOFunction(SDIO_HandleTypeDef *hsdio, uint32_t IOFunction)
2313 {
2314   /* Check the parameters */
2315   assert_param(hsdio != NULL);
2316   assert_param(IS_SDIO_FUNCTION(IOFunction));
2317 
2318   /* Check the SDIO peripheral handle parameter */
2319   if (hsdio == NULL)
2320   {
2321     return HAL_ERROR;
2322   }
2323 
2324   if (SDIO_WriteDirect(hsdio, SDMMC_SDIO_CCCR12_SD_BYTE1, HAL_SDIO_READ_AFTER_WRITE, SDIO_FUNCTION_0,
2325                        (uint8_t *)&IOFunction) != HAL_OK)
2326   {
2327     return HAL_ERROR;
2328   }
2329 
2330   return HAL_OK;
2331 }
2332 
2333 /**
2334   * @brief  Abort IO transfer.
2335   * @param  hsdio:  Pointer to SDIO handle
2336   * @param IOFunction IO number
2337   * @retval HAL status
2338   */
HAL_SDIO_AbortIOFunction(SDIO_HandleTypeDef * hsdio,uint32_t IOFunction)2339 HAL_StatusTypeDef HAL_SDIO_AbortIOFunction(SDIO_HandleTypeDef *hsdio, uint32_t IOFunction)
2340 {
2341   /* Check the parameters */
2342   assert_param(hsdio != NULL);
2343   assert_param(IS_SDIO_FUNCTION(IOFunction));
2344 
2345   /* Check the SDIO peripheral handle parameter */
2346   if (hsdio == NULL)
2347   {
2348     return HAL_ERROR;
2349   }
2350 
2351   if (SDIO_WriteDirect(hsdio, SDMMC_SDIO_CCCR4_SD_BYTE2, HAL_SDIO_READ_AFTER_WRITE, SDIO_FUNCTION_0,
2352                        (uint8_t *)&IOFunction) != HAL_OK)
2353   {
2354     return HAL_ERROR;
2355   }
2356 
2357   return HAL_OK;
2358 }
2359 
2360 /**
2361   * @brief  Enable Assynchrone interrupt.
2362   * @param  hsdio: Pointer to SDIO handle
2363   * @retval HAL status
2364   */
HAL_SDIO_EnableIOAsynInterrupt(SDIO_HandleTypeDef * hsdio)2365 HAL_StatusTypeDef HAL_SDIO_EnableIOAsynInterrupt(SDIO_HandleTypeDef *hsdio)
2366 {
2367   uint8_t enable_asyn_it  = 0U;
2368 
2369   /* Check the parameters */
2370   assert_param(hsdio != NULL);
2371 
2372   /* Check the SDIO peripheral handle parameter */
2373   if (hsdio == NULL)
2374   {
2375     return HAL_ERROR;
2376   }
2377 
2378   if (SDIO_ReadDirect(hsdio, SDMMC_SDIO_CCCR20_SD_BYTE2, HAL_SDIO_WRITE_ONLY, SDIO_FUNCTION_0, &enable_asyn_it)
2379       != HAL_OK)
2380   {
2381     return HAL_ERROR;
2382   }
2383 
2384   /* if already enable , do not need enable again */
2385   if ((enable_asyn_it & 0x02U) == 0x02U)
2386   {
2387     return HAL_OK;
2388   }
2389   else
2390   {
2391     enable_asyn_it |= 0x02U;
2392   }
2393 
2394   if (SDIO_WriteDirect(hsdio, SDMMC_SDIO_CCCR20_SD_BYTE2, HAL_SDIO_READ_AFTER_WRITE, SDIO_FUNCTION_0,
2395                        &enable_asyn_it) != HAL_OK)
2396   {
2397     return HAL_ERROR;
2398   }
2399 
2400   return HAL_OK;
2401 }
2402 
2403 /**
2404   * @brief  Disable Assynchrone interrupt.
2405   * @param  hsdio: Pointer to SDIO handle
2406   * @retval HAL status
2407   */
HAL_SDIO_DisableIOAsynInterrupt(SDIO_HandleTypeDef * hsdio)2408 HAL_StatusTypeDef HAL_SDIO_DisableIOAsynInterrupt(SDIO_HandleTypeDef *hsdio)
2409 {
2410   uint8_t enable_asyn_it  = 0U;
2411 
2412   /* Check the parameters */
2413   assert_param(hsdio != NULL);
2414 
2415   /* Check the SDIO peripheral handle parameter */
2416   if (hsdio == NULL)
2417   {
2418     return HAL_ERROR;
2419   }
2420 
2421   if (SDIO_ReadDirect(hsdio, SDMMC_SDIO_CCCR20_SD_BYTE2, HAL_SDIO_WRITE_ONLY, SDIO_FUNCTION_0, &enable_asyn_it)
2422       != HAL_OK)
2423   {
2424     return HAL_ERROR;
2425   }
2426 
2427   /* if already disable , do not need disable again */
2428   if ((enable_asyn_it & 0x02U) == 0x00U)
2429   {
2430     return HAL_OK;
2431   }
2432   else
2433   {
2434     enable_asyn_it &= (uint8_t) ~(0x02U);
2435   }
2436 
2437   if (SDIO_WriteDirect(hsdio, SDMMC_SDIO_CCCR20_SD_BYTE2, HAL_SDIO_READ_AFTER_WRITE, SDIO_FUNCTION_0,
2438                        &enable_asyn_it) != HAL_OK)
2439   {
2440     return HAL_ERROR;
2441   }
2442 
2443   return HAL_OK;
2444 }
2445 
2446 /**
2447   * @brief sdio set io IRQ handler.
2448   * @param hsdio  Pointer to SDIO handle
2449   * @param IOFunction IO function io number.
2450   * @param Callback io IRQ handler.
2451   */
HAL_SDIO_RegisterIOFunctionCallback(SDIO_HandleTypeDef * hsdio,uint32_t IOFunction,HAL_SDIO_IOFunction_CallbackTypeDef pCallback)2452 HAL_StatusTypeDef HAL_SDIO_RegisterIOFunctionCallback(SDIO_HandleTypeDef *hsdio, uint32_t IOFunction,
2453                                                       HAL_SDIO_IOFunction_CallbackTypeDef pCallback)
2454 {
2455   /* Check the parameters */
2456   assert_param(hsdio != NULL);
2457   assert_param(IS_SDIO_FUNCTION(IOFunction));
2458 
2459   /* Check the SDIO peripheral handle parameter */
2460   if (hsdio == NULL)
2461   {
2462     return HAL_ERROR;
2463   }
2464 
2465   hsdio->SDIO_IOFunction_Callback[(uint32_t)IOFunction] = pCallback;
2466   hsdio->IOFunctionMask |= (1U << (uint8_t)IOFunction);
2467 
2468   return HAL_OK;
2469 }
2470 /**
2471   * @}
2472   */
2473 
2474 /**
2475   * @}
2476   */
2477 
2478 /* Private function --------------------------------------------------------------------------------------------------*/
2479 /** @addtogroup SDIO_Private_Functions
2480   * @{
2481   */
2482 /**
2483   * @brief  Initializes the SDIO device.
2484   * @param  hsdio: Pointer to the SDIO handle
2485   * @retval HAL status
2486   */
SDIO_InitCard(SDIO_HandleTypeDef * hsdio)2487 static HAL_StatusTypeDef SDIO_InitCard(SDIO_HandleTypeDef *hsdio)
2488 {
2489   uint32_t errorstate;
2490   uint32_t timeout = 0U;
2491   uint16_t sdio_rca = 1U;
2492   uint32_t Resp4;
2493   uint32_t nbr_of_func;
2494 
2495   /* Identify card operating voltage */
2496   errorstate = SDMMC_CmdGoIdleState(hsdio->Instance);
2497   if (errorstate != HAL_SDIO_ERROR_NONE)
2498   {
2499     return HAL_ERROR;
2500   }
2501 
2502   /* Check the power State */
2503   if (SDMMC_GetPowerState(hsdio->Instance) == 0U)
2504   {
2505     return HAL_ERROR;
2506   }
2507 
2508   /* Send CMD5 */
2509   errorstate = SDMMC_CmdSendOperationcondition(hsdio->Instance, 0U, &Resp4);
2510   if (errorstate != HAL_SDIO_ERROR_NONE)
2511   {
2512     return HAL_ERROR;
2513   }
2514 
2515   nbr_of_func = ((Resp4 & 0x70000000U) >> 28U);
2516   /* Check if Nbr of function > 0 and OCR valid */
2517   if (nbr_of_func > 0U)
2518   {
2519     /* Send CMD5 with arg= S18R, WV*/
2520     if (SDMMC_CmdSendOperationcondition(hsdio->Instance, (SDIO_OCR_VDD_32_33 | SDIO_OCR_SDIO_S18R), &Resp4)
2521         != HAL_SDIO_ERROR_NONE)
2522     {
2523       return HAL_ERROR;
2524     }
2525     /* Check if IORDY = 1 and S18A = 1 */
2526     if ((((Resp4 & 0x80000000U) >> 31U) != 0U) && (((Resp4 & 0x1000000U) >> 24U) != 0U))
2527     {
2528       /* Send CMD11 to switch 1.8V mode */
2529       errorstate = SDMMC_CmdVoltageSwitch(hsdio->Instance);
2530       if (errorstate != HAL_SDIO_ERROR_NONE)
2531       {
2532         return HAL_ERROR;
2533       }
2534     }
2535     else
2536     {
2537       /* S18A is not supported */
2538     }
2539   }
2540 
2541   /** Cmd3 is sent while response is SDMMC_ERROR_ILLEGAL_CMD, due to the partial init test done before
2542     * (sending cmd0 after the sequence cmd0/cmd3 is sent is considered illegal).
2543     */
2544   do
2545   {
2546     errorstate = SDMMC_CmdSetRelAdd(hsdio->Instance, &sdio_rca);
2547     timeout++;
2548     HAL_Delay(1);
2549   } while ((errorstate == SDMMC_ERROR_ILLEGAL_CMD) && (timeout != SDIO_TIMEOUT));
2550 
2551   if ((timeout == SDIO_TIMEOUT) || (errorstate != HAL_SDIO_ERROR_NONE))
2552   {
2553     return HAL_ERROR;
2554   }
2555 
2556   /* Select the Card ( Sending CMD7)*/
2557   errorstate = SDMMC_CmdSelDesel(hsdio->Instance, (uint32_t)(((uint32_t)sdio_rca) << 16U));
2558   if (errorstate != HAL_SDIO_ERROR_NONE)
2559   {
2560     return HAL_ERROR;
2561   }
2562 
2563   return HAL_OK;
2564 }
2565 
2566 /**
2567   * @brief  Read 1 byte data.
2568   * @param  hsdio: Pointer to SDIO handle
2569   * @param  cmd_arg: formatted CMD52 structure
2570   * @param  pData: pointer to write or read data
2571   * @retval HAL status
2572   */
SDIO_ReadDirect(SDIO_HandleTypeDef * hsdio,uint32_t addr,uint32_t raw,uint32_t function_nbr,uint8_t * pData)2573 static HAL_StatusTypeDef SDIO_ReadDirect(SDIO_HandleTypeDef *hsdio, uint32_t addr, uint32_t raw,
2574                                          uint32_t function_nbr, uint8_t *pData)
2575 {
2576   uint32_t errorstate;
2577   uint32_t cmd;
2578 
2579   cmd = SDIO_READ << 31U;
2580   cmd |= function_nbr << 28U;
2581   cmd |= raw << 27U;
2582   cmd |= (addr & 0x1FFFFU) << 9U;
2583   errorstate = SDMMC_SDIO_CmdReadWriteDirect(hsdio->Instance, cmd, pData);
2584   if (errorstate != HAL_SDIO_ERROR_NONE)
2585   {
2586     hsdio->ErrorCode |= errorstate;
2587     /* Clear all the static flags */
2588     __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
2589     hsdio->State = HAL_SDIO_STATE_READY;
2590     hsdio->Context = SDIO_CONTEXT_NONE;
2591     return HAL_ERROR;
2592   }
2593   __SDMMC_CMDTRANS_DISABLE(hsdio->Instance);
2594 
2595   /* Clear all the static flags */
2596   __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_DATA_FLAGS);
2597 
2598   return HAL_OK;
2599 }
2600 
2601 /**
2602   * @brief  Write 1 byte data.
2603   * @param  hsdio: Pointer to SDIO handle
2604   * @param  cmd_arg: formatted CMD52 structure
2605   * @param  pData: pointer to write or read data
2606   * @retval HAL status
2607   */
SDIO_WriteDirect(SDIO_HandleTypeDef * hsdio,uint32_t addr,uint32_t raw,uint32_t function_nbr,uint8_t * pData)2608 static HAL_StatusTypeDef SDIO_WriteDirect(SDIO_HandleTypeDef *hsdio, uint32_t addr, uint32_t raw,
2609                                           uint32_t function_nbr, uint8_t *pData)
2610 {
2611   uint32_t errorstate;
2612   uint32_t cmd;
2613   uint8_t response;
2614 
2615   cmd = SDIO_WRITE << 31U;
2616   cmd |= function_nbr << 28U;
2617   cmd |= raw << 27U;
2618   cmd |= (addr & 0x1FFFFU) << 9U;
2619   cmd |= ((uint32_t) * pData & 0x000000FFU);
2620   errorstate = SDMMC_SDIO_CmdReadWriteDirect(hsdio->Instance, cmd, &response);
2621 
2622   if (errorstate != HAL_SDIO_ERROR_NONE)
2623   {
2624     hsdio->ErrorCode |= errorstate;
2625     /* Clear all the static flags */
2626     __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
2627     hsdio->State = HAL_SDIO_STATE_READY;
2628     hsdio->Context = SDIO_CONTEXT_NONE;
2629     return HAL_ERROR;
2630   }
2631   __SDMMC_CMDTRANS_DISABLE(hsdio->Instance);
2632 
2633   /* Clear all the static flags */
2634   __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_DATA_FLAGS);
2635 
2636   return HAL_OK;
2637 }
2638 
2639 /**
2640   * @brief  Write multiple data with a single command.
2641   * @param  hsdio: Pointer to SDIO handle
2642   * @param  cmd_arg: formatted cmd53 structure
2643   * @param  Size_byte: block size if CMD53 defined in HAL_SDIO_MODE_BLOCK
2644   * @param  pData: pointer to write or read data
2645   * @retval HAL status
2646   */
SDIO_WriteExtended(SDIO_HandleTypeDef * hsdio,HAL_SDIO_ExtendedCmd_TypeDef * cmd_arg,uint8_t * pData,uint16_t Size_byte)2647 static HAL_StatusTypeDef SDIO_WriteExtended(SDIO_HandleTypeDef *hsdio, HAL_SDIO_ExtendedCmd_TypeDef *cmd_arg,
2648                                             uint8_t *pData, uint16_t Size_byte)
2649 {
2650   SDMMC_DataInitTypeDef config;
2651   uint32_t errorstate;
2652   uint32_t tickstart = HAL_GetTick();
2653   uint32_t regCount;
2654   uint8_t byteCount;
2655   uint32_t data;
2656   uint32_t dataremaining;
2657   uint32_t *u32tempbuff = (uint32_t *)(uint32_t)pData;
2658   SDMMC_TypeDef *SDMMCx;
2659   uint32_t cmd;
2660   uint32_t nbr_of_block;
2661 
2662   hsdio->ErrorCode = HAL_SDIO_ERROR_NONE;
2663 
2664   /* Compute how many blocks are to be send for pData of length data_size to be send */
2665   nbr_of_block = (((uint32_t)Size_byte & ~((uint32_t)hsdio->block_size & 1U))) >> __CLZ(__RBIT(hsdio->block_size));
2666 
2667   /* Initialize data control register */
2668   if ((hsdio->Instance->DCTRL & SDMMC_DCTRL_SDIOEN) != 0U)
2669   {
2670     hsdio->Instance->DCTRL = SDMMC_DCTRL_SDIOEN;
2671   }
2672   else
2673   {
2674     hsdio->Instance->DCTRL = 0U;
2675   }
2676 
2677   /* Configure the SDIO DPSM (Data Path State Machine) */
2678   config.DataTimeOut   = SDMMC_DATATIMEOUT;
2679   if (cmd_arg->Block_Mode == HAL_SDIO_MODE_BLOCK)
2680   {
2681     config.DataLength    = (uint32_t)(nbr_of_block * hsdio->block_size);
2682     config.DataBlockSize = SDIO_Convert_Block_Size(hsdio, hsdio->block_size);
2683   }
2684   else
2685   {
2686     config.DataLength    = Size_byte;
2687     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_1B;
2688   }
2689 
2690   config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
2691   config.TransferMode  = (cmd_arg->Block_Mode == HAL_SDIO_MODE_BLOCK) ? SDMMC_TRANSFER_MODE_BLOCK :
2692                          SDMMC_TRANSFER_MODE_SDIO;
2693   config.DPSM          = SDMMC_DPSM_DISABLE;
2694   (void)SDMMC_ConfigData(hsdio->Instance, &config);
2695   __SDMMC_CMDTRANS_ENABLE(hsdio->Instance);
2696 
2697   hsdio->Context = (cmd_arg->Block_Mode == HAL_SDIO_MODE_BLOCK) ? SDIO_CONTEXT_WRITE_MULTIPLE_BLOCK :
2698                    SDIO_CONTEXT_WRITE_SINGLE_BLOCK;
2699   cmd = SDIO_WRITE << 31U;
2700   cmd |= cmd_arg->IOFunctionNbr << 28U;
2701   cmd |= cmd_arg->Block_Mode << 27U;
2702   cmd |= cmd_arg->OpCode << 26U;
2703   cmd |= (cmd_arg->Reg_Addr & 0x1FFFFU) << 9U;
2704   cmd |= (((uint32_t)Size_byte) & 0x1FFU);
2705   errorstate = SDMMC_SDIO_CmdReadWriteExtended(hsdio->Instance, cmd);
2706   if (errorstate != HAL_SDIO_ERROR_NONE)
2707   {
2708     MODIFY_REG(hsdio->Instance->DCTRL, SDMMC_DCTRL_FIFORST, SDMMC_DCTRL_FIFORST);
2709     __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
2710     __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_DATA_FLAGS);
2711     hsdio->ErrorCode |= errorstate;
2712     hsdio->State = HAL_SDIO_STATE_READY;
2713     hsdio->Context = SDIO_CONTEXT_NONE;
2714     return HAL_ERROR;
2715   }
2716 
2717   SDMMCx = hsdio->Instance;
2718   dataremaining = config.DataLength;
2719   while (!__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT |
2720                               SDMMC_FLAG_DATAEND))
2721   {
2722     if (__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U))
2723     {
2724       for (regCount = 8U; regCount > 0U; regCount--)
2725       {
2726         SDMMCx->FIFO = *u32tempbuff;
2727         u32tempbuff++;
2728       }
2729       dataremaining -= 32U;
2730     }
2731     else if ((dataremaining < 32U) && (__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_TXFIFOHE | SDMMC_FLAG_TXFIFOE)))
2732     {
2733       uint8_t *u8buff = (uint8_t *)u32tempbuff;
2734       while (dataremaining > 0U)
2735       {
2736         data = 0U;
2737         for (byteCount = 0U; (byteCount < 4U) && (dataremaining > 0U); byteCount++)
2738         {
2739           data |= ((uint32_t)(*u8buff) << (byteCount << 3U));
2740           u8buff++;
2741           dataremaining--;
2742         }
2743         SDMMCx->FIFO = data;
2744       }
2745     }
2746     if ((HAL_GetTick() - tickstart) >= SDMMC_DATATIMEOUT)
2747     {
2748       __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
2749       hsdio->ErrorCode |= HAL_SDIO_ERROR_TIMEOUT;
2750       hsdio->State = HAL_SDIO_STATE_READY;
2751       hsdio->Context = SDIO_CONTEXT_NONE;
2752       return HAL_TIMEOUT;
2753     }
2754   }
2755 
2756   __SDMMC_CMDTRANS_DISABLE(hsdio->Instance);
2757   if (__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_DTIMEOUT))
2758   {
2759     __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
2760     hsdio->ErrorCode |= HAL_SDIO_ERROR_DATA_TIMEOUT;
2761     hsdio->State = HAL_SDIO_STATE_READY;
2762     hsdio->Context = SDIO_CONTEXT_NONE;
2763     return HAL_ERROR;
2764   }
2765   else if (__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_DCRCFAIL))
2766   {
2767     __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
2768     hsdio->ErrorCode |= HAL_SDIO_ERROR_DATA_CRC_FAIL;
2769     hsdio->State = HAL_SDIO_STATE_READY;
2770     hsdio->Context = SDIO_CONTEXT_NONE;
2771     return HAL_ERROR;
2772   }
2773   else if (__HAL_SDIO_GET_FLAG(hsdio, SDMMC_FLAG_TXUNDERR))
2774   {
2775     __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_FLAGS);
2776     hsdio->ErrorCode |= HAL_SDIO_ERROR_TX_UNDERRUN;
2777     hsdio->State = HAL_SDIO_STATE_READY;
2778     hsdio->Context = SDIO_CONTEXT_NONE;
2779     return HAL_ERROR;
2780   }
2781   else if (hsdio->ErrorCode == SDMMC_ERROR_INVALID_PARAMETER)
2782   {
2783     __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_DATA_FLAGS);
2784     hsdio->State = HAL_SDIO_STATE_READY;
2785     hsdio->Context = SDIO_CONTEXT_NONE;
2786     return HAL_ERROR;
2787   }
2788   else
2789   {
2790     /* Nothing to do */
2791   }
2792 
2793   __HAL_SDIO_CLEAR_FLAG(hsdio, SDMMC_STATIC_DATA_FLAGS);
2794 
2795   return HAL_OK;
2796 }
2797 
2798 /**
2799   * @brief  Allows to convert a block size in the according SDMMC value for configuring the SDMMC when doing a CMD53
2800   * @param  hsdio: Pointer to the SDIO handle.
2801   * @param  block_size: block size in bytes
2802   * @retval block size as DBLOCKSIZE[3:0] bits format
2803   */
SDIO_Convert_Block_Size(SDIO_HandleTypeDef * hsdio,uint32_t block_size)2804 static uint8_t SDIO_Convert_Block_Size(SDIO_HandleTypeDef *hsdio, uint32_t block_size)
2805 {
2806   UNUSED(hsdio);
2807 
2808   uint8_t most_bit = (uint8_t)__CLZ(__RBIT(block_size));
2809   /*(1 << most_bit) - 1) is the mask used for blocksize*/
2810   if (((uint8_t)block_size & ((1U << most_bit) - 1U)) != 0U)
2811   {
2812     return (uint8_t)SDMMC_DATABLOCK_SIZE_4B;
2813   }
2814   return most_bit << SDMMC_DCTRL_DBLOCKSIZE_Pos;
2815 }
2816 
2817 /*!
2818  * @brief SDIO card io pending interrupt handle function.
2819  * @note  This function is used to handle the pending io interrupt.
2820  *        To register a IO IRQ handler, Use HAL_SDIO_EnableIOInterrupt and HAL_SDIO_SetIOIRQHandler
2821  * @param  hsdio: Pointer to SDIO handle
2822  * @retval HAL status
2823  */
SDIO_IOFunction_IRQHandler(SDIO_HandleTypeDef * hsdio)2824 static HAL_StatusTypeDef SDIO_IOFunction_IRQHandler(SDIO_HandleTypeDef *hsdio)
2825 {
2826   uint8_t count;
2827   uint8_t pendingInt;
2828 
2829   if (hsdio->IOInterruptNbr == 1U)
2830   {
2831     if ((hsdio->SDIO_IOFunction_Callback[hsdio->IOFunctionMask - 1U]) != NULL)
2832     {
2833       (hsdio->SDIO_IOFunction_Callback[hsdio->IOFunctionMask - 1U])(hsdio, hsdio->IOFunctionMask - 1U);
2834     }
2835   }
2836   else if ((hsdio->IOInterruptNbr > 1U) && (hsdio->IOFunctionMask != 0U))
2837   {
2838     /* Get pending int firstly */
2839     if (SDIO_ReadDirect(hsdio, SDMMC_SDIO_CCCR4_SD_BYTE1, HAL_SDIO_WRITE_ONLY, SDIO_FUNCTION_0, &pendingInt) !=
2840         HAL_OK)
2841     {
2842       return HAL_ERROR;
2843     }
2844 
2845     if ((pendingInt != 0U) && (hsdio->IOFunctionMask != 0U))
2846     {
2847       for (count = 1; count <= SDIO_MAX_IO_NUMBER; count++)
2848       {
2849         if (((pendingInt & (1U << count)) != 0U) && (((1U << count)  & hsdio->IOFunctionMask) != 0U))
2850         {
2851           if ((hsdio->SDIO_IOFunction_Callback[count - 1U]) != NULL)
2852           {
2853             (hsdio->SDIO_IOFunction_Callback[count - 1U])(hsdio, count);
2854           }
2855         }
2856       }
2857     }
2858   }
2859   else
2860   {
2861     /* Nothing to do */
2862   }
2863 
2864   return HAL_OK;
2865 }
2866 /**
2867   * @}
2868   */
2869 #endif /* HAL_SDIO_MODULE_ENABLED */
2870 #endif /* SDMMC1 || SDMMC2 */
2871 /**
2872   * @}
2873   */
2874 
2875 /**
2876   * @}
2877   */
2878