1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 */
9
10 #include <rtthread.h>
11 #include <rthw.h>
12 #include <drivers/dev_mmcsd_core.h>
13 #include <drivers/dev_sdio.h>
14
15 #include "stm32l4xx.h"
16
17 #ifdef BSP_USING_STM32_SDIO
18
19 #include <stm32_sdio.h>
20
21 static DMA_HandleTypeDef SDTxDMAHandler;
22 static DMA_HandleTypeDef SDRxDMAHandler;
23
24 static struct rt_mmcsd_host *host;
25
SDMMC1_IRQHandler(void)26 void SDMMC1_IRQHandler(void)
27 {
28 /* enter interrupt */
29 rt_interrupt_enter();
30
31 /* Process All SDIO Interrupt Sources */
32 rthw_sdio_irq_process(host);
33
34 /* leave interrupt */
35 rt_interrupt_leave();
36 }
37
38 /**
39 * @brief Configures the DMA2 Channel4 for SDIO Tx request.
40 * @param BufferSRC: pointer to the source buffer
41 * @param BufferSize: buffer size
42 * @retval None
43 */
SD_LowLevel_DMA_TxConfig(uint32_t * src,uint32_t * dst,uint32_t BufferSize)44 void SD_LowLevel_DMA_TxConfig(uint32_t *src, uint32_t *dst, uint32_t BufferSize)
45 {
46 DMA2_Channel4->CCR &= ~0x00000001;
47
48 DMA2->IFCR = DMA_ISR_GIF1 << 4;
49
50 DMA2_CSELR->CSELR &= ~(0xf << (3 * 4)); // channel 4
51 DMA2_CSELR->CSELR |= (uint32_t) (0x07 << (3 * 4));
52
53 DMA2_Channel4->CCR = DMA_MEMORY_TO_PERIPH | DMA_PINC_DISABLE | DMA_MINC_ENABLE | \
54 DMA_PDATAALIGN_WORD | DMA_MDATAALIGN_WORD | DMA_NORMAL | DMA_PRIORITY_MEDIUM;
55 DMA2_Channel4->CNDTR = BufferSize;
56 DMA2_Channel4->CPAR = (uint32_t)dst;
57 DMA2_Channel4->CMAR = (uint32_t)src;
58
59 DMA2_Channel4->CCR |= 0x00000001;
60
61 // HAL_DMA_Start(&SDTxDMAHandler, (uint32_t)src, (uint32_t)dst, BufferSize);
62 }
63
64 /**
65 * @brief Configures the DMA2 Channel4 for SDIO Rx request.
66 * @param BufferDST: pointer to the destination buffer
67 * @param BufferSize: buffer size
68 * @retval None
69 */
SD_LowLevel_DMA_RxConfig(uint32_t * src,uint32_t * dst,uint32_t BufferSize)70 void SD_LowLevel_DMA_RxConfig(uint32_t *src, uint32_t *dst, uint32_t BufferSize)
71 {
72
73 DMA2_Channel4->CCR &= ~0x00000001;
74
75 DMA2->IFCR = DMA_ISR_GIF1 << 4;
76
77 DMA2_CSELR->CSELR &= ~(0xf << (3 * 4)); // channel 4
78 DMA2_CSELR->CSELR |= (uint32_t) (0x07 << (3 * 4));
79
80 DMA2_Channel4->CCR = DMA_PERIPH_TO_MEMORY | DMA_PINC_DISABLE | DMA_MINC_ENABLE | \
81 DMA_PDATAALIGN_WORD | DMA_MDATAALIGN_WORD | DMA_NORMAL | DMA_PRIORITY_MEDIUM;
82 DMA2_Channel4->CNDTR = BufferSize;
83 DMA2_Channel4->CPAR = (uint32_t)src;
84 DMA2_Channel4->CMAR = (uint32_t)dst;
85
86 DMA2_Channel4->CCR |= 0x00000001;
87 }
88
SD_LowLevel_Init(void)89 void SD_LowLevel_Init(void)
90 {
91 {
92 // clock enable
93 __HAL_RCC_GPIOB_CLK_ENABLE();
94 __HAL_RCC_GPIOC_CLK_ENABLE();
95 __HAL_RCC_GPIOD_CLK_ENABLE();
96 __HAL_RCC_DMA2_CLK_ENABLE();
97 __HAL_RCC_SDMMC1_CLK_ENABLE();
98 }
99
100 {
101 HAL_NVIC_EnableIRQ(SDMMC1_IRQn);
102 }
103
104 {
105 // init sdio hardware
106 GPIO_InitTypeDef GPIO_InitStruct;
107
108 /*Configure GPIO pin Output Level */
109 HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_RESET);
110 GPIO_InitStruct.Pin = GPIO_PIN_1;
111 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
112 GPIO_InitStruct.Pull = GPIO_NOPULL;
113 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
114 HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
115 rt_thread_delay(1);
116 HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_SET);
117
118 /* Setup GPIO pins for SDIO data & clock */
119 /**SDMMC1 GPIO Configuration
120 PC8 ------> SDMMC1_D0
121 PC9 ------> SDMMC1_D1
122 PC10 ------> SDMMC1_D2
123 PC11 ------> SDMMC1_D3
124 PC12 ------> SDMMC1_CK
125 PD2 ------> SDMMC1_CMD
126 */
127 GPIO_InitStruct.Pin = GPIO_PIN_9;
128 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
129 GPIO_InitStruct.Pull = GPIO_PULLUP;
130 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
131 GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
132 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
133
134 GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_10 | GPIO_PIN_11
135 | GPIO_PIN_12;
136 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
137 GPIO_InitStruct.Pull = GPIO_PULLUP;
138 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
139 GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
140 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
141
142 GPIO_InitStruct.Pin = GPIO_PIN_2;
143 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
144 GPIO_InitStruct.Pull = GPIO_PULLUP;
145 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
146 GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
147
148 HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
149 }
150
151 {
152 }
153 }
154
stm32_sdio_clock_get(struct stm32_sdio * hw_sdio)155 static rt_uint32_t stm32_sdio_clock_get(struct stm32_sdio *hw_sdio)
156 {
157 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC1);
158 }
159
DMA_TxConfig(rt_uint32_t * src,rt_uint32_t * dst,int Size)160 static rt_err_t DMA_TxConfig(rt_uint32_t *src, rt_uint32_t *dst, int Size)
161 {
162 SD_LowLevel_DMA_TxConfig((uint32_t *)src, (uint32_t *)dst, Size / 4);
163 return RT_EOK;
164 }
165
DMA_RxConfig(rt_uint32_t * src,rt_uint32_t * dst,int Size)166 static rt_err_t DMA_RxConfig(rt_uint32_t *src, rt_uint32_t *dst, int Size)
167 {
168 SD_LowLevel_DMA_RxConfig((uint32_t *)src, (uint32_t *)dst, Size / 4);
169 return RT_EOK;
170 }
171
stm32f4xx_sdio_init(void)172 int stm32f4xx_sdio_init(void)
173 {
174 struct stm32_sdio_des sdio_des;
175
176 SD_LowLevel_Init();
177
178 sdio_des.clk_get = stm32_sdio_clock_get;
179 sdio_des.hw_sdio = (struct stm32_sdio *)0x40012800U;
180 sdio_des.rxconfig = DMA_RxConfig;
181 sdio_des.txconfig = DMA_TxConfig;
182
183 host = sdio_host_create(&sdio_des);
184 if (host == RT_NULL)
185 {
186 rt_kprintf("%s host create fail\n");
187 return -1;
188 }
189
190 return 0;
191 }
192 INIT_DEVICE_EXPORT(stm32f4xx_sdio_init);
193
194 #endif
195