1 /*****************************************************************************
2  * Copyright (c) 2019, Nations Technologies Inc.
3  *
4  * All rights reserved.
5  * ****************************************************************************
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the disclaimer below.
12  *
13  * Nations' name may not be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
19  * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
22  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  * ****************************************************************************/
27 
28 /**
29  * @file n32g4fr_sdio.c
30  * @author Nations
31  * @version v1.0.1
32  *
33  * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved.
34  */
35 #include "n32g4fr_sdio.h"
36 #include "n32g4fr_rcc.h"
37 
38 /** @addtogroup N32G4FR_StdPeriph_Driver
39  * @{
40  */
41 
42 /** @addtogroup SDIO
43  * @brief SDIO driver modules
44  * @{
45  */
46 
47 /** @addtogroup SDIO_Private_TypesDefinitions
48  * @{
49  */
50 
51 /* ------------ SDIO registers bit address in the alias region ----------- */
52 #define SDIO_OFFSET (SDIO_BASE - PERIPH_BASE)
53 
54 /* --- CLKCTRL Register ---*/
55 
56 /* Alias word address of CLKEN bit */
57 #define CLKCTRL_OFFSET   (SDIO_OFFSET + 0x04)
58 #define CLKEN_BIT_NUMBER 0x08
59 #define CLKCTRL_CLKEN_BB (PERIPH_BB_BASE + (CLKCTRL_OFFSET * 32) + (CLKEN_BIT_NUMBER * 4))
60 
61 /* --- CMDCTRL Register ---*/
62 
63 /* Alias word address of SDIOSUSPEND bit */
64 #define CMD_OFFSET              (SDIO_OFFSET + 0x0C)
65 #define SDIO_SUSPEND_BIT_NUMBER 0x0B
66 #define CMD_SDIO_SUSPEND_BB     (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (SDIO_SUSPEND_BIT_NUMBER * 4))
67 
68 /* Alias word address of ENCMDCOMPL bit */
69 #define EN_CMD_COMPL_BIT_NUMBER 0x0C
70 #define EN_CMD_COMPL_BB         (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (EN_CMD_COMPL_BIT_NUMBER * 4))
71 
72 /* Alias word address of NIEN bit */
73 #define NIEN_BIT_NUMBER 0x0D
74 #define CMD_NIEN_BB     (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (NIEN_BIT_NUMBER * 4))
75 
76 /* Alias word address of ATACMD bit */
77 #define ATACMD_BIT_NUMBER 0x0E
78 #define CMD_ATACMD_BB     (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (ATACMD_BIT_NUMBER * 4))
79 
80 /* --- DATCTRL Register ---*/
81 
82 /* Alias word address of DMAEN bit */
83 #define DCTRL_OFFSET     (SDIO_OFFSET + 0x2C)
84 #define DMAEN_BIT_NUMBER 0x03
85 #define DCTRL_DMAEN_BB   (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (DMAEN_BIT_NUMBER * 4))
86 
87 /* Alias word address of RWSTART bit */
88 #define RWSTART_BIT_NUMBER 0x08
89 #define DCTRL_RWSTART_BB   (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWSTART_BIT_NUMBER * 4))
90 
91 /* Alias word address of RWSTOP bit */
92 #define RWSTOP_BIT_NUMBER 0x09
93 #define DCTRL_RWSTOP_BB   (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWSTOP_BIT_NUMBER * 4))
94 
95 /* Alias word address of RWMOD bit */
96 #define RWMOD_BIT_NUMBER 0x0A
97 #define DCTRL_RWMOD_BB   (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWMOD_BIT_NUMBER * 4))
98 
99 /* Alias word address of SDIOEN bit */
100 #define SDIOEN_BIT_NUMBER 0x0B
101 #define DCTRL_SDIOEN_BB   (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (SDIOEN_BIT_NUMBER * 4))
102 
103 /* ---------------------- SDIO registers bit mask ------------------------ */
104 
105 /* --- CLKCTRL Register ---*/
106 
107 /* CLKCTRL register clear mask */
108 #define CLKCTRL_CLR_MASK ((uint32_t)0xFFFF8100)
109 
110 /* --- PWRCTRL Register ---*/
111 
112 /* SDIO PWRCTRL Mask */
113 #define POWER_PWRCTRL_MASK ((uint32_t)0xFFFFFFFC)
114 
115 /* --- DATCTRL Register ---*/
116 
117 /* SDIO DATCTRL Clear Mask */
118 #define DATCTRL_CLR_MASK ((uint32_t)0xFFFFFF08)
119 
120 /* --- CMDCTRL Register ---*/
121 
122 /* CMDCTRL Register clear mask */
123 #define CMD_CLR_MASK ((uint32_t)0xFFFFF800)
124 
125 /* SDIO RESP Registers Address */
126 #define SDID_RESPONSE_ADDR ((uint32_t)(SDIO_BASE + 0x14))
127 
128 /**
129  * @}
130  */
131 
132 /** @addtogroup SDIO_Private_Defines
133  * @{
134  */
135 
136 /**
137  * @}
138  */
139 
140 /** @addtogroup SDIO_Private_Macros
141  * @{
142  */
143 
144 /**
145  * @}
146  */
147 
148 /** @addtogroup SDIO_Private_Variables
149  * @{
150  */
151 
152 /**
153  * @}
154  */
155 
156 /** @addtogroup SDIO_Private_FunctionPrototypes
157  * @{
158  */
159 
160 /**
161  * @}
162  */
163 
164 /** @addtogroup SDIO_Private_Functions
165  * @{
166  */
167 
168 /**
169  * @brief  Deinitializes the SDIO peripheral registers to their default reset values.
170  */
SDIO_DeInit(void)171 void SDIO_DeInit(void)
172 {
173     SDIO->PWRCTRL    = 0x00000000;
174     SDIO->CLKCTRL    = 0x00000000;
175     SDIO->CMDARG     = 0x00000000;
176     SDIO->CMDCTRL    = 0x00000000;
177     SDIO->DTIMER     = 0x00000000;
178     SDIO->DATLEN     = 0x00000000;
179     SDIO->DATCTRL    = 0x00000000;
180     SDIO->INTCLR     = 0x00C007FF;
181     SDIO->INTEN      = 0x00000000;
182 }
183 
184 /**
185  * @brief  Initializes the SDIO peripheral according to the specified
186  *         parameters in the SDIO_InitStruct.
187  * @param SDIO_InitStruct pointer to a SDIO_InitType structure
188  *         that contains the configuration information for the SDIO peripheral.
189  */
SDIO_Init(SDIO_InitType * SDIO_InitStruct)190 void SDIO_Init(SDIO_InitType* SDIO_InitStruct)
191 {
192     uint32_t tmpregister = 0;
193 
194     /* Check the parameters */
195     assert_param(IS_SDIO_CLK_EDGE(SDIO_InitStruct->ClkEdge));
196     assert_param(IS_SDIO_CLK_BYPASS(SDIO_InitStruct->ClkBypass));
197     assert_param(IS_SDIO_CLK_POWER_SAVE(SDIO_InitStruct->ClkPwrSave));
198     assert_param(IS_SDIO_BUS_WIDTH(SDIO_InitStruct->BusWidth));
199     assert_param(IS_SDIO_HARDWARE_CLKCTRL(SDIO_InitStruct->HardwareClkCtrl));
200 
201     /*---------------------------- SDIO CLKCTRL Configuration ------------------------*/
202     /* Get the SDIO CLKCTRL value */
203     tmpregister = SDIO->CLKCTRL;
204 
205     /* Clear CLKDIV, PWRSAV, BYPASS, WIDBUS, NEGEDGE, HWFC_EN bits */
206     tmpregister &= CLKCTRL_CLR_MASK;
207 
208     /* Set CLKDIV bits according to ClkDiv value */
209     /* Set PWRSAV bit according to ClkPwrSave value */
210     /* Set BYPASS bit according to ClkBypass value */
211     /* Set WIDBUS bits according to BusWidth value */
212     /* Set NEGEDGE bits according to ClkEdge value */
213     /* Set HWFC_EN bits according to HardwareClkCtrl value */
214     tmpregister |= (SDIO_InitStruct->ClkDiv | SDIO_InitStruct->ClkPwrSave | SDIO_InitStruct->ClkBypass
215                     | SDIO_InitStruct->BusWidth | SDIO_InitStruct->ClkEdge | SDIO_InitStruct->HardwareClkCtrl);
216 
217     /* Write to SDIO CLKCTRL */
218     SDIO->CLKCTRL = tmpregister;
219 }
220 
221 /**
222  * @brief  Fills each SDIO_InitStruct member with its default value.
223  * @param SDIO_InitStruct pointer to an SDIO_InitType structure which
224  *   will be initialized.
225  */
SDIO_InitStruct(SDIO_InitType * SDIO_InitStruct)226 void SDIO_InitStruct(SDIO_InitType* SDIO_InitStruct)
227 {
228     /* SDIO_InitStruct members default value */
229     SDIO_InitStruct->ClkDiv          = 0x00;
230     SDIO_InitStruct->ClkEdge         = SDIO_CLKEDGE_RISING;
231     SDIO_InitStruct->ClkBypass       = SDIO_ClkBYPASS_DISABLE;
232     SDIO_InitStruct->ClkPwrSave      = SDIO_CLKPOWERSAVE_DISABLE;
233     SDIO_InitStruct->BusWidth        = SDIO_BUSWIDTH_1B;
234     SDIO_InitStruct->HardwareClkCtrl = SDIO_HARDWARE_CLKCTRL_DISABLE;
235 }
236 
237 /**
238  * @brief  Enables or disables the SDIO Clock.
239  * @param Cmd new state of the SDIO Clock. This parameter can be: ENABLE or DISABLE.
240  */
SDIO_EnableClock(FunctionalState Cmd)241 void SDIO_EnableClock(FunctionalState Cmd)
242 {
243     /* Check the parameters */
244     assert_param(IS_FUNCTIONAL_STATE(Cmd));
245 
246     *(__IO uint32_t*)CLKCTRL_CLKEN_BB = (uint32_t)Cmd;
247 }
248 
249 /**
250  * @brief  Sets the power status of the controller.
251  * @param SDIO_PowerState new state of the Power state.
252  *   This parameter can be one of the following values:
253  *     @arg SDIO_POWER_CTRL_OFF
254  *     @arg SDIO_POWER_CTRL_ON
255  */
SDIO_SetPower(uint32_t SDIO_PowerState)256 void SDIO_SetPower(uint32_t SDIO_PowerState)
257 {
258     /* Check the parameters */
259     assert_param(IS_SDIO_POWER_CTRL(SDIO_PowerState));
260 
261     SDIO->PWRCTRL &= POWER_PWRCTRL_MASK;
262     SDIO->PWRCTRL |= SDIO_PowerState;
263 }
264 
265 /**
266  * @brief  Gets the power status of the controller.
267  * @return Power status of the controller. The returned value can
268  *   be one of the following:
269  * - 0x00: Power OFF
270  * - 0x02: Power UP
271  * - 0x03: Power ON
272  */
SDIO_GetPower(void)273 uint32_t SDIO_GetPower(void)
274 {
275     return (SDIO->PWRCTRL & (~POWER_PWRCTRL_MASK));
276 }
277 
278 /**
279  * @brief  Enables or disables the SDIO interrupts.
280  * @param SDIO_IT specifies the SDIO interrupt sources to be enabled or disabled.
281  *   This parameter can be one or a combination of the following values:
282  *     @arg SDIO_INT_CCRCERR Command response received (CRC check failed) interrupt
283  *     @arg SDIO_INT_DCRCERR Data block sent/received (CRC check failed) interrupt
284  *     @arg SDIO_INT_CMDTIMEOUT Command response timeout interrupt
285  *     @arg SDIO_INT_DATTIMEOUT Data timeout interrupt
286  *     @arg SDIO_INT_TXURERR Transmit DATFIFO underrun error interrupt
287  *     @arg SDIO_INT_RXORERR Received DATFIFO overrun error interrupt
288  *     @arg SDIO_INT_CMDRESPRECV Command response received (CRC check passed) interrupt
289  *     @arg SDIO_INT_CMDSEND Command sent (no response required) interrupt
290  *     @arg SDIO_INT_DATEND Data end (data counter, SDIDCOUNT, is zero) interrupt
291  *     @arg SDIO_INT_SBERR Start bit not detected on all data signals in wide
292  *                            bus mode interrupt
293  *     @arg SDIO_INT_DATBLKEND Data block sent/received (CRC check passed) interrupt
294  *     @arg SDIO_INT_CMDRUN Command transfer in progress interrupt
295  *     @arg SDIO_INT_TXRUN Data transmit in progress interrupt
296  *     @arg SDIO_INT_RXRUN Data receive in progress interrupt
297  *     @arg SDIO_INT_TFIFOHE Transmit DATFIFO Half Empty interrupt
298  *     @arg SDIO_INT_RFIFOHF Receive DATFIFO Half Full interrupt
299  *     @arg SDIO_INT_TFIFOF Transmit DATFIFO full interrupt
300  *     @arg SDIO_INT_RFIFOF Receive DATFIFO full interrupt
301  *     @arg SDIO_INT_TFIFOE Transmit DATFIFO empty interrupt
302  *     @arg SDIO_INT_RFIFOE Receive DATFIFO empty interrupt
303  *     @arg SDIO_INT_TDATVALID Data available in transmit DATFIFO interrupt
304  *     @arg SDIO_INT_RDATVALID Data available in receive DATFIFO interrupt
305  *     @arg SDIO_INT_SDIOINT SD I/O interrupt received interrupt
306  *     @arg SDIO_INT_CEATAF CE-ATA command completion signal received for CMD61 interrupt
307  * @param Cmd new state of the specified SDIO interrupts.
308  *   This parameter can be: ENABLE or DISABLE.
309  */
SDIO_ConfigInt(uint32_t SDIO_IT,FunctionalState Cmd)310 void SDIO_ConfigInt(uint32_t SDIO_IT, FunctionalState Cmd)
311 {
312     /* Check the parameters */
313     assert_param(IS_SDIO_INT(SDIO_IT));
314     assert_param(IS_FUNCTIONAL_STATE(Cmd));
315 
316     if (Cmd != DISABLE)
317     {
318         /* Enable the SDIO interrupts */
319         SDIO->INTEN |= SDIO_IT;
320     }
321     else
322     {
323         /* Disable the SDIO interrupts */
324         SDIO->INTEN &= ~SDIO_IT;
325     }
326 }
327 
328 /**
329  * @brief  Enables or disables the SDIO DMA request.
330  * @param Cmd new state of the selected SDIO DMA request.
331  *   This parameter can be: ENABLE or DISABLE.
332  */
SDIO_DMACmd(FunctionalState Cmd)333 void SDIO_DMACmd(FunctionalState Cmd)
334 {
335     /* Check the parameters */
336     assert_param(IS_FUNCTIONAL_STATE(Cmd));
337 
338     *(__IO uint32_t*)DCTRL_DMAEN_BB = (uint32_t)Cmd;
339 }
340 
341 /**
342  * @brief  Initializes the SDIO Command according to the specified
343  *         parameters in the SDIO_CmdInitStruct and send the command.
344  * @param SDIO_CmdInitStruct pointer to a SDIO_CmdInitType
345  *         structure that contains the configuration information for the SDIO command.
346  */
SDIO_SendCmd(SDIO_CmdInitType * SDIO_CmdInitStruct)347 void SDIO_SendCmd(SDIO_CmdInitType* SDIO_CmdInitStruct)
348 {
349     uint32_t tmpregister = 0;
350 
351     /* Check the parameters */
352     assert_param(IS_SDIO_CMD_INDEX(SDIO_CmdInitStruct->CmdIndex));
353     assert_param(IS_SDIO_RESP(SDIO_CmdInitStruct->ResponseType));
354     assert_param(IS_SDIO_WAIT(SDIO_CmdInitStruct->WaitType));
355     assert_param(IS_SDIO_CPSM(SDIO_CmdInitStruct->CPSMConfig));
356 
357     /*---------------------------- SDIO CMDARG Configuration ------------------------*/
358     /* Set the SDIO Argument value */
359     SDIO->CMDARG = SDIO_CmdInitStruct->CmdArgument;
360 
361     /*---------------------------- SDIO CMDCTRL Configuration ------------------------*/
362     /* Get the SDIO CMDCTRL value */
363     tmpregister = SDIO->CMDCTRL;
364     /* Clear CMDINDEX, WAITRESP, WAITINT, WAITPEND, CPSMEN bits */
365     tmpregister &= CMD_CLR_MASK;
366     /* Set CMDINDEX bits according to CmdIndex value */
367     /* Set WAITRESP bits according to ResponseType value */
368     /* Set WAITINT and WAITPEND bits according to WaitType value */
369     /* Set CPSMEN bits according to CPSMConfig value */
370     tmpregister |= (uint32_t)SDIO_CmdInitStruct->CmdIndex | SDIO_CmdInitStruct->ResponseType
371                    | SDIO_CmdInitStruct->WaitType | SDIO_CmdInitStruct->CPSMConfig;
372 
373     /* Write to SDIO CMDCTRL */
374     SDIO->CMDCTRL = tmpregister;
375 }
376 
377 /**
378  * @brief  Fills each SDIO_CmdInitStruct member with its default value.
379  * @param SDIO_CmdInitStruct pointer to an SDIO_CmdInitType
380  *         structure which will be initialized.
381  */
SDIO_InitCmdStruct(SDIO_CmdInitType * SDIO_CmdInitStruct)382 void SDIO_InitCmdStruct(SDIO_CmdInitType* SDIO_CmdInitStruct)
383 {
384     /* SDIO_CmdInitStruct members default value */
385     SDIO_CmdInitStruct->CmdArgument  = 0x00;
386     SDIO_CmdInitStruct->CmdIndex     = 0x00;
387     SDIO_CmdInitStruct->ResponseType = SDIO_RESP_NO;
388     SDIO_CmdInitStruct->WaitType     = SDIO_WAIT_NO;
389     SDIO_CmdInitStruct->CPSMConfig   = SDIO_CPSM_DISABLE;
390 }
391 
392 /**
393  * @brief  Returns command index of last command for which response received.
394  * @return Returns the command index of the last command response received.
395  */
SDIO_GetCmdResp(void)396 uint8_t SDIO_GetCmdResp(void)
397 {
398     return (uint8_t)(SDIO->CMDRESP);
399 }
400 
401 /**
402  * @brief  Returns response received from the card for the last command.
403  * @param SDIO_RESP Specifies the SDIO response register.
404  *   This parameter can be one of the following values:
405  *     @arg SDIO_RESPONSE_1 Response Register 1
406  *     @arg SDIO_RESPONSE_2 Response Register 2
407  *     @arg SDIO_RESPONSE_3 Response Register 3
408  *     @arg SDIO_RESPONSE_4 Response Register 4
409  * @return The Corresponding response register value.
410  */
SDIO_GetResp(uint32_t SDIO_RESP)411 uint32_t SDIO_GetResp(uint32_t SDIO_RESP)
412 {
413     __IO uint32_t tmp = 0;
414 
415     /* Check the parameters */
416     assert_param(IS_SDIO_RESPONSE(SDIO_RESP));
417 
418     tmp = SDID_RESPONSE_ADDR + SDIO_RESP;
419 
420     return (*(__IO uint32_t*)tmp);
421 }
422 
423 /**
424  * @brief  Initializes the SDIO data path according to the specified
425  *   parameters in the SDIO_DataInitStruct.
426  * @param SDIO_DataInitStruct pointer to a SDIO_DataInitType structure that
427  *   contains the configuration information for the SDIO command.
428  */
SDIO_ConfigData(SDIO_DataInitType * SDIO_DataInitStruct)429 void SDIO_ConfigData(SDIO_DataInitType* SDIO_DataInitStruct)
430 {
431     uint32_t tmpregister = 0;
432 
433     /* Check the parameters */
434     assert_param(IS_SDIO_DAT_LEN(SDIO_DataInitStruct->DatLen));
435     assert_param(IS_SDIO_BLK_SIZE(SDIO_DataInitStruct->DatBlkSize));
436     assert_param(IS_SDIO_TRANSFER_DIRECTION(SDIO_DataInitStruct->TransferDirection));
437     assert_param(IS_SDIO_TRANS_MODE(SDIO_DataInitStruct->TransferMode));
438     assert_param(IS_SDIO_DPSM(SDIO_DataInitStruct->DPSMConfig));
439 
440     /*---------------------------- SDIO DATTIMEOUT Configuration ---------------------*/
441     /* Set the SDIO Data TimeOut value */
442     SDIO->DTIMER = SDIO_DataInitStruct->DatTimeout;
443 
444     /*---------------------------- SDIO DATLEN Configuration -----------------------*/
445     /* Set the SDIO DataLength value */
446     SDIO->DATLEN = SDIO_DataInitStruct->DatLen;
447 
448     /*---------------------------- SDIO DATCTRL Configuration ----------------------*/
449     /* Get the SDIO DATCTRL value */
450     tmpregister = SDIO->DATCTRL;
451     /* Clear DEN, DTMODE, DTDIR and DBCKSIZE bits */
452     tmpregister &= DATCTRL_CLR_MASK;
453     /* Set DEN bit according to DPSMConfig value */
454     /* Set DTMODE bit according to TransferMode value */
455     /* Set DTDIR bit according to TransferDirection value */
456     /* Set DBCKSIZE bits according to DatBlkSize value */
457     tmpregister |= (uint32_t)SDIO_DataInitStruct->DatBlkSize | SDIO_DataInitStruct->TransferDirection
458                    | SDIO_DataInitStruct->TransferMode | SDIO_DataInitStruct->DPSMConfig;
459 
460     if(SDIO_DataInitStruct->TransferDirection)
461     {
462         tmpregister &= ~(1<<12);
463     }
464     else
465     {
466         tmpregister |= 1<<12;
467     }
468 
469     /* Write to SDIO DATCTRL */
470     SDIO->DATCTRL = tmpregister;
471 }
472 
473 /**
474  * @brief  Fills each SDIO_DataInitStruct member with its default value.
475  * @param SDIO_DataInitStruct pointer to an SDIO_DataInitType structure which
476  *         will be initialized.
477  */
SDIO_InitDataStruct(SDIO_DataInitType * SDIO_DataInitStruct)478 void SDIO_InitDataStruct(SDIO_DataInitType* SDIO_DataInitStruct)
479 {
480     /* SDIO_DataInitStruct members default value */
481     SDIO_DataInitStruct->DatTimeout        = 0xFFFFFFFF;
482     SDIO_DataInitStruct->DatLen            = 0x00;
483     SDIO_DataInitStruct->DatBlkSize        = SDIO_DATBLK_SIZE_1B;
484     SDIO_DataInitStruct->TransferDirection = SDIO_TRANSDIR_TOCARD;
485     SDIO_DataInitStruct->TransferMode      = SDIO_TRANSMODE_BLOCK;
486     SDIO_DataInitStruct->DPSMConfig        = SDIO_DPSM_DISABLE;
487 }
488 
489 /**
490  * @brief  Returns number of remaining data bytes to be transferred.
491  * @return Number of remaining data bytes to be transferred
492  */
SDIO_GetDataCountValue(void)493 uint32_t SDIO_GetDataCountValue(void)
494 {
495     return SDIO->DATCOUNT;
496 }
497 
498 /**
499  * @brief  Read one data word from Rx DATFIFO.
500  * @return Data received
501  */
SDIO_ReadData(void)502 uint32_t SDIO_ReadData(void)
503 {
504     return SDIO->DATFIFO;
505 }
506 
507 /**
508  * @brief  Write one data word to Tx DATFIFO.
509  * @param Data 32-bit data word to write.
510  */
SDIO_WriteData(uint32_t Data)511 void SDIO_WriteData(uint32_t Data)
512 {
513     SDIO->DATFIFO = Data;
514 }
515 
516 /**
517  * @brief  Returns the number of words left to be written to or read from DATFIFO.
518  * @return Remaining number of words.
519  */
SDIO_GetFifoCounter(void)520 uint32_t SDIO_GetFifoCounter(void)
521 {
522     return SDIO->FIFOCOUNT;
523 }
524 
525 /**
526  * @brief  Starts the SD I/O Read Wait operation.
527  * @param Cmd new state of the Start SDIO Read Wait operation.
528  *   This parameter can be: ENABLE or DISABLE.
529  */
SDIO_EnableReadWait(FunctionalState Cmd)530 void SDIO_EnableReadWait(FunctionalState Cmd)
531 {
532     /* Check the parameters */
533     assert_param(IS_FUNCTIONAL_STATE(Cmd));
534 
535     *(__IO uint32_t*)DCTRL_RWSTART_BB = (uint32_t)Cmd;
536 }
537 
538 /**
539  * @brief  Stops the SD I/O Read Wait operation.
540  * @param Cmd new state of the Stop SDIO Read Wait operation.
541  *   This parameter can be: ENABLE or DISABLE.
542  */
SDIO_DisableReadWait(FunctionalState Cmd)543 void SDIO_DisableReadWait(FunctionalState Cmd)
544 {
545     /* Check the parameters */
546     assert_param(IS_FUNCTIONAL_STATE(Cmd));
547 
548     *(__IO uint32_t*)DCTRL_RWSTOP_BB = (uint32_t)Cmd;
549 }
550 
551 /**
552  * @brief  Sets one of the two options of inserting read wait interval.
553  * @param SDIO_ReadWaitMode SD I/O Read Wait operation mode.
554  *   This parameter can be:
555  *     @arg SDIO_RDWAIT_MODE_CLK Read Wait control by stopping SDIOCLK
556  *     @arg SDIO_RDWAIT_MODE_DAT2 Read Wait control using SDIO_DATA2
557  */
SDIO_EnableSdioReadWaitMode(uint32_t SDIO_ReadWaitMode)558 void SDIO_EnableSdioReadWaitMode(uint32_t SDIO_ReadWaitMode)
559 {
560     /* Check the parameters */
561     assert_param(IS_SDIO_RDWAIT_MODE(SDIO_ReadWaitMode));
562 
563     *(__IO uint32_t*)DCTRL_RWMOD_BB = SDIO_ReadWaitMode;
564 }
565 
566 /**
567  * @brief  Enables or disables the SD I/O Mode Operation.
568  * @param Cmd new state of SDIO specific operation.
569  *   This parameter can be: ENABLE or DISABLE.
570  */
SDIO_EnableSdioOperation(FunctionalState Cmd)571 void SDIO_EnableSdioOperation(FunctionalState Cmd)
572 {
573     /* Check the parameters */
574     assert_param(IS_FUNCTIONAL_STATE(Cmd));
575 
576     *(__IO uint32_t*)DCTRL_SDIOEN_BB = (uint32_t)Cmd;
577 }
578 
579 /**
580  * @brief  Enables or disables the SD I/O Mode suspend command sending.
581  * @param Cmd new state of the SD I/O Mode suspend command.
582  *   This parameter can be: ENABLE or DISABLE.
583  */
SDIO_EnableSendSdioSuspend(FunctionalState Cmd)584 void SDIO_EnableSendSdioSuspend(FunctionalState Cmd)
585 {
586     /* Check the parameters */
587     assert_param(IS_FUNCTIONAL_STATE(Cmd));
588 
589     *(__IO uint32_t*)CMD_SDIO_SUSPEND_BB = (uint32_t)Cmd;
590 }
591 
592 /**
593  * @brief  Enables or disables the command completion signal.
594  * @param Cmd new state of command completion signal.
595  *   This parameter can be: ENABLE or DISABLE.
596  */
SDIO_EnableCommandCompletion(FunctionalState Cmd)597 void SDIO_EnableCommandCompletion(FunctionalState Cmd)
598 {
599     /* Check the parameters */
600     assert_param(IS_FUNCTIONAL_STATE(Cmd));
601 
602     *(__IO uint32_t*)EN_CMD_COMPL_BB = (uint32_t)Cmd;
603 }
604 
605 /**
606  * @brief  Enables or disables the CE-ATA interrupt.
607  * @param Cmd new state of CE-ATA interrupt. This parameter can be: ENABLE or DISABLE.
608  */
SDIO_EnableCEATAInt(FunctionalState Cmd)609 void SDIO_EnableCEATAInt(FunctionalState Cmd)
610 {
611     /* Check the parameters */
612     assert_param(IS_FUNCTIONAL_STATE(Cmd));
613 
614     *(__IO uint32_t*)CMD_NIEN_BB = (uint32_t)((~((uint32_t)Cmd)) & ((uint32_t)0x1));
615 }
616 
617 /**
618  * @brief  Sends CE-ATA command (CMD61).
619  * @param Cmd new state of CE-ATA command. This parameter can be: ENABLE or DISABLE.
620  */
SDIO_EnableSendCEATA(FunctionalState Cmd)621 void SDIO_EnableSendCEATA(FunctionalState Cmd)
622 {
623     /* Check the parameters */
624     assert_param(IS_FUNCTIONAL_STATE(Cmd));
625 
626     *(__IO uint32_t*)CMD_ATACMD_BB = (uint32_t)Cmd;
627 }
628 
629 /**
630  * @brief  Checks whether the specified SDIO flag is set or not.
631  * @param SDIO_FLAG specifies the flag to check.
632  *   This parameter can be one of the following values:
633  *     @arg SDIO_FLAG_CCRCERR Command response received (CRC check failed)
634  *     @arg SDIO_FLAG_DCRCERR Data block sent/received (CRC check failed)
635  *     @arg SDIO_FLAG_CMDTIMEOUT Command response timeout
636  *     @arg SDIO_FLAG_DATTIMEOUT Data timeout
637  *     @arg SDIO_FLAG_TXURERR Transmit DATFIFO underrun error
638  *     @arg SDIO_FLAG_RXORERR Received DATFIFO overrun error
639  *     @arg SDIO_FLAG_CMDRESPRECV Command response received (CRC check passed)
640  *     @arg SDIO_FLAG_CMDSEND Command sent (no response required)
641  *     @arg SDIO_FLAG_DATEND Data end (data counter, SDIDCOUNT, is zero)
642  *     @arg SDIO_FLAG_SBERR Start bit not detected on all data signals in wide
643  *                              bus mode.
644  *     @arg SDIO_FLAG_DATBLKEND Data block sent/received (CRC check passed)
645  *     @arg SDIO_FLAG_CMDRUN Command transfer in progress
646  *     @arg SDIO_FLAG_TXRUN Data transmit in progress
647  *     @arg SDIO_FLAG_RXRUN Data receive in progress
648  *     @arg SDIO_FLAG_TFIFOHE Transmit DATFIFO Half Empty
649  *     @arg SDIO_FLAG_RFIFOHF Receive DATFIFO Half Full
650  *     @arg SDIO_FLAG_TFIFOF Transmit DATFIFO full
651  *     @arg SDIO_FLAG_RFIFOF Receive DATFIFO full
652  *     @arg SDIO_FLAG_TFIFOE Transmit DATFIFO empty
653  *     @arg SDIO_FLAG_RFIFOE Receive DATFIFO empty
654  *     @arg SDIO_FLAG_TDATVALID Data available in transmit DATFIFO
655  *     @arg SDIO_FLAG_RDATVALID Data available in receive DATFIFO
656  *     @arg SDIO_FLAG_SDIOINT SD I/O interrupt received
657  *     @arg SDIO_FLAG_CEATAF CE-ATA command completion signal received for CMD61
658  * @return The new state of SDIO_FLAG (SET or RESET).
659  */
SDIO_GetFlag(uint32_t SDIO_FLAG)660 FlagStatus SDIO_GetFlag(uint32_t SDIO_FLAG)
661 {
662     FlagStatus bitstatus = RESET;
663 
664     /* Check the parameters */
665     assert_param(IS_SDIO_FLAG(SDIO_FLAG));
666 
667     if ((SDIO->STS & SDIO_FLAG) != (uint32_t)RESET)
668     {
669         bitstatus = SET;
670     }
671     else
672     {
673         bitstatus = RESET;
674     }
675     return bitstatus;
676 }
677 
678 /**
679  * @brief  Clears the SDIO's pending flags.
680  * @param SDIO_FLAG specifies the flag to clear.
681  *   This parameter can be one or a combination of the following values:
682  *     @arg SDIO_FLAG_CCRCERR Command response received (CRC check failed)
683  *     @arg SDIO_FLAG_DCRCERR Data block sent/received (CRC check failed)
684  *     @arg SDIO_FLAG_CMDTIMEOUT Command response timeout
685  *     @arg SDIO_FLAG_DATTIMEOUT Data timeout
686  *     @arg SDIO_FLAG_TXURERR Transmit DATFIFO underrun error
687  *     @arg SDIO_FLAG_RXORERR Received DATFIFO overrun error
688  *     @arg SDIO_FLAG_CMDRESPRECV Command response received (CRC check passed)
689  *     @arg SDIO_FLAG_CMDSEND Command sent (no response required)
690  *     @arg SDIO_FLAG_DATEND Data end (data counter, SDIDCOUNT, is zero)
691  *     @arg SDIO_FLAG_SBERR Start bit not detected on all data signals in wide
692  *                              bus mode
693  *     @arg SDIO_FLAG_DATBLKEND Data block sent/received (CRC check passed)
694  *     @arg SDIO_FLAG_SDIOINT SD I/O interrupt received
695  *     @arg SDIO_FLAG_CEATAF CE-ATA command completion signal received for CMD61
696  */
SDIO_ClrFlag(uint32_t SDIO_FLAG)697 void SDIO_ClrFlag(uint32_t SDIO_FLAG)
698 {
699     /* Check the parameters */
700     assert_param(IS_SDIO_CLR_FLAG(SDIO_FLAG));
701 
702     SDIO->INTCLR = SDIO_FLAG;
703 }
704 
705 /**
706  * @brief  Checks whether the specified SDIO interrupt has occurred or not.
707  * @param SDIO_IT specifies the SDIO interrupt source to check.
708  *   This parameter can be one of the following values:
709  *     @arg SDIO_INT_CCRCERR Command response received (CRC check failed) interrupt
710  *     @arg SDIO_INT_DCRCERR Data block sent/received (CRC check failed) interrupt
711  *     @arg SDIO_INT_CMDTIMEOUT Command response timeout interrupt
712  *     @arg SDIO_INT_DATTIMEOUT Data timeout interrupt
713  *     @arg SDIO_INT_TXURERR Transmit DATFIFO underrun error interrupt
714  *     @arg SDIO_INT_RXORERR Received DATFIFO overrun error interrupt
715  *     @arg SDIO_INT_CMDRESPRECV Command response received (CRC check passed) interrupt
716  *     @arg SDIO_INT_CMDSEND Command sent (no response required) interrupt
717  *     @arg SDIO_INT_DATEND Data end (data counter, SDIDCOUNT, is zero) interrupt
718  *     @arg SDIO_INT_SBERR Start bit not detected on all data signals in wide
719  *                            bus mode interrupt
720  *     @arg SDIO_INT_DATBLKEND Data block sent/received (CRC check passed) interrupt
721  *     @arg SDIO_INT_CMDRUN Command transfer in progress interrupt
722  *     @arg SDIO_INT_TXRUN Data transmit in progress interrupt
723  *     @arg SDIO_INT_RXRUN Data receive in progress interrupt
724  *     @arg SDIO_INT_TFIFOHE Transmit DATFIFO Half Empty interrupt
725  *     @arg SDIO_INT_RFIFOHF Receive DATFIFO Half Full interrupt
726  *     @arg SDIO_INT_TFIFOF Transmit DATFIFO full interrupt
727  *     @arg SDIO_INT_RFIFOF Receive DATFIFO full interrupt
728  *     @arg SDIO_INT_TFIFOE Transmit DATFIFO empty interrupt
729  *     @arg SDIO_INT_RFIFOE Receive DATFIFO empty interrupt
730  *     @arg SDIO_INT_TDATVALID Data available in transmit DATFIFO interrupt
731  *     @arg SDIO_INT_RDATVALID Data available in receive DATFIFO interrupt
732  *     @arg SDIO_INT_SDIOINT SD I/O interrupt received interrupt
733  *     @arg SDIO_INT_CEATAF CE-ATA command completion signal received for CMD61 interrupt
734  * @return The new state of SDIO_IT (SET or RESET).
735  */
SDIO_GetIntStatus(uint32_t SDIO_IT)736 INTStatus SDIO_GetIntStatus(uint32_t SDIO_IT)
737 {
738     INTStatus bitstatus = RESET;
739 
740     /* Check the parameters */
741     assert_param(IS_SDIO_GET_INT(SDIO_IT));
742     if ((SDIO->STS & SDIO_IT) != (uint32_t)RESET)
743     {
744         bitstatus = SET;
745     }
746     else
747     {
748         bitstatus = RESET;
749     }
750     return bitstatus;
751 }
752 
753 /**
754  * @brief  Clears the SDIO's interrupt pending bits.
755  * @param SDIO_IT specifies the interrupt pending bit to clear.
756  *   This parameter can be one or a combination of the following values:
757  *     @arg SDIO_INT_CCRCERR Command response received (CRC check failed) interrupt
758  *     @arg SDIO_INT_DCRCERR Data block sent/received (CRC check failed) interrupt
759  *     @arg SDIO_INT_CMDTIMEOUT Command response timeout interrupt
760  *     @arg SDIO_INT_DATTIMEOUT Data timeout interrupt
761  *     @arg SDIO_INT_TXURERR Transmit DATFIFO underrun error interrupt
762  *     @arg SDIO_INT_RXORERR Received DATFIFO overrun error interrupt
763  *     @arg SDIO_INT_CMDRESPRECV Command response received (CRC check passed) interrupt
764  *     @arg SDIO_INT_CMDSEND Command sent (no response required) interrupt
765  *     @arg SDIO_INT_DATEND Data end (data counter, SDIDCOUNT, is zero) interrupt
766  *     @arg SDIO_INT_SBERR Start bit not detected on all data signals in wide
767  *                            bus mode interrupt
768  *     @arg SDIO_INT_SDIOINT SD I/O interrupt received interrupt
769  *     @arg SDIO_INT_CEATAF CE-ATA command completion signal received for CMD61
770  */
SDIO_ClrIntPendingBit(uint32_t SDIO_IT)771 void SDIO_ClrIntPendingBit(uint32_t SDIO_IT)
772 {
773     /* Check the parameters */
774     assert_param(IS_SDIO_CLR_INT(SDIO_IT));
775 
776     SDIO->INTCLR = SDIO_IT;
777 }
778 
779 /**
780  * @}
781  */
782 
783 /**
784  * @}
785  */
786 
787 /**
788  * @}
789  */
790