1 | /**
|
---|
2 | ******************************************************************************
|
---|
3 | * @file stm32f4xx_ll_sdmmc.c
|
---|
4 | * @author MCD Application Team
|
---|
5 | * @brief SDMMC Low Layer HAL module driver.
|
---|
6 | *
|
---|
7 | * This file provides firmware functions to manage the following
|
---|
8 | * functionalities of the SDMMC peripheral:
|
---|
9 | * + Initialization/de-initialization functions
|
---|
10 | * + I/O operation functions
|
---|
11 | * + Peripheral Control functions
|
---|
12 | * + Peripheral State functions
|
---|
13 | *
|
---|
14 | @verbatim
|
---|
15 | ==============================================================================
|
---|
16 | ##### SDMMC peripheral features #####
|
---|
17 | ==============================================================================
|
---|
18 | [..] The SD/SDMMC MMC card host interface (SDMMC) provides an interface between the AHB
|
---|
19 | peripheral bus and MultiMedia cards (MMCs), SD memory cards, SDMMC cards and CE-ATA
|
---|
20 | devices.
|
---|
21 |
|
---|
22 | [..] The SDMMC features include the following:
|
---|
23 | (+) Full compliance with MultiMedia Card System Specification Version 4.2. Card support
|
---|
24 | for three different databus modes: 1-bit (default), 4-bit and 8-bit
|
---|
25 | (+) Full compatibility with previous versions of MultiMedia Cards (forward compatibility)
|
---|
26 | (+) Full compliance with SD Memory Card Specifications Version 2.0
|
---|
27 | (+) Full compliance with SD I/O Card Specification Version 2.0: card support for two
|
---|
28 | different data bus modes: 1-bit (default) and 4-bit
|
---|
29 | (+) Full support of the CE-ATA features (full compliance with CE-ATA digital protocol
|
---|
30 | Rev1.1)
|
---|
31 | (+) Data transfer up to 48 MHz for the 8 bit mode
|
---|
32 | (+) Data and command output enable signals to control external bidirectional drivers
|
---|
33 |
|
---|
34 | ##### How to use this driver #####
|
---|
35 | ==============================================================================
|
---|
36 | [..]
|
---|
37 | This driver is a considered as a driver of service for external devices drivers
|
---|
38 | that interfaces with the SDMMC peripheral.
|
---|
39 | According to the device used (SD card/ MMC card / SDMMC card ...), a set of APIs
|
---|
40 | is used in the device's driver to perform SDMMC operations and functionalities.
|
---|
41 |
|
---|
42 | This driver is almost transparent for the final user, it is only used to implement other
|
---|
43 | functionalities of the external device.
|
---|
44 |
|
---|
45 | [..]
|
---|
46 | (+) The SDMMC clock (SDMMCCLK = 48 MHz) is coming from a specific output (MSI, PLLUSB1CLK,
|
---|
47 | PLLUSB2CLK). Before start working with SDMMC peripheral make sure that the
|
---|
48 | PLL is well configured.
|
---|
49 | The SDMMC peripheral uses two clock signals:
|
---|
50 | (++) SDMMC adapter clock (SDMMCCLK = 48 MHz)
|
---|
51 | (++) APB2 bus clock (PCLK2)
|
---|
52 |
|
---|
53 | -@@- PCLK2 and SDMMC_CK clock frequencies must respect the following condition:
|
---|
54 | Frequency(PCLK2) >= (3 / 8 x Frequency(SDMMC_CK))
|
---|
55 |
|
---|
56 | (+) Enable/Disable peripheral clock using RCC peripheral macros related to SDMMC
|
---|
57 | peripheral.
|
---|
58 |
|
---|
59 | (+) Enable the Power ON State using the SDIO_PowerState_ON()
|
---|
60 | function and disable it using the function SDIO_PowerState_OFF().
|
---|
61 |
|
---|
62 | (+) Enable/Disable the clock using the __SDIO_ENABLE()/__SDIO_DISABLE() macros.
|
---|
63 |
|
---|
64 | (+) Enable/Disable the peripheral interrupts using the macros __SDIO_ENABLE_IT()
|
---|
65 | and __SDIO_DISABLE_IT() if you need to use interrupt mode.
|
---|
66 |
|
---|
67 | (+) When using the DMA mode
|
---|
68 | (++) Configure the DMA in the MSP layer of the external device
|
---|
69 | (++) Active the needed channel Request
|
---|
70 | (++) Enable the DMA using __SDIO_DMA_ENABLE() macro or Disable it using the macro
|
---|
71 | __SDIO_DMA_DISABLE().
|
---|
72 |
|
---|
73 | (+) To control the CPSM (Command Path State Machine) and send
|
---|
74 | commands to the card use the SDIO_SendCommand(),
|
---|
75 | SDIO_GetCommandResponse() and SDIO_GetResponse() functions. First, user has
|
---|
76 | to fill the command structure (pointer to SDIO_CmdInitTypeDef) according
|
---|
77 | to the selected command to be sent.
|
---|
78 | The parameters that should be filled are:
|
---|
79 | (++) Command Argument
|
---|
80 | (++) Command Index
|
---|
81 | (++) Command Response type
|
---|
82 | (++) Command Wait
|
---|
83 | (++) CPSM Status (Enable or Disable).
|
---|
84 |
|
---|
85 | -@@- To check if the command is well received, read the SDIO_CMDRESP
|
---|
86 | register using the SDIO_GetCommandResponse().
|
---|
87 | The SDMMC responses registers (SDIO_RESP1 to SDIO_RESP2), use the
|
---|
88 | SDIO_GetResponse() function.
|
---|
89 |
|
---|
90 | (+) To control the DPSM (Data Path State Machine) and send/receive
|
---|
91 | data to/from the card use the SDIO_DataConfig(), SDIO_GetDataCounter(),
|
---|
92 | SDIO_ReadFIFO(), SDIO_WriteFIFO() and SDIO_GetFIFOCount() functions.
|
---|
93 |
|
---|
94 | *** Read Operations ***
|
---|
95 | =======================
|
---|
96 | [..]
|
---|
97 | (#) First, user has to fill the data structure (pointer to
|
---|
98 | SDIO_DataInitTypeDef) according to the selected data type to be received.
|
---|
99 | The parameters that should be filled are:
|
---|
100 | (++) Data TimeOut
|
---|
101 | (++) Data Length
|
---|
102 | (++) Data Block size
|
---|
103 | (++) Data Transfer direction: should be from card (To SDMMC)
|
---|
104 | (++) Data Transfer mode
|
---|
105 | (++) DPSM Status (Enable or Disable)
|
---|
106 |
|
---|
107 | (#) Configure the SDMMC resources to receive the data from the card
|
---|
108 | according to selected transfer mode (Refer to Step 8, 9 and 10).
|
---|
109 |
|
---|
110 | (#) Send the selected Read command (refer to step 11).
|
---|
111 |
|
---|
112 | (#) Use the SDIO flags/interrupts to check the transfer status.
|
---|
113 |
|
---|
114 | *** Write Operations ***
|
---|
115 | ========================
|
---|
116 | [..]
|
---|
117 | (#) First, user has to fill the data structure (pointer to
|
---|
118 | SDIO_DataInitTypeDef) according to the selected data type to be received.
|
---|
119 | The parameters that should be filled are:
|
---|
120 | (++) Data TimeOut
|
---|
121 | (++) Data Length
|
---|
122 | (++) Data Block size
|
---|
123 | (++) Data Transfer direction: should be to card (To CARD)
|
---|
124 | (++) Data Transfer mode
|
---|
125 | (++) DPSM Status (Enable or Disable)
|
---|
126 |
|
---|
127 | (#) Configure the SDMMC resources to send the data to the card according to
|
---|
128 | selected transfer mode.
|
---|
129 |
|
---|
130 | (#) Send the selected Write command.
|
---|
131 |
|
---|
132 | (#) Use the SDIO flags/interrupts to check the transfer status.
|
---|
133 |
|
---|
134 | *** Command management operations ***
|
---|
135 | =====================================
|
---|
136 | [..]
|
---|
137 | (#) The commands used for Read/Write/Erase operations are managed in
|
---|
138 | separate functions.
|
---|
139 | Each function allows to send the needed command with the related argument,
|
---|
140 | then check the response.
|
---|
141 | By the same approach, you could implement a command and check the response.
|
---|
142 |
|
---|
143 | @endverbatim
|
---|
144 | ******************************************************************************
|
---|
145 | * @attention
|
---|
146 | *
|
---|
147 | * <h2><center>© Copyright (c) 2017 STMicroelectronics.
|
---|
148 | * All rights reserved.</center></h2>
|
---|
149 | *
|
---|
150 | * This software component is licensed by ST under BSD 3-Clause license,
|
---|
151 | * the "License"; You may not use this file except in compliance with the
|
---|
152 | * License. You may obtain a copy of the License at:
|
---|
153 | * opensource.org/licenses/BSD-3-Clause
|
---|
154 | *
|
---|
155 | ******************************************************************************
|
---|
156 | */
|
---|
157 |
|
---|
158 | /* Includes ------------------------------------------------------------------*/
|
---|
159 | #include "stm32f4xx_hal.h"
|
---|
160 |
|
---|
161 | #if defined(SDIO)
|
---|
162 |
|
---|
163 | /** @addtogroup STM32F4xx_HAL_Driver
|
---|
164 | * @{
|
---|
165 | */
|
---|
166 |
|
---|
167 | /** @defgroup SDMMC_LL SDMMC Low Layer
|
---|
168 | * @brief Low layer module for SD
|
---|
169 | * @{
|
---|
170 | */
|
---|
171 |
|
---|
172 | #if defined(HAL_SD_MODULE_ENABLED) || defined(HAL_MMC_MODULE_ENABLED)
|
---|
173 |
|
---|
174 | /* Private typedef -----------------------------------------------------------*/
|
---|
175 | /* Private define ------------------------------------------------------------*/
|
---|
176 | /* Private macro -------------------------------------------------------------*/
|
---|
177 | /* Private variables ---------------------------------------------------------*/
|
---|
178 | /* Private function prototypes -----------------------------------------------*/
|
---|
179 | static uint32_t SDMMC_GetCmdError(SDIO_TypeDef *SDIOx);
|
---|
180 | static uint32_t SDMMC_GetCmdResp1(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint32_t Timeout);
|
---|
181 | static uint32_t SDMMC_GetCmdResp2(SDIO_TypeDef *SDIOx);
|
---|
182 | static uint32_t SDMMC_GetCmdResp3(SDIO_TypeDef *SDIOx);
|
---|
183 | static uint32_t SDMMC_GetCmdResp7(SDIO_TypeDef *SDIOx);
|
---|
184 | static uint32_t SDMMC_GetCmdResp6(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint16_t *pRCA);
|
---|
185 |
|
---|
186 | /* Exported functions --------------------------------------------------------*/
|
---|
187 |
|
---|
188 | /** @defgroup SDMMC_LL_Exported_Functions SDMMC Low Layer Exported Functions
|
---|
189 | * @{
|
---|
190 | */
|
---|
191 |
|
---|
192 | /** @defgroup HAL_SDMMC_LL_Group1 Initialization de-initialization functions
|
---|
193 | * @brief Initialization and Configuration functions
|
---|
194 | *
|
---|
195 | @verbatim
|
---|
196 | ===============================================================================
|
---|
197 | ##### Initialization/de-initialization functions #####
|
---|
198 | ===============================================================================
|
---|
199 | [..] This section provides functions allowing to:
|
---|
200 |
|
---|
201 | @endverbatim
|
---|
202 | * @{
|
---|
203 | */
|
---|
204 |
|
---|
205 | /**
|
---|
206 | * @brief Initializes the SDMMC according to the specified
|
---|
207 | * parameters in the SDMMC_InitTypeDef and create the associated handle.
|
---|
208 | * @param SDIOx: Pointer to SDMMC register base
|
---|
209 | * @param Init: SDMMC initialization structure
|
---|
210 | * @retval HAL status
|
---|
211 | */
|
---|
212 | HAL_StatusTypeDef SDIO_Init(SDIO_TypeDef *SDIOx, SDIO_InitTypeDef Init)
|
---|
213 | {
|
---|
214 | uint32_t tmpreg = 0;
|
---|
215 |
|
---|
216 | /* Check the parameters */
|
---|
217 | assert_param(IS_SDIO_ALL_INSTANCE(SDIOx));
|
---|
218 | assert_param(IS_SDIO_CLOCK_EDGE(Init.ClockEdge));
|
---|
219 | assert_param(IS_SDIO_CLOCK_BYPASS(Init.ClockBypass));
|
---|
220 | assert_param(IS_SDIO_CLOCK_POWER_SAVE(Init.ClockPowerSave));
|
---|
221 | assert_param(IS_SDIO_BUS_WIDE(Init.BusWide));
|
---|
222 | assert_param(IS_SDIO_HARDWARE_FLOW_CONTROL(Init.HardwareFlowControl));
|
---|
223 | assert_param(IS_SDIO_CLKDIV(Init.ClockDiv));
|
---|
224 |
|
---|
225 | /* Set SDMMC configuration parameters */
|
---|
226 | tmpreg |= (Init.ClockEdge |\
|
---|
227 | Init.ClockBypass |\
|
---|
228 | Init.ClockPowerSave |\
|
---|
229 | Init.BusWide |\
|
---|
230 | Init.HardwareFlowControl |\
|
---|
231 | Init.ClockDiv
|
---|
232 | );
|
---|
233 |
|
---|
234 | /* Write to SDMMC CLKCR */
|
---|
235 | MODIFY_REG(SDIOx->CLKCR, CLKCR_CLEAR_MASK, tmpreg);
|
---|
236 |
|
---|
237 | return HAL_OK;
|
---|
238 | }
|
---|
239 |
|
---|
240 |
|
---|
241 | /**
|
---|
242 | * @}
|
---|
243 | */
|
---|
244 |
|
---|
245 | /** @defgroup HAL_SDMMC_LL_Group2 IO operation functions
|
---|
246 | * @brief Data transfers functions
|
---|
247 | *
|
---|
248 | @verbatim
|
---|
249 | ===============================================================================
|
---|
250 | ##### I/O operation functions #####
|
---|
251 | ===============================================================================
|
---|
252 | [..]
|
---|
253 | This subsection provides a set of functions allowing to manage the SDMMC data
|
---|
254 | transfers.
|
---|
255 |
|
---|
256 | @endverbatim
|
---|
257 | * @{
|
---|
258 | */
|
---|
259 |
|
---|
260 | /**
|
---|
261 | * @brief Read data (word) from Rx FIFO in blocking mode (polling)
|
---|
262 | * @param SDIOx: Pointer to SDMMC register base
|
---|
263 | * @retval HAL status
|
---|
264 | */
|
---|
265 | uint32_t SDIO_ReadFIFO(SDIO_TypeDef *SDIOx)
|
---|
266 | {
|
---|
267 | /* Read data from Rx FIFO */
|
---|
268 | return (SDIOx->FIFO);
|
---|
269 | }
|
---|
270 |
|
---|
271 | /**
|
---|
272 | * @brief Write data (word) to Tx FIFO in blocking mode (polling)
|
---|
273 | * @param SDIOx: Pointer to SDMMC register base
|
---|
274 | * @param pWriteData: pointer to data to write
|
---|
275 | * @retval HAL status
|
---|
276 | */
|
---|
277 | HAL_StatusTypeDef SDIO_WriteFIFO(SDIO_TypeDef *SDIOx, uint32_t *pWriteData)
|
---|
278 | {
|
---|
279 | /* Write data to FIFO */
|
---|
280 | SDIOx->FIFO = *pWriteData;
|
---|
281 |
|
---|
282 | return HAL_OK;
|
---|
283 | }
|
---|
284 |
|
---|
285 | /**
|
---|
286 | * @}
|
---|
287 | */
|
---|
288 |
|
---|
289 | /** @defgroup HAL_SDMMC_LL_Group3 Peripheral Control functions
|
---|
290 | * @brief management functions
|
---|
291 | *
|
---|
292 | @verbatim
|
---|
293 | ===============================================================================
|
---|
294 | ##### Peripheral Control functions #####
|
---|
295 | ===============================================================================
|
---|
296 | [..]
|
---|
297 | This subsection provides a set of functions allowing to control the SDMMC data
|
---|
298 | transfers.
|
---|
299 |
|
---|
300 | @endverbatim
|
---|
301 | * @{
|
---|
302 | */
|
---|
303 |
|
---|
304 | /**
|
---|
305 | * @brief Set SDMMC Power state to ON.
|
---|
306 | * @param SDIOx: Pointer to SDMMC register base
|
---|
307 | * @retval HAL status
|
---|
308 | */
|
---|
309 | HAL_StatusTypeDef SDIO_PowerState_ON(SDIO_TypeDef *SDIOx)
|
---|
310 | {
|
---|
311 | /* Set power state to ON */
|
---|
312 | SDIOx->POWER = SDIO_POWER_PWRCTRL;
|
---|
313 |
|
---|
314 | /* 1ms: required power up waiting time before starting the SD initialization
|
---|
315 | sequence */
|
---|
316 | HAL_Delay(2);
|
---|
317 |
|
---|
318 | return HAL_OK;
|
---|
319 | }
|
---|
320 |
|
---|
321 | /**
|
---|
322 | * @brief Set SDMMC Power state to OFF.
|
---|
323 | * @param SDIOx: Pointer to SDMMC register base
|
---|
324 | * @retval HAL status
|
---|
325 | */
|
---|
326 | HAL_StatusTypeDef SDIO_PowerState_OFF(SDIO_TypeDef *SDIOx)
|
---|
327 | {
|
---|
328 | /* Set power state to OFF */
|
---|
329 | SDIOx->POWER = (uint32_t)0x00000000;
|
---|
330 |
|
---|
331 | return HAL_OK;
|
---|
332 | }
|
---|
333 |
|
---|
334 | /**
|
---|
335 | * @brief Get SDMMC Power state.
|
---|
336 | * @param SDIOx: Pointer to SDMMC register base
|
---|
337 | * @retval Power status of the controller. The returned value can be one of the
|
---|
338 | * following values:
|
---|
339 | * - 0x00: Power OFF
|
---|
340 | * - 0x02: Power UP
|
---|
341 | * - 0x03: Power ON
|
---|
342 | */
|
---|
343 | uint32_t SDIO_GetPowerState(SDIO_TypeDef *SDIOx)
|
---|
344 | {
|
---|
345 | return (SDIOx->POWER & SDIO_POWER_PWRCTRL);
|
---|
346 | }
|
---|
347 |
|
---|
348 | /**
|
---|
349 | * @brief Configure the SDMMC command path according to the specified parameters in
|
---|
350 | * SDIO_CmdInitTypeDef structure and send the command
|
---|
351 | * @param SDIOx: Pointer to SDMMC register base
|
---|
352 | * @param Command: pointer to a SDIO_CmdInitTypeDef structure that contains
|
---|
353 | * the configuration information for the SDMMC command
|
---|
354 | * @retval HAL status
|
---|
355 | */
|
---|
356 | HAL_StatusTypeDef SDIO_SendCommand(SDIO_TypeDef *SDIOx, SDIO_CmdInitTypeDef *Command)
|
---|
357 | {
|
---|
358 | uint32_t tmpreg = 0;
|
---|
359 |
|
---|
360 | /* Check the parameters */
|
---|
361 | assert_param(IS_SDIO_CMD_INDEX(Command->CmdIndex));
|
---|
362 | assert_param(IS_SDIO_RESPONSE(Command->Response));
|
---|
363 | assert_param(IS_SDIO_WAIT(Command->WaitForInterrupt));
|
---|
364 | assert_param(IS_SDIO_CPSM(Command->CPSM));
|
---|
365 |
|
---|
366 | /* Set the SDMMC Argument value */
|
---|
367 | SDIOx->ARG = Command->Argument;
|
---|
368 |
|
---|
369 | /* Set SDMMC command parameters */
|
---|
370 | tmpreg |= (uint32_t)(Command->CmdIndex |\
|
---|
371 | Command->Response |\
|
---|
372 | Command->WaitForInterrupt |\
|
---|
373 | Command->CPSM);
|
---|
374 |
|
---|
375 | /* Write to SDMMC CMD register */
|
---|
376 | MODIFY_REG(SDIOx->CMD, CMD_CLEAR_MASK, tmpreg);
|
---|
377 |
|
---|
378 | return HAL_OK;
|
---|
379 | }
|
---|
380 |
|
---|
381 | /**
|
---|
382 | * @brief Return the command index of last command for which response received
|
---|
383 | * @param SDIOx: Pointer to SDMMC register base
|
---|
384 | * @retval Command index of the last command response received
|
---|
385 | */
|
---|
386 | uint8_t SDIO_GetCommandResponse(SDIO_TypeDef *SDIOx)
|
---|
387 | {
|
---|
388 | return (uint8_t)(SDIOx->RESPCMD);
|
---|
389 | }
|
---|
390 |
|
---|
391 |
|
---|
392 | /**
|
---|
393 | * @brief Return the response received from the card for the last command
|
---|
394 | * @param SDIOx: Pointer to SDMMC register base
|
---|
395 | * @param Response: Specifies the SDMMC response register.
|
---|
396 | * This parameter can be one of the following values:
|
---|
397 | * @arg SDIO_RESP1: Response Register 1
|
---|
398 | * @arg SDIO_RESP2: Response Register 2
|
---|
399 | * @arg SDIO_RESP3: Response Register 3
|
---|
400 | * @arg SDIO_RESP4: Response Register 4
|
---|
401 | * @retval The Corresponding response register value
|
---|
402 | */
|
---|
403 | uint32_t SDIO_GetResponse(SDIO_TypeDef *SDIOx, uint32_t Response)
|
---|
404 | {
|
---|
405 | uint32_t tmp;
|
---|
406 |
|
---|
407 | /* Check the parameters */
|
---|
408 | assert_param(IS_SDIO_RESP(Response));
|
---|
409 |
|
---|
410 | /* Get the response */
|
---|
411 | tmp = (uint32_t)(&(SDIOx->RESP1)) + Response;
|
---|
412 |
|
---|
413 | return (*(__IO uint32_t *) tmp);
|
---|
414 | }
|
---|
415 |
|
---|
416 | /**
|
---|
417 | * @brief Configure the SDMMC data path according to the specified
|
---|
418 | * parameters in the SDIO_DataInitTypeDef.
|
---|
419 | * @param SDIOx: Pointer to SDIO register base
|
---|
420 | * @param Data : pointer to a SDIO_DataInitTypeDef structure
|
---|
421 | * that contains the configuration information for the SDMMC data.
|
---|
422 | * @retval HAL status
|
---|
423 | */
|
---|
424 | HAL_StatusTypeDef SDIO_ConfigData(SDIO_TypeDef *SDIOx, SDIO_DataInitTypeDef* Data)
|
---|
425 | {
|
---|
426 | uint32_t tmpreg = 0;
|
---|
427 |
|
---|
428 | /* Check the parameters */
|
---|
429 | assert_param(IS_SDIO_DATA_LENGTH(Data->DataLength));
|
---|
430 | assert_param(IS_SDIO_BLOCK_SIZE(Data->DataBlockSize));
|
---|
431 | assert_param(IS_SDIO_TRANSFER_DIR(Data->TransferDir));
|
---|
432 | assert_param(IS_SDIO_TRANSFER_MODE(Data->TransferMode));
|
---|
433 | assert_param(IS_SDIO_DPSM(Data->DPSM));
|
---|
434 |
|
---|
435 | /* Set the SDMMC Data TimeOut value */
|
---|
436 | SDIOx->DTIMER = Data->DataTimeOut;
|
---|
437 |
|
---|
438 | /* Set the SDMMC DataLength value */
|
---|
439 | SDIOx->DLEN = Data->DataLength;
|
---|
440 |
|
---|
441 | /* Set the SDMMC data configuration parameters */
|
---|
442 | tmpreg |= (uint32_t)(Data->DataBlockSize |\
|
---|
443 | Data->TransferDir |\
|
---|
444 | Data->TransferMode |\
|
---|
445 | Data->DPSM);
|
---|
446 |
|
---|
447 | /* Write to SDMMC DCTRL */
|
---|
448 | MODIFY_REG(SDIOx->DCTRL, DCTRL_CLEAR_MASK, tmpreg);
|
---|
449 |
|
---|
450 | return HAL_OK;
|
---|
451 |
|
---|
452 | }
|
---|
453 |
|
---|
454 | /**
|
---|
455 | * @brief Returns number of remaining data bytes to be transferred.
|
---|
456 | * @param SDIOx: Pointer to SDIO register base
|
---|
457 | * @retval Number of remaining data bytes to be transferred
|
---|
458 | */
|
---|
459 | uint32_t SDIO_GetDataCounter(SDIO_TypeDef *SDIOx)
|
---|
460 | {
|
---|
461 | return (SDIOx->DCOUNT);
|
---|
462 | }
|
---|
463 |
|
---|
464 | /**
|
---|
465 | * @brief Get the FIFO data
|
---|
466 | * @param SDIOx: Pointer to SDIO register base
|
---|
467 | * @retval Data received
|
---|
468 | */
|
---|
469 | uint32_t SDIO_GetFIFOCount(SDIO_TypeDef *SDIOx)
|
---|
470 | {
|
---|
471 | return (SDIOx->FIFO);
|
---|
472 | }
|
---|
473 |
|
---|
474 | /**
|
---|
475 | * @brief Sets one of the two options of inserting read wait interval.
|
---|
476 | * @param SDIOx: Pointer to SDIO register base
|
---|
477 | * @param SDIO_ReadWaitMode: SDMMC Read Wait operation mode.
|
---|
478 | * This parameter can be:
|
---|
479 | * @arg SDIO_READ_WAIT_MODE_CLK: Read Wait control by stopping SDMMCCLK
|
---|
480 | * @arg SDIO_READ_WAIT_MODE_DATA2: Read Wait control using SDMMC_DATA2
|
---|
481 | * @retval None
|
---|
482 | */
|
---|
483 | HAL_StatusTypeDef SDIO_SetSDMMCReadWaitMode(SDIO_TypeDef *SDIOx, uint32_t SDIO_ReadWaitMode)
|
---|
484 | {
|
---|
485 | /* Check the parameters */
|
---|
486 | assert_param(IS_SDIO_READWAIT_MODE(SDIO_ReadWaitMode));
|
---|
487 |
|
---|
488 | /* Set SDMMC read wait mode */
|
---|
489 | MODIFY_REG(SDIOx->DCTRL, SDIO_DCTRL_RWMOD, SDIO_ReadWaitMode);
|
---|
490 |
|
---|
491 | return HAL_OK;
|
---|
492 | }
|
---|
493 |
|
---|
494 | /**
|
---|
495 | * @}
|
---|
496 | */
|
---|
497 |
|
---|
498 |
|
---|
499 | /** @defgroup HAL_SDMMC_LL_Group4 Command management functions
|
---|
500 | * @brief Data transfers functions
|
---|
501 | *
|
---|
502 | @verbatim
|
---|
503 | ===============================================================================
|
---|
504 | ##### Commands management functions #####
|
---|
505 | ===============================================================================
|
---|
506 | [..]
|
---|
507 | This subsection provides a set of functions allowing to manage the needed commands.
|
---|
508 |
|
---|
509 | @endverbatim
|
---|
510 | * @{
|
---|
511 | */
|
---|
512 |
|
---|
513 | /**
|
---|
514 | * @brief Send the Data Block Length command and check the response
|
---|
515 | * @param SDIOx: Pointer to SDIO register base
|
---|
516 | * @retval HAL status
|
---|
517 | */
|
---|
518 | uint32_t SDMMC_CmdBlockLength(SDIO_TypeDef *SDIOx, uint32_t BlockSize)
|
---|
519 | {
|
---|
520 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
521 | uint32_t errorstate;
|
---|
522 |
|
---|
523 | /* Set Block Size for Card */
|
---|
524 | sdmmc_cmdinit.Argument = (uint32_t)BlockSize;
|
---|
525 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SET_BLOCKLEN;
|
---|
526 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
527 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
528 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
529 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
530 |
|
---|
531 | /* Check for error conditions */
|
---|
532 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SET_BLOCKLEN, SDIO_CMDTIMEOUT);
|
---|
533 |
|
---|
534 | return errorstate;
|
---|
535 | }
|
---|
536 |
|
---|
537 | /**
|
---|
538 | * @brief Send the Read Single Block command and check the response
|
---|
539 | * @param SDIOx: Pointer to SDIO register base
|
---|
540 | * @retval HAL status
|
---|
541 | */
|
---|
542 | uint32_t SDMMC_CmdReadSingleBlock(SDIO_TypeDef *SDIOx, uint32_t ReadAdd)
|
---|
543 | {
|
---|
544 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
545 | uint32_t errorstate;
|
---|
546 |
|
---|
547 | /* Set Block Size for Card */
|
---|
548 | sdmmc_cmdinit.Argument = (uint32_t)ReadAdd;
|
---|
549 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_READ_SINGLE_BLOCK;
|
---|
550 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
551 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
552 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
553 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
554 |
|
---|
555 | /* Check for error conditions */
|
---|
556 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_READ_SINGLE_BLOCK, SDIO_CMDTIMEOUT);
|
---|
557 |
|
---|
558 | return errorstate;
|
---|
559 | }
|
---|
560 |
|
---|
561 | /**
|
---|
562 | * @brief Send the Read Multi Block command and check the response
|
---|
563 | * @param SDIOx: Pointer to SDIO register base
|
---|
564 | * @retval HAL status
|
---|
565 | */
|
---|
566 | uint32_t SDMMC_CmdReadMultiBlock(SDIO_TypeDef *SDIOx, uint32_t ReadAdd)
|
---|
567 | {
|
---|
568 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
569 | uint32_t errorstate;
|
---|
570 |
|
---|
571 | /* Set Block Size for Card */
|
---|
572 | sdmmc_cmdinit.Argument = (uint32_t)ReadAdd;
|
---|
573 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_READ_MULT_BLOCK;
|
---|
574 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
575 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
576 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
577 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
578 |
|
---|
579 | /* Check for error conditions */
|
---|
580 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_READ_MULT_BLOCK, SDIO_CMDTIMEOUT);
|
---|
581 |
|
---|
582 | return errorstate;
|
---|
583 | }
|
---|
584 |
|
---|
585 | /**
|
---|
586 | * @brief Send the Write Single Block command and check the response
|
---|
587 | * @param SDIOx: Pointer to SDIO register base
|
---|
588 | * @retval HAL status
|
---|
589 | */
|
---|
590 | uint32_t SDMMC_CmdWriteSingleBlock(SDIO_TypeDef *SDIOx, uint32_t WriteAdd)
|
---|
591 | {
|
---|
592 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
593 | uint32_t errorstate;
|
---|
594 |
|
---|
595 | /* Set Block Size for Card */
|
---|
596 | sdmmc_cmdinit.Argument = (uint32_t)WriteAdd;
|
---|
597 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_WRITE_SINGLE_BLOCK;
|
---|
598 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
599 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
600 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
601 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
602 |
|
---|
603 | /* Check for error conditions */
|
---|
604 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_WRITE_SINGLE_BLOCK, SDIO_CMDTIMEOUT);
|
---|
605 |
|
---|
606 | return errorstate;
|
---|
607 | }
|
---|
608 |
|
---|
609 | /**
|
---|
610 | * @brief Send the Write Multi Block command and check the response
|
---|
611 | * @param SDIOx: Pointer to SDIO register base
|
---|
612 | * @retval HAL status
|
---|
613 | */
|
---|
614 | uint32_t SDMMC_CmdWriteMultiBlock(SDIO_TypeDef *SDIOx, uint32_t WriteAdd)
|
---|
615 | {
|
---|
616 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
617 | uint32_t errorstate;
|
---|
618 |
|
---|
619 | /* Set Block Size for Card */
|
---|
620 | sdmmc_cmdinit.Argument = (uint32_t)WriteAdd;
|
---|
621 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_WRITE_MULT_BLOCK;
|
---|
622 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
623 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
624 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
625 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
626 |
|
---|
627 | /* Check for error conditions */
|
---|
628 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_WRITE_MULT_BLOCK, SDIO_CMDTIMEOUT);
|
---|
629 |
|
---|
630 | return errorstate;
|
---|
631 | }
|
---|
632 |
|
---|
633 | /**
|
---|
634 | * @brief Send the Start Address Erase command for SD and check the response
|
---|
635 | * @param SDIOx: Pointer to SDIO register base
|
---|
636 | * @retval HAL status
|
---|
637 | */
|
---|
638 | uint32_t SDMMC_CmdSDEraseStartAdd(SDIO_TypeDef *SDIOx, uint32_t StartAdd)
|
---|
639 | {
|
---|
640 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
641 | uint32_t errorstate;
|
---|
642 |
|
---|
643 | /* Set Block Size for Card */
|
---|
644 | sdmmc_cmdinit.Argument = (uint32_t)StartAdd;
|
---|
645 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_ERASE_GRP_START;
|
---|
646 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
647 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
648 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
649 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
650 |
|
---|
651 | /* Check for error conditions */
|
---|
652 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SD_ERASE_GRP_START, SDIO_CMDTIMEOUT);
|
---|
653 |
|
---|
654 | return errorstate;
|
---|
655 | }
|
---|
656 |
|
---|
657 | /**
|
---|
658 | * @brief Send the End Address Erase command for SD and check the response
|
---|
659 | * @param SDIOx: Pointer to SDIO register base
|
---|
660 | * @retval HAL status
|
---|
661 | */
|
---|
662 | uint32_t SDMMC_CmdSDEraseEndAdd(SDIO_TypeDef *SDIOx, uint32_t EndAdd)
|
---|
663 | {
|
---|
664 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
665 | uint32_t errorstate;
|
---|
666 |
|
---|
667 | /* Set Block Size for Card */
|
---|
668 | sdmmc_cmdinit.Argument = (uint32_t)EndAdd;
|
---|
669 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_ERASE_GRP_END;
|
---|
670 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
671 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
672 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
673 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
674 |
|
---|
675 | /* Check for error conditions */
|
---|
676 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SD_ERASE_GRP_END, SDIO_CMDTIMEOUT);
|
---|
677 |
|
---|
678 | return errorstate;
|
---|
679 | }
|
---|
680 |
|
---|
681 | /**
|
---|
682 | * @brief Send the Start Address Erase command and check the response
|
---|
683 | * @param SDIOx: Pointer to SDIO register base
|
---|
684 | * @retval HAL status
|
---|
685 | */
|
---|
686 | uint32_t SDMMC_CmdEraseStartAdd(SDIO_TypeDef *SDIOx, uint32_t StartAdd)
|
---|
687 | {
|
---|
688 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
689 | uint32_t errorstate;
|
---|
690 |
|
---|
691 | /* Set Block Size for Card */
|
---|
692 | sdmmc_cmdinit.Argument = (uint32_t)StartAdd;
|
---|
693 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_ERASE_GRP_START;
|
---|
694 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
695 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
696 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
697 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
698 |
|
---|
699 | /* Check for error conditions */
|
---|
700 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_ERASE_GRP_START, SDIO_CMDTIMEOUT);
|
---|
701 |
|
---|
702 | return errorstate;
|
---|
703 | }
|
---|
704 |
|
---|
705 | /**
|
---|
706 | * @brief Send the End Address Erase command and check the response
|
---|
707 | * @param SDIOx: Pointer to SDIO register base
|
---|
708 | * @retval HAL status
|
---|
709 | */
|
---|
710 | uint32_t SDMMC_CmdEraseEndAdd(SDIO_TypeDef *SDIOx, uint32_t EndAdd)
|
---|
711 | {
|
---|
712 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
713 | uint32_t errorstate;
|
---|
714 |
|
---|
715 | /* Set Block Size for Card */
|
---|
716 | sdmmc_cmdinit.Argument = (uint32_t)EndAdd;
|
---|
717 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_ERASE_GRP_END;
|
---|
718 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
719 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
720 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
721 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
722 |
|
---|
723 | /* Check for error conditions */
|
---|
724 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_ERASE_GRP_END, SDIO_CMDTIMEOUT);
|
---|
725 |
|
---|
726 | return errorstate;
|
---|
727 | }
|
---|
728 |
|
---|
729 | /**
|
---|
730 | * @brief Send the Erase command and check the response
|
---|
731 | * @param SDIOx: Pointer to SDIO register base
|
---|
732 | * @retval HAL status
|
---|
733 | */
|
---|
734 | uint32_t SDMMC_CmdErase(SDIO_TypeDef *SDIOx)
|
---|
735 | {
|
---|
736 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
737 | uint32_t errorstate;
|
---|
738 |
|
---|
739 | /* Set Block Size for Card */
|
---|
740 | sdmmc_cmdinit.Argument = 0U;
|
---|
741 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_ERASE;
|
---|
742 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
743 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
744 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
745 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
746 |
|
---|
747 | /* Check for error conditions */
|
---|
748 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_ERASE, SDIO_MAXERASETIMEOUT);
|
---|
749 |
|
---|
750 | return errorstate;
|
---|
751 | }
|
---|
752 |
|
---|
753 | /**
|
---|
754 | * @brief Send the Stop Transfer command and check the response.
|
---|
755 | * @param SDIOx: Pointer to SDIO register base
|
---|
756 | * @retval HAL status
|
---|
757 | */
|
---|
758 | uint32_t SDMMC_CmdStopTransfer(SDIO_TypeDef *SDIOx)
|
---|
759 | {
|
---|
760 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
761 | uint32_t errorstate;
|
---|
762 |
|
---|
763 | /* Send CMD12 STOP_TRANSMISSION */
|
---|
764 | sdmmc_cmdinit.Argument = 0U;
|
---|
765 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_STOP_TRANSMISSION;
|
---|
766 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
767 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
768 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
769 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
770 |
|
---|
771 | /* Check for error conditions */
|
---|
772 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_STOP_TRANSMISSION, SDIO_STOPTRANSFERTIMEOUT);
|
---|
773 |
|
---|
774 | return errorstate;
|
---|
775 | }
|
---|
776 |
|
---|
777 | /**
|
---|
778 | * @brief Send the Select Deselect command and check the response.
|
---|
779 | * @param SDIOx: Pointer to SDIO register base
|
---|
780 | * @param addr: Address of the card to be selected
|
---|
781 | * @retval HAL status
|
---|
782 | */
|
---|
783 | uint32_t SDMMC_CmdSelDesel(SDIO_TypeDef *SDIOx, uint64_t Addr)
|
---|
784 | {
|
---|
785 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
786 | uint32_t errorstate;
|
---|
787 |
|
---|
788 | /* Send CMD7 SDMMC_SEL_DESEL_CARD */
|
---|
789 | sdmmc_cmdinit.Argument = (uint32_t)Addr;
|
---|
790 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SEL_DESEL_CARD;
|
---|
791 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
792 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
793 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
794 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
795 |
|
---|
796 | /* Check for error conditions */
|
---|
797 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SEL_DESEL_CARD, SDIO_CMDTIMEOUT);
|
---|
798 |
|
---|
799 | return errorstate;
|
---|
800 | }
|
---|
801 |
|
---|
802 | /**
|
---|
803 | * @brief Send the Go Idle State command and check the response.
|
---|
804 | * @param SDIOx: Pointer to SDIO register base
|
---|
805 | * @retval HAL status
|
---|
806 | */
|
---|
807 | uint32_t SDMMC_CmdGoIdleState(SDIO_TypeDef *SDIOx)
|
---|
808 | {
|
---|
809 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
810 | uint32_t errorstate;
|
---|
811 |
|
---|
812 | sdmmc_cmdinit.Argument = 0U;
|
---|
813 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_GO_IDLE_STATE;
|
---|
814 | sdmmc_cmdinit.Response = SDIO_RESPONSE_NO;
|
---|
815 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
816 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
817 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
818 |
|
---|
819 | /* Check for error conditions */
|
---|
820 | errorstate = SDMMC_GetCmdError(SDIOx);
|
---|
821 |
|
---|
822 | return errorstate;
|
---|
823 | }
|
---|
824 |
|
---|
825 | /**
|
---|
826 | * @brief Send the Operating Condition command and check the response.
|
---|
827 | * @param SDIOx: Pointer to SDIO register base
|
---|
828 | * @retval HAL status
|
---|
829 | */
|
---|
830 | uint32_t SDMMC_CmdOperCond(SDIO_TypeDef *SDIOx)
|
---|
831 | {
|
---|
832 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
833 | uint32_t errorstate;
|
---|
834 |
|
---|
835 | /* Send CMD8 to verify SD card interface operating condition */
|
---|
836 | /* Argument: - [31:12]: Reserved (shall be set to '0')
|
---|
837 | - [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V)
|
---|
838 | - [7:0]: Check Pattern (recommended 0xAA) */
|
---|
839 | /* CMD Response: R7 */
|
---|
840 | sdmmc_cmdinit.Argument = SDMMC_CHECK_PATTERN;
|
---|
841 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_HS_SEND_EXT_CSD;
|
---|
842 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
843 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
844 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
845 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
846 |
|
---|
847 | /* Check for error conditions */
|
---|
848 | errorstate = SDMMC_GetCmdResp7(SDIOx);
|
---|
849 |
|
---|
850 | return errorstate;
|
---|
851 | }
|
---|
852 |
|
---|
853 | /**
|
---|
854 | * @brief Send the Application command to verify that that the next command
|
---|
855 | * is an application specific com-mand rather than a standard command
|
---|
856 | * and check the response.
|
---|
857 | * @param SDIOx: Pointer to SDIO register base
|
---|
858 | * @param Argument: Command Argument
|
---|
859 | * @retval HAL status
|
---|
860 | */
|
---|
861 | uint32_t SDMMC_CmdAppCommand(SDIO_TypeDef *SDIOx, uint32_t Argument)
|
---|
862 | {
|
---|
863 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
864 | uint32_t errorstate;
|
---|
865 |
|
---|
866 | sdmmc_cmdinit.Argument = (uint32_t)Argument;
|
---|
867 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_APP_CMD;
|
---|
868 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
869 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
870 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
871 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
872 |
|
---|
873 | /* Check for error conditions */
|
---|
874 | /* If there is a HAL_ERROR, it is a MMC card, else
|
---|
875 | it is a SD card: SD card 2.0 (voltage range mismatch)
|
---|
876 | or SD card 1.x */
|
---|
877 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_APP_CMD, SDIO_CMDTIMEOUT);
|
---|
878 |
|
---|
879 | return errorstate;
|
---|
880 | }
|
---|
881 |
|
---|
882 | /**
|
---|
883 | * @brief Send the command asking the accessed card to send its operating
|
---|
884 | * condition register (OCR)
|
---|
885 | * @param SDIOx: Pointer to SDIO register base
|
---|
886 | * @param Argument: Command Argument
|
---|
887 | * @retval HAL status
|
---|
888 | */
|
---|
889 | uint32_t SDMMC_CmdAppOperCommand(SDIO_TypeDef *SDIOx, uint32_t Argument)
|
---|
890 | {
|
---|
891 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
892 | uint32_t errorstate;
|
---|
893 |
|
---|
894 | sdmmc_cmdinit.Argument = SDMMC_VOLTAGE_WINDOW_SD | Argument;
|
---|
895 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_APP_OP_COND;
|
---|
896 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
897 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
898 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
899 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
900 |
|
---|
901 | /* Check for error conditions */
|
---|
902 | errorstate = SDMMC_GetCmdResp3(SDIOx);
|
---|
903 |
|
---|
904 | return errorstate;
|
---|
905 | }
|
---|
906 |
|
---|
907 | /**
|
---|
908 | * @brief Send the Bus Width command and check the response.
|
---|
909 | * @param SDIOx: Pointer to SDIO register base
|
---|
910 | * @param BusWidth: BusWidth
|
---|
911 | * @retval HAL status
|
---|
912 | */
|
---|
913 | uint32_t SDMMC_CmdBusWidth(SDIO_TypeDef *SDIOx, uint32_t BusWidth)
|
---|
914 | {
|
---|
915 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
916 | uint32_t errorstate;
|
---|
917 |
|
---|
918 | sdmmc_cmdinit.Argument = (uint32_t)BusWidth;
|
---|
919 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_APP_SD_SET_BUSWIDTH;
|
---|
920 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
921 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
922 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
923 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
924 |
|
---|
925 | /* Check for error conditions */
|
---|
926 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_APP_SD_SET_BUSWIDTH, SDIO_CMDTIMEOUT);
|
---|
927 |
|
---|
928 | return errorstate;
|
---|
929 | }
|
---|
930 |
|
---|
931 | /**
|
---|
932 | * @brief Send the Send SCR command and check the response.
|
---|
933 | * @param SDIOx: Pointer to SDIO register base
|
---|
934 | * @retval HAL status
|
---|
935 | */
|
---|
936 | uint32_t SDMMC_CmdSendSCR(SDIO_TypeDef *SDIOx)
|
---|
937 | {
|
---|
938 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
939 | uint32_t errorstate;
|
---|
940 |
|
---|
941 | /* Send CMD51 SD_APP_SEND_SCR */
|
---|
942 | sdmmc_cmdinit.Argument = 0U;
|
---|
943 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_APP_SEND_SCR;
|
---|
944 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
945 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
946 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
947 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
948 |
|
---|
949 | /* Check for error conditions */
|
---|
950 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SD_APP_SEND_SCR, SDIO_CMDTIMEOUT);
|
---|
951 |
|
---|
952 | return errorstate;
|
---|
953 | }
|
---|
954 |
|
---|
955 | /**
|
---|
956 | * @brief Send the Send CID command and check the response.
|
---|
957 | * @param SDIOx: Pointer to SDIO register base
|
---|
958 | * @retval HAL status
|
---|
959 | */
|
---|
960 | uint32_t SDMMC_CmdSendCID(SDIO_TypeDef *SDIOx)
|
---|
961 | {
|
---|
962 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
963 | uint32_t errorstate;
|
---|
964 |
|
---|
965 | /* Send CMD2 ALL_SEND_CID */
|
---|
966 | sdmmc_cmdinit.Argument = 0U;
|
---|
967 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_ALL_SEND_CID;
|
---|
968 | sdmmc_cmdinit.Response = SDIO_RESPONSE_LONG;
|
---|
969 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
970 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
971 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
972 |
|
---|
973 | /* Check for error conditions */
|
---|
974 | errorstate = SDMMC_GetCmdResp2(SDIOx);
|
---|
975 |
|
---|
976 | return errorstate;
|
---|
977 | }
|
---|
978 |
|
---|
979 | /**
|
---|
980 | * @brief Send the Send CSD command and check the response.
|
---|
981 | * @param SDIOx: Pointer to SDIO register base
|
---|
982 | * @param Argument: Command Argument
|
---|
983 | * @retval HAL status
|
---|
984 | */
|
---|
985 | uint32_t SDMMC_CmdSendCSD(SDIO_TypeDef *SDIOx, uint32_t Argument)
|
---|
986 | {
|
---|
987 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
988 | uint32_t errorstate;
|
---|
989 |
|
---|
990 | /* Send CMD9 SEND_CSD */
|
---|
991 | sdmmc_cmdinit.Argument = Argument;
|
---|
992 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SEND_CSD;
|
---|
993 | sdmmc_cmdinit.Response = SDIO_RESPONSE_LONG;
|
---|
994 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
995 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
996 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
997 |
|
---|
998 | /* Check for error conditions */
|
---|
999 | errorstate = SDMMC_GetCmdResp2(SDIOx);
|
---|
1000 |
|
---|
1001 | return errorstate;
|
---|
1002 | }
|
---|
1003 |
|
---|
1004 | /**
|
---|
1005 | * @brief Send the Send CSD command and check the response.
|
---|
1006 | * @param SDIOx: Pointer to SDIO register base
|
---|
1007 | * @param pRCA: Card RCA
|
---|
1008 | * @retval HAL status
|
---|
1009 | */
|
---|
1010 | uint32_t SDMMC_CmdSetRelAdd(SDIO_TypeDef *SDIOx, uint16_t *pRCA)
|
---|
1011 | {
|
---|
1012 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
1013 | uint32_t errorstate;
|
---|
1014 |
|
---|
1015 | /* Send CMD3 SD_CMD_SET_REL_ADDR */
|
---|
1016 | sdmmc_cmdinit.Argument = 0U;
|
---|
1017 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SET_REL_ADDR;
|
---|
1018 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
1019 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
1020 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
1021 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
1022 |
|
---|
1023 | /* Check for error conditions */
|
---|
1024 | errorstate = SDMMC_GetCmdResp6(SDIOx, SDMMC_CMD_SET_REL_ADDR, pRCA);
|
---|
1025 |
|
---|
1026 | return errorstate;
|
---|
1027 | }
|
---|
1028 |
|
---|
1029 | /**
|
---|
1030 | * @brief Send the Status command and check the response.
|
---|
1031 | * @param SDIOx: Pointer to SDIO register base
|
---|
1032 | * @param Argument: Command Argument
|
---|
1033 | * @retval HAL status
|
---|
1034 | */
|
---|
1035 | uint32_t SDMMC_CmdSendStatus(SDIO_TypeDef *SDIOx, uint32_t Argument)
|
---|
1036 | {
|
---|
1037 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
1038 | uint32_t errorstate;
|
---|
1039 |
|
---|
1040 | sdmmc_cmdinit.Argument = Argument;
|
---|
1041 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SEND_STATUS;
|
---|
1042 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
1043 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
1044 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
1045 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
1046 |
|
---|
1047 | /* Check for error conditions */
|
---|
1048 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SEND_STATUS, SDIO_CMDTIMEOUT);
|
---|
1049 |
|
---|
1050 | return errorstate;
|
---|
1051 | }
|
---|
1052 |
|
---|
1053 | /**
|
---|
1054 | * @brief Send the Status register command and check the response.
|
---|
1055 | * @param SDIOx: Pointer to SDIO register base
|
---|
1056 | * @retval HAL status
|
---|
1057 | */
|
---|
1058 | uint32_t SDMMC_CmdStatusRegister(SDIO_TypeDef *SDIOx)
|
---|
1059 | {
|
---|
1060 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
1061 | uint32_t errorstate;
|
---|
1062 |
|
---|
1063 | sdmmc_cmdinit.Argument = 0U;
|
---|
1064 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_APP_STATUS;
|
---|
1065 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
1066 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
1067 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
1068 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
1069 |
|
---|
1070 | /* Check for error conditions */
|
---|
1071 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SD_APP_STATUS, SDIO_CMDTIMEOUT);
|
---|
1072 |
|
---|
1073 | return errorstate;
|
---|
1074 | }
|
---|
1075 |
|
---|
1076 | /**
|
---|
1077 | * @brief Sends host capacity support information and activates the card's
|
---|
1078 | * initialization process. Send SDMMC_CMD_SEND_OP_COND command
|
---|
1079 | * @param SDIOx: Pointer to SDIO register base
|
---|
1080 | * @parame Argument: Argument used for the command
|
---|
1081 | * @retval HAL status
|
---|
1082 | */
|
---|
1083 | uint32_t SDMMC_CmdOpCondition(SDIO_TypeDef *SDIOx, uint32_t Argument)
|
---|
1084 | {
|
---|
1085 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
1086 | uint32_t errorstate;
|
---|
1087 |
|
---|
1088 | sdmmc_cmdinit.Argument = Argument;
|
---|
1089 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SEND_OP_COND;
|
---|
1090 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
1091 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
1092 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
1093 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
1094 |
|
---|
1095 | /* Check for error conditions */
|
---|
1096 | errorstate = SDMMC_GetCmdResp3(SDIOx);
|
---|
1097 |
|
---|
1098 | return errorstate;
|
---|
1099 | }
|
---|
1100 |
|
---|
1101 | /**
|
---|
1102 | * @brief Checks switchable function and switch card function. SDMMC_CMD_HS_SWITCH command
|
---|
1103 | * @param SDIOx: Pointer to SDIO register base
|
---|
1104 | * @parame Argument: Argument used for the command
|
---|
1105 | * @retval HAL status
|
---|
1106 | */
|
---|
1107 | uint32_t SDMMC_CmdSwitch(SDIO_TypeDef *SDIOx, uint32_t Argument)
|
---|
1108 | {
|
---|
1109 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
1110 | uint32_t errorstate;
|
---|
1111 |
|
---|
1112 | /* Send CMD6 to activate SDR50 Mode and Power Limit 1.44W */
|
---|
1113 | /* CMD Response: R1 */
|
---|
1114 | sdmmc_cmdinit.Argument = Argument; /* SDMMC_SDR25_SWITCH_PATTERN */
|
---|
1115 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_HS_SWITCH;
|
---|
1116 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
1117 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
1118 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
1119 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
1120 |
|
---|
1121 | /* Check for error conditions */
|
---|
1122 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_HS_SWITCH, SDIO_CMDTIMEOUT);
|
---|
1123 |
|
---|
1124 | return errorstate;
|
---|
1125 | }
|
---|
1126 |
|
---|
1127 | /**
|
---|
1128 | * @}
|
---|
1129 | */
|
---|
1130 |
|
---|
1131 | /* Private function ----------------------------------------------------------*/
|
---|
1132 | /** @addtogroup SD_Private_Functions
|
---|
1133 | * @{
|
---|
1134 | */
|
---|
1135 |
|
---|
1136 | /**
|
---|
1137 | * @brief Checks for error conditions for CMD0.
|
---|
1138 | * @param hsd: SD handle
|
---|
1139 | * @retval SD Card error state
|
---|
1140 | */
|
---|
1141 | static uint32_t SDMMC_GetCmdError(SDIO_TypeDef *SDIOx)
|
---|
1142 | {
|
---|
1143 | /* 8 is the number of required instructions cycles for the below loop statement.
|
---|
1144 | The SDIO_CMDTIMEOUT is expressed in ms */
|
---|
1145 | uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
|
---|
1146 |
|
---|
1147 | do
|
---|
1148 | {
|
---|
1149 | if (count-- == 0U)
|
---|
1150 | {
|
---|
1151 | return SDMMC_ERROR_TIMEOUT;
|
---|
1152 | }
|
---|
1153 |
|
---|
1154 | }while(!__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CMDSENT));
|
---|
1155 |
|
---|
1156 | /* Clear all the static flags */
|
---|
1157 | __SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS);
|
---|
1158 |
|
---|
1159 | return SDMMC_ERROR_NONE;
|
---|
1160 | }
|
---|
1161 |
|
---|
1162 | /**
|
---|
1163 | * @brief Checks for error conditions for R1 response.
|
---|
1164 | * @param hsd: SD handle
|
---|
1165 | * @param SD_CMD: The sent command index
|
---|
1166 | * @retval SD Card error state
|
---|
1167 | */
|
---|
1168 | static uint32_t SDMMC_GetCmdResp1(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint32_t Timeout)
|
---|
1169 | {
|
---|
1170 | uint32_t response_r1;
|
---|
1171 | uint32_t sta_reg;
|
---|
1172 |
|
---|
1173 | /* 8 is the number of required instructions cycles for the below loop statement.
|
---|
1174 | The Timeout is expressed in ms */
|
---|
1175 | uint32_t count = Timeout * (SystemCoreClock / 8U /1000U);
|
---|
1176 |
|
---|
1177 | do
|
---|
1178 | {
|
---|
1179 | if (count-- == 0U)
|
---|
1180 | {
|
---|
1181 | return SDMMC_ERROR_TIMEOUT;
|
---|
1182 | }
|
---|
1183 | sta_reg = SDIOx->STA;
|
---|
1184 | }while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) ||
|
---|
1185 | ((sta_reg & SDIO_FLAG_CMDACT) != 0U ));
|
---|
1186 |
|
---|
1187 | if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT))
|
---|
1188 | {
|
---|
1189 | __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT);
|
---|
1190 |
|
---|
1191 | return SDMMC_ERROR_CMD_RSP_TIMEOUT;
|
---|
1192 | }
|
---|
1193 | else if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL))
|
---|
1194 | {
|
---|
1195 | __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL);
|
---|
1196 |
|
---|
1197 | return SDMMC_ERROR_CMD_CRC_FAIL;
|
---|
1198 | }
|
---|
1199 | else
|
---|
1200 | {
|
---|
1201 | /* Nothing to do */
|
---|
1202 | }
|
---|
1203 |
|
---|
1204 | /* Clear all the static flags */
|
---|
1205 | __SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS);
|
---|
1206 |
|
---|
1207 | /* Check response received is of desired command */
|
---|
1208 | if(SDIO_GetCommandResponse(SDIOx) != SD_CMD)
|
---|
1209 | {
|
---|
1210 | return SDMMC_ERROR_CMD_CRC_FAIL;
|
---|
1211 | }
|
---|
1212 |
|
---|
1213 | /* We have received response, retrieve it for analysis */
|
---|
1214 | response_r1 = SDIO_GetResponse(SDIOx, SDIO_RESP1);
|
---|
1215 |
|
---|
1216 | if((response_r1 & SDMMC_OCR_ERRORBITS) == SDMMC_ALLZERO)
|
---|
1217 | {
|
---|
1218 | return SDMMC_ERROR_NONE;
|
---|
1219 | }
|
---|
1220 | else if((response_r1 & SDMMC_OCR_ADDR_OUT_OF_RANGE) == SDMMC_OCR_ADDR_OUT_OF_RANGE)
|
---|
1221 | {
|
---|
1222 | return SDMMC_ERROR_ADDR_OUT_OF_RANGE;
|
---|
1223 | }
|
---|
1224 | else if((response_r1 & SDMMC_OCR_ADDR_MISALIGNED) == SDMMC_OCR_ADDR_MISALIGNED)
|
---|
1225 | {
|
---|
1226 | return SDMMC_ERROR_ADDR_MISALIGNED;
|
---|
1227 | }
|
---|
1228 | else if((response_r1 & SDMMC_OCR_BLOCK_LEN_ERR) == SDMMC_OCR_BLOCK_LEN_ERR)
|
---|
1229 | {
|
---|
1230 | return SDMMC_ERROR_BLOCK_LEN_ERR;
|
---|
1231 | }
|
---|
1232 | else if((response_r1 & SDMMC_OCR_ERASE_SEQ_ERR) == SDMMC_OCR_ERASE_SEQ_ERR)
|
---|
1233 | {
|
---|
1234 | return SDMMC_ERROR_ERASE_SEQ_ERR;
|
---|
1235 | }
|
---|
1236 | else if((response_r1 & SDMMC_OCR_BAD_ERASE_PARAM) == SDMMC_OCR_BAD_ERASE_PARAM)
|
---|
1237 | {
|
---|
1238 | return SDMMC_ERROR_BAD_ERASE_PARAM;
|
---|
1239 | }
|
---|
1240 | else if((response_r1 & SDMMC_OCR_WRITE_PROT_VIOLATION) == SDMMC_OCR_WRITE_PROT_VIOLATION)
|
---|
1241 | {
|
---|
1242 | return SDMMC_ERROR_WRITE_PROT_VIOLATION;
|
---|
1243 | }
|
---|
1244 | else if((response_r1 & SDMMC_OCR_LOCK_UNLOCK_FAILED) == SDMMC_OCR_LOCK_UNLOCK_FAILED)
|
---|
1245 | {
|
---|
1246 | return SDMMC_ERROR_LOCK_UNLOCK_FAILED;
|
---|
1247 | }
|
---|
1248 | else if((response_r1 & SDMMC_OCR_COM_CRC_FAILED) == SDMMC_OCR_COM_CRC_FAILED)
|
---|
1249 | {
|
---|
1250 | return SDMMC_ERROR_COM_CRC_FAILED;
|
---|
1251 | }
|
---|
1252 | else if((response_r1 & SDMMC_OCR_ILLEGAL_CMD) == SDMMC_OCR_ILLEGAL_CMD)
|
---|
1253 | {
|
---|
1254 | return SDMMC_ERROR_ILLEGAL_CMD;
|
---|
1255 | }
|
---|
1256 | else if((response_r1 & SDMMC_OCR_CARD_ECC_FAILED) == SDMMC_OCR_CARD_ECC_FAILED)
|
---|
1257 | {
|
---|
1258 | return SDMMC_ERROR_CARD_ECC_FAILED;
|
---|
1259 | }
|
---|
1260 | else if((response_r1 & SDMMC_OCR_CC_ERROR) == SDMMC_OCR_CC_ERROR)
|
---|
1261 | {
|
---|
1262 | return SDMMC_ERROR_CC_ERR;
|
---|
1263 | }
|
---|
1264 | else if((response_r1 & SDMMC_OCR_STREAM_READ_UNDERRUN) == SDMMC_OCR_STREAM_READ_UNDERRUN)
|
---|
1265 | {
|
---|
1266 | return SDMMC_ERROR_STREAM_READ_UNDERRUN;
|
---|
1267 | }
|
---|
1268 | else if((response_r1 & SDMMC_OCR_STREAM_WRITE_OVERRUN) == SDMMC_OCR_STREAM_WRITE_OVERRUN)
|
---|
1269 | {
|
---|
1270 | return SDMMC_ERROR_STREAM_WRITE_OVERRUN;
|
---|
1271 | }
|
---|
1272 | else if((response_r1 & SDMMC_OCR_CID_CSD_OVERWRITE) == SDMMC_OCR_CID_CSD_OVERWRITE)
|
---|
1273 | {
|
---|
1274 | return SDMMC_ERROR_CID_CSD_OVERWRITE;
|
---|
1275 | }
|
---|
1276 | else if((response_r1 & SDMMC_OCR_WP_ERASE_SKIP) == SDMMC_OCR_WP_ERASE_SKIP)
|
---|
1277 | {
|
---|
1278 | return SDMMC_ERROR_WP_ERASE_SKIP;
|
---|
1279 | }
|
---|
1280 | else if((response_r1 & SDMMC_OCR_CARD_ECC_DISABLED) == SDMMC_OCR_CARD_ECC_DISABLED)
|
---|
1281 | {
|
---|
1282 | return SDMMC_ERROR_CARD_ECC_DISABLED;
|
---|
1283 | }
|
---|
1284 | else if((response_r1 & SDMMC_OCR_ERASE_RESET) == SDMMC_OCR_ERASE_RESET)
|
---|
1285 | {
|
---|
1286 | return SDMMC_ERROR_ERASE_RESET;
|
---|
1287 | }
|
---|
1288 | else if((response_r1 & SDMMC_OCR_AKE_SEQ_ERROR) == SDMMC_OCR_AKE_SEQ_ERROR)
|
---|
1289 | {
|
---|
1290 | return SDMMC_ERROR_AKE_SEQ_ERR;
|
---|
1291 | }
|
---|
1292 | else
|
---|
1293 | {
|
---|
1294 | return SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
|
---|
1295 | }
|
---|
1296 | }
|
---|
1297 |
|
---|
1298 | /**
|
---|
1299 | * @brief Checks for error conditions for R2 (CID or CSD) response.
|
---|
1300 | * @param hsd: SD handle
|
---|
1301 | * @retval SD Card error state
|
---|
1302 | */
|
---|
1303 | static uint32_t SDMMC_GetCmdResp2(SDIO_TypeDef *SDIOx)
|
---|
1304 | {
|
---|
1305 | uint32_t sta_reg;
|
---|
1306 | /* 8 is the number of required instructions cycles for the below loop statement.
|
---|
1307 | The SDIO_CMDTIMEOUT is expressed in ms */
|
---|
1308 | uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
|
---|
1309 |
|
---|
1310 | do
|
---|
1311 | {
|
---|
1312 | if (count-- == 0U)
|
---|
1313 | {
|
---|
1314 | return SDMMC_ERROR_TIMEOUT;
|
---|
1315 | }
|
---|
1316 | sta_reg = SDIOx->STA;
|
---|
1317 | }while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) ||
|
---|
1318 | ((sta_reg & SDIO_FLAG_CMDACT) != 0U ));
|
---|
1319 |
|
---|
1320 | if (__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT))
|
---|
1321 | {
|
---|
1322 | __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT);
|
---|
1323 |
|
---|
1324 | return SDMMC_ERROR_CMD_RSP_TIMEOUT;
|
---|
1325 | }
|
---|
1326 | else if (__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL))
|
---|
1327 | {
|
---|
1328 | __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL);
|
---|
1329 |
|
---|
1330 | return SDMMC_ERROR_CMD_CRC_FAIL;
|
---|
1331 | }
|
---|
1332 | else
|
---|
1333 | {
|
---|
1334 | /* No error flag set */
|
---|
1335 | /* Clear all the static flags */
|
---|
1336 | __SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS);
|
---|
1337 | }
|
---|
1338 |
|
---|
1339 | return SDMMC_ERROR_NONE;
|
---|
1340 | }
|
---|
1341 |
|
---|
1342 | /**
|
---|
1343 | * @brief Checks for error conditions for R3 (OCR) response.
|
---|
1344 | * @param hsd: SD handle
|
---|
1345 | * @retval SD Card error state
|
---|
1346 | */
|
---|
1347 | static uint32_t SDMMC_GetCmdResp3(SDIO_TypeDef *SDIOx)
|
---|
1348 | {
|
---|
1349 | uint32_t sta_reg;
|
---|
1350 | /* 8 is the number of required instructions cycles for the below loop statement.
|
---|
1351 | The SDIO_CMDTIMEOUT is expressed in ms */
|
---|
1352 | uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
|
---|
1353 |
|
---|
1354 | do
|
---|
1355 | {
|
---|
1356 | if (count-- == 0U)
|
---|
1357 | {
|
---|
1358 | return SDMMC_ERROR_TIMEOUT;
|
---|
1359 | }
|
---|
1360 | sta_reg = SDIOx->STA;
|
---|
1361 | }while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) ||
|
---|
1362 | ((sta_reg & SDIO_FLAG_CMDACT) != 0U ));
|
---|
1363 |
|
---|
1364 | if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT))
|
---|
1365 | {
|
---|
1366 | __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT);
|
---|
1367 |
|
---|
1368 | return SDMMC_ERROR_CMD_RSP_TIMEOUT;
|
---|
1369 | }
|
---|
1370 | else
|
---|
1371 | {
|
---|
1372 | /* Clear all the static flags */
|
---|
1373 | __SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS);
|
---|
1374 | }
|
---|
1375 |
|
---|
1376 | return SDMMC_ERROR_NONE;
|
---|
1377 | }
|
---|
1378 |
|
---|
1379 | /**
|
---|
1380 | * @brief Checks for error conditions for R6 (RCA) response.
|
---|
1381 | * @param hsd: SD handle
|
---|
1382 | * @param SD_CMD: The sent command index
|
---|
1383 | * @param pRCA: Pointer to the variable that will contain the SD card relative
|
---|
1384 | * address RCA
|
---|
1385 | * @retval SD Card error state
|
---|
1386 | */
|
---|
1387 | static uint32_t SDMMC_GetCmdResp6(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint16_t *pRCA)
|
---|
1388 | {
|
---|
1389 | uint32_t response_r1;
|
---|
1390 | uint32_t sta_reg;
|
---|
1391 |
|
---|
1392 | /* 8 is the number of required instructions cycles for the below loop statement.
|
---|
1393 | The SDIO_CMDTIMEOUT is expressed in ms */
|
---|
1394 | uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
|
---|
1395 |
|
---|
1396 | do
|
---|
1397 | {
|
---|
1398 | if (count-- == 0U)
|
---|
1399 | {
|
---|
1400 | return SDMMC_ERROR_TIMEOUT;
|
---|
1401 | }
|
---|
1402 | sta_reg = SDIOx->STA;
|
---|
1403 | }while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) ||
|
---|
1404 | ((sta_reg & SDIO_FLAG_CMDACT) != 0U ));
|
---|
1405 |
|
---|
1406 | if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT))
|
---|
1407 | {
|
---|
1408 | __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT);
|
---|
1409 |
|
---|
1410 | return SDMMC_ERROR_CMD_RSP_TIMEOUT;
|
---|
1411 | }
|
---|
1412 | else if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL))
|
---|
1413 | {
|
---|
1414 | __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL);
|
---|
1415 |
|
---|
1416 | return SDMMC_ERROR_CMD_CRC_FAIL;
|
---|
1417 | }
|
---|
1418 | else
|
---|
1419 | {
|
---|
1420 | /* Nothing to do */
|
---|
1421 | }
|
---|
1422 |
|
---|
1423 | /* Check response received is of desired command */
|
---|
1424 | if(SDIO_GetCommandResponse(SDIOx) != SD_CMD)
|
---|
1425 | {
|
---|
1426 | return SDMMC_ERROR_CMD_CRC_FAIL;
|
---|
1427 | }
|
---|
1428 |
|
---|
1429 | /* Clear all the static flags */
|
---|
1430 | __SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS);
|
---|
1431 |
|
---|
1432 | /* We have received response, retrieve it. */
|
---|
1433 | response_r1 = SDIO_GetResponse(SDIOx, SDIO_RESP1);
|
---|
1434 |
|
---|
1435 | if((response_r1 & (SDMMC_R6_GENERAL_UNKNOWN_ERROR | SDMMC_R6_ILLEGAL_CMD | SDMMC_R6_COM_CRC_FAILED)) == SDMMC_ALLZERO)
|
---|
1436 | {
|
---|
1437 | *pRCA = (uint16_t) (response_r1 >> 16);
|
---|
1438 |
|
---|
1439 | return SDMMC_ERROR_NONE;
|
---|
1440 | }
|
---|
1441 | else if((response_r1 & SDMMC_R6_ILLEGAL_CMD) == SDMMC_R6_ILLEGAL_CMD)
|
---|
1442 | {
|
---|
1443 | return SDMMC_ERROR_ILLEGAL_CMD;
|
---|
1444 | }
|
---|
1445 | else if((response_r1 & SDMMC_R6_COM_CRC_FAILED) == SDMMC_R6_COM_CRC_FAILED)
|
---|
1446 | {
|
---|
1447 | return SDMMC_ERROR_COM_CRC_FAILED;
|
---|
1448 | }
|
---|
1449 | else
|
---|
1450 | {
|
---|
1451 | return SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
|
---|
1452 | }
|
---|
1453 | }
|
---|
1454 |
|
---|
1455 | /**
|
---|
1456 | * @brief Checks for error conditions for R7 response.
|
---|
1457 | * @param hsd: SD handle
|
---|
1458 | * @retval SD Card error state
|
---|
1459 | */
|
---|
1460 | static uint32_t SDMMC_GetCmdResp7(SDIO_TypeDef *SDIOx)
|
---|
1461 | {
|
---|
1462 | uint32_t sta_reg;
|
---|
1463 | /* 8 is the number of required instructions cycles for the below loop statement.
|
---|
1464 | The SDIO_CMDTIMEOUT is expressed in ms */
|
---|
1465 | uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
|
---|
1466 |
|
---|
1467 | do
|
---|
1468 | {
|
---|
1469 | if (count-- == 0U)
|
---|
1470 | {
|
---|
1471 | return SDMMC_ERROR_TIMEOUT;
|
---|
1472 | }
|
---|
1473 | sta_reg = SDIOx->STA;
|
---|
1474 | }while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) ||
|
---|
1475 | ((sta_reg & SDIO_FLAG_CMDACT) != 0U ));
|
---|
1476 |
|
---|
1477 | if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT))
|
---|
1478 | {
|
---|
1479 | /* Card is SD V2.0 compliant */
|
---|
1480 | __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT);
|
---|
1481 |
|
---|
1482 | return SDMMC_ERROR_CMD_RSP_TIMEOUT;
|
---|
1483 | }
|
---|
1484 | else if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL))
|
---|
1485 | {
|
---|
1486 | /* Card is SD V2.0 compliant */
|
---|
1487 | __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL);
|
---|
1488 |
|
---|
1489 | return SDMMC_ERROR_CMD_CRC_FAIL;
|
---|
1490 | }
|
---|
1491 | else
|
---|
1492 | {
|
---|
1493 | /* Nothing to do */
|
---|
1494 | }
|
---|
1495 |
|
---|
1496 | if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CMDREND))
|
---|
1497 | {
|
---|
1498 | /* Card is SD V2.0 compliant */
|
---|
1499 | __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CMDREND);
|
---|
1500 | }
|
---|
1501 |
|
---|
1502 | return SDMMC_ERROR_NONE;
|
---|
1503 |
|
---|
1504 | }
|
---|
1505 |
|
---|
1506 | /**
|
---|
1507 | * @brief Send the Send EXT_CSD command and check the response.
|
---|
1508 | * @param SDIOx: Pointer to SDMMC register base
|
---|
1509 | * @param Argument: Command Argument
|
---|
1510 | * @retval HAL status
|
---|
1511 | */
|
---|
1512 | uint32_t SDMMC_CmdSendEXTCSD(SDIO_TypeDef *SDIOx, uint32_t Argument)
|
---|
1513 | {
|
---|
1514 | SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
---|
1515 | uint32_t errorstate;
|
---|
1516 |
|
---|
1517 | /* Send CMD9 SEND_CSD */
|
---|
1518 | sdmmc_cmdinit.Argument = Argument;
|
---|
1519 | sdmmc_cmdinit.CmdIndex = SDMMC_CMD_HS_SEND_EXT_CSD;
|
---|
1520 | sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
---|
1521 | sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
---|
1522 | sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
---|
1523 | (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
---|
1524 |
|
---|
1525 | /* Check for error conditions */
|
---|
1526 | errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_HS_SEND_EXT_CSD,SDIO_CMDTIMEOUT);
|
---|
1527 |
|
---|
1528 | return errorstate;
|
---|
1529 | }
|
---|
1530 |
|
---|
1531 |
|
---|
1532 | /**
|
---|
1533 | * @}
|
---|
1534 | */
|
---|
1535 |
|
---|
1536 | #endif /* HAL_SD_MODULE_ENABLED || HAL_MMC_MODULE_ENABLED */
|
---|
1537 | /**
|
---|
1538 | * @}
|
---|
1539 | */
|
---|
1540 |
|
---|
1541 | /**
|
---|
1542 | * @}
|
---|
1543 | */
|
---|
1544 |
|
---|
1545 | #endif /* SDIO */
|
---|
1546 |
|
---|
1547 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
---|