1 /*
2 ******************************************************************************
3 * @file HAL_DMA.c
4 * @version V1.0.0
5 * @date 2020
6 * @brief DMA HAL module driver.
7 * This file provides firmware functions to manage the following
8 * functionalities of the Direct Memory Access (DMA) peripheral:
9 * @ Initialization and de-initialization functions
10 * @ IO operation functions
11 ******************************************************************************
12 */
13 #include "ACM32Fxx_HAL.h"
14
15 /**************** Used in cycle mode ****************/
16 static DMA_LLI_InitTypeDef Cycle_Channel[DMA_CHANNEL_NUM];
17
18 /*********************************************************************************
19 * Function : HAL_DMA_IRQHandler
20 * Description : This function handles DMA interrupt request.
21 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
22 * the configuration information for DMA module
23 * Output :
24 * Author : Chris_Kyle Data : 2020
25 **********************************************************************************/
HAL_DMA_IRQHandler(DMA_HandleTypeDef * hdma)26 __weak void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
27 {
28 uint32_t lu32_Channel_Index;
29
30 /* Get DMA Channel number */
31 lu32_Channel_Index = ((uint32_t)(hdma->Instance) - (uint32_t)(DMA_Channel0)) / 0x20;
32
33 /* Channel has been interrupted */
34 if (DMA->INT_STATUS & (1 << lu32_Channel_Index))
35 {
36 /* Transfer complete interrupt */
37 if (DMA->INT_TC_STATUS & (1 << lu32_Channel_Index))
38 {
39 DMA->INT_TC_CLR |= (1 << lu32_Channel_Index);
40
41 if (NULL != hdma->DMA_ITC_Callback)
42 {
43 hdma->DMA_ITC_Callback();
44 }
45 }
46
47 /* Transfer error interrupt */
48 if (DMA->INT_ERR_STATUS & (1 << lu32_Channel_Index))
49 {
50 DMA->INT_ERR_CLR |= (1 << lu32_Channel_Index);
51
52 if (NULL != hdma->DMA_IE_Callback)
53 {
54 hdma->DMA_IE_Callback();
55 }
56 }
57 }
58 }
59
60 /*********************************************************************************
61 * Function : HAL_DMA_Init
62 * Description : DMA initial with parameters.
63 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
64 * the configuration information for DMA module
65 * Output :
66 * Author : Chris_Kyle Data : 2020
67 **********************************************************************************/
HAL_DMA_Init(DMA_HandleTypeDef * hdma)68 HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)
69 {
70 #if (USE_FULL_ASSERT == 1)
71 /* Check DMA Parameter */
72 if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
73 if (!IS_DMA_DATA_FLOW(hdma->Init.Data_Flow)) return HAL_ERROR;
74 if (!IS_DMA_REQUEST_ID(hdma->Init.Request_ID)) return HAL_ERROR;
75 if (!IS_DMA_SRC_WIDTH(hdma->Init.Source_Width)) return HAL_ERROR;
76 if (!IS_DMA_DST_WIDTH(hdma->Init.Desination_Width)) return HAL_ERROR;
77 #endif
78
79 /* Enable DMA Module */
80 System_Module_Enable(EN_DMA);
81
82 /* Enable External Interrupt */
83 NVIC_ClearPendingIRQ(DMA_IRQn);
84 NVIC_EnableIRQ(DMA_IRQn);
85
86 /* Default Little-Endian、Enable DMA */
87 DMA->CONFIG = DMA_CONFIG_EN;
88
89 /* Clear Channel Config */
90 hdma->Instance->CONFIG = 0x00000000;
91
92 if (hdma->Init.Data_Flow == DMA_DATA_FLOW_M2P)
93 {
94 hdma->Init.Request_ID <<= DMA_CHANNEL_CONFIG_DEST_PERIPH_POS;
95 }
96 else if (hdma->Init.Data_Flow == DMA_DATA_FLOW_P2M)
97 {
98 hdma->Init.Request_ID <<= DMA_CHANNEL_CONFIG_SRC_PERIPH_POS;
99 }
100
101 hdma->Instance->CONFIG = hdma->Init.Data_Flow | hdma->Init.Request_ID;
102
103 /* Config Channel Control */
104
105 hdma->Instance->CTRL = DMA_CHANNEL_CTRL_ITC;
106
107 /* Source or Desination address increase */
108 hdma->Instance->CTRL |= (hdma->Init.Desination_Inc | hdma->Init.Source_Inc);
109 /* Source or Desination date width */
110 hdma->Instance->CTRL |= (hdma->Init.Desination_Width | hdma->Init.Source_Width);
111
112 return HAL_OK;
113 }
114
115 /*********************************************************************************
116 * Function : HAL_DMA_DeInit
117 * Description : DMA De-initial with parameters.
118 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
119 * the configuration information for DMA module
120 * Output :
121 * Author : Chris_Kyle Data : 2020
122 **********************************************************************************/
HAL_DMA_DeInit(DMA_HandleTypeDef * hdma)123 HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
124 {
125 #if (USE_FULL_ASSERT == 1)
126 /* Check DMA Parameter */
127 if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
128 if (!IS_DMA_DATA_FLOW(hdma->Init.Data_Flow)) return HAL_ERROR;
129 if (!IS_DMA_REQUEST_ID(hdma->Init.Request_ID)) return HAL_ERROR;
130 if (!IS_DMA_SRC_WIDTH(hdma->Init.Source_Width)) return HAL_ERROR;
131 if (!IS_DMA_DST_WIDTH(hdma->Init.Desination_Width)) return HAL_ERROR;
132 #endif
133
134 /* Reset DMA Module */
135 System_Module_Reset(RST_DMA);
136
137 /* Disable DMA Module */
138 System_Module_Disable(EN_DMA);
139
140 /* Disable Interrupt */
141 NVIC_ClearPendingIRQ(DMA_IRQn);
142 NVIC_DisableIRQ(DMA_IRQn);
143
144 hdma->DMA_IE_Callback = NULL;
145 hdma->DMA_ITC_Callback = NULL;
146
147 memset(&hdma->Init, 0, sizeof(hdma->Init));
148
149 return HAL_OK;
150 }
151
152 /*********************************************************************************
153 * Function : HAL_DMA_NormalMode_Start
154 * Description : DMA transfer start.
155 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
156 * the configuration information for DMA module
157 * Input : fu32_SrcAddr: source address
158 * Input : fu32_DstAddr: desination address
159 * Input : fu32_Size: transfer size (This parameter can be a 12-bit Size)
160 * Output :
161 * Author : Chris_Kyle Data : 2020
162 **********************************************************************************/
HAL_DMA_NormalMode_Start(DMA_HandleTypeDef * hdma,uint32_t fu32_SrcAddr,uint32_t fu32_DstAddr,uint32_t fu32_Size)163 HAL_StatusTypeDef HAL_DMA_NormalMode_Start(DMA_HandleTypeDef *hdma, uint32_t fu32_SrcAddr, uint32_t fu32_DstAddr, uint32_t fu32_Size)
164 {
165 #if (USE_FULL_ASSERT == 1)
166 /* Check DMA Parameter */
167 if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
168 #endif
169
170 if (fu32_Size > 0xFFF)
171 {
172 return HAL_ERROR;
173 }
174
175 /* Set source address and desination address */
176 hdma->Instance->SRC_ADDR = fu32_SrcAddr;
177 hdma->Instance->DEST_ADDR = fu32_DstAddr;
178
179 /* Set Transfer Size */
180 hdma->Instance->CTRL = (hdma->Instance->CTRL & (~0xFFF)) | fu32_Size;
181
182 /* DMA Channel Enable */
183 hdma->Instance->CONFIG |= DMA_CHANNEL_CONFIG_EN;
184
185 return HAL_OK;
186 }
187
188 /*********************************************************************************
189 * Function : HAL_DMA_NormalMode_Start_IT
190 * Description : DMA transfer start with interrupt.
191 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
192 * the configuration information for DMA module
193 * Input : fu32_SrcAddr: source address
194 * Input : fu32_DstAddr: desination address
195 * Input : fu32_Size: transfer size (This parameter can be a 12-bit Size)
196 * Output :
197 * Author : Chris_Kyle Data : 2020
198 **********************************************************************************/
HAL_DMA_NormalMode_Start_IT(DMA_HandleTypeDef * hdma,uint32_t fu32_SrcAddr,uint32_t fu32_DstAddr,uint32_t fu32_Size)199 HAL_StatusTypeDef HAL_DMA_NormalMode_Start_IT(DMA_HandleTypeDef *hdma, uint32_t fu32_SrcAddr, uint32_t fu32_DstAddr, uint32_t fu32_Size)
200 {
201 #if (USE_FULL_ASSERT == 1)
202 /* Check DMA Parameter */
203 if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
204 #endif
205
206 /* Set source address and desination address */
207 hdma->Instance->SRC_ADDR = fu32_SrcAddr;
208 hdma->Instance->DEST_ADDR = fu32_DstAddr;
209
210 /* Set Transfer Size and enable LLI interrupt */
211 hdma->Instance->CTRL = (hdma->Instance->CTRL & (~0xFFF)) | fu32_Size;
212 // hdma->Instance->CTRL &=~(1<<31);
213 /* DMA Channel Enable and enable transfer error interrupt and transfer complete interrupt*/
214 hdma->Instance->CONFIG |= DMA_CHANNEL_CONFIG_ITC | DMA_CHANNEL_CONFIG_IE | DMA_CHANNEL_CONFIG_EN;
215
216 return HAL_OK;
217 }
218
219 /*********************************************************************************
220 * Function : HAL_DMA_CycleMode_Start
221 * Description : DMA Cycle transfer start.
222 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
223 * the configuration information for DMA module
224 * Input : fu32_SrcAddr: source address
225 * Input : fu32_DstAddr: desination address
226 * Input : fu32_Size: transfer size (This parameter can be a 12-bit Size)
227 * Output :
228 * Author : Chris_Kyle Data : 2020
229 **********************************************************************************/
HAL_DMA_CycleMode_Start(DMA_HandleTypeDef * hdma,uint32_t fu32_SrcAddr,uint32_t fu32_DstAddr,uint32_t fu32_Size)230 HAL_StatusTypeDef HAL_DMA_CycleMode_Start(DMA_HandleTypeDef *hdma, uint32_t fu32_SrcAddr, uint32_t fu32_DstAddr, uint32_t fu32_Size)
231 {
232 uint32_t lu32_Channel_Index;
233
234 #if (USE_FULL_ASSERT == 1)
235 /* Check DMA Parameter */
236 if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
237 #endif
238
239 /* Get DMA Channel number */
240 lu32_Channel_Index = ((uint32_t)(hdma->Instance) - (uint32_t)(DMA_Channel0)) / 0x20;
241
242 /* Set source address and desination address */
243 hdma->Instance->SRC_ADDR = fu32_SrcAddr;
244 hdma->Instance->DEST_ADDR = fu32_DstAddr;
245
246 /* Set Next Link */
247 hdma->Instance->LLI = (uint32_t)&Cycle_Channel[lu32_Channel_Index];
248
249 /* Set Transfer Size */
250 hdma->Instance->CTRL = (hdma->Instance->CTRL & (~0xFFF)) | fu32_Size;
251
252 /* The list point to oneself */
253 Cycle_Channel[lu32_Channel_Index].SrcAddr = fu32_SrcAddr;
254 Cycle_Channel[lu32_Channel_Index].DstAddr = fu32_DstAddr;
255 Cycle_Channel[lu32_Channel_Index].Next = &Cycle_Channel[lu32_Channel_Index];
256 Cycle_Channel[lu32_Channel_Index].Control = (hdma->Instance->CTRL & (~0xFFF)) | fu32_Size;
257
258 /* DMA Channel Enable */
259 hdma->Instance->CONFIG |= DMA_CHANNEL_CONFIG_EN;
260
261 return HAL_OK;
262 }
263
264 /*********************************************************************************
265 * Function : HAL_DMA_CycleMode_Start_IT
266 * Description : DMA Cycle transfer start with interrupt.
267 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
268 * the configuration information for DMA module
269 * Input : fu32_SrcAddr: source address
270 * Input : fu32_DstAddr: desination address
271 * Input : fu32_Size: transfer size (This parameter can be a 12-bit Size)
272 * Output :
273 * Author : Chris_Kyle Data : 2020
274 **********************************************************************************/
HAL_DMA_CycleMode_Start_IT(DMA_HandleTypeDef * hdma,uint32_t fu32_SrcAddr,uint32_t fu32_DstAddr,uint32_t fu32_Size)275 HAL_StatusTypeDef HAL_DMA_CycleMode_Start_IT(DMA_HandleTypeDef *hdma, uint32_t fu32_SrcAddr, uint32_t fu32_DstAddr, uint32_t fu32_Size)
276 {
277 uint32_t lu32_Channel_Index;
278
279 #if (USE_FULL_ASSERT == 1)
280 /* Check DMA Parameter */
281 if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
282 #endif
283
284 /* Get DMA Channel number */
285 lu32_Channel_Index = ((uint32_t)(hdma->Instance) - (uint32_t)(DMA_Channel0)) / 0x20;
286
287 /* Set source address and desination address */
288 hdma->Instance->SRC_ADDR = fu32_SrcAddr;
289 hdma->Instance->DEST_ADDR = fu32_DstAddr;
290
291 /* Set Next Link */
292 hdma->Instance->LLI = (uint32_t)&Cycle_Channel[lu32_Channel_Index];
293
294 /* Set Transfer Size */
295 hdma->Instance->CTRL = (hdma->Instance->CTRL & (~0xFFF)) | fu32_Size;
296
297 /* The list point to oneself */
298 Cycle_Channel[lu32_Channel_Index].SrcAddr = fu32_SrcAddr;
299 Cycle_Channel[lu32_Channel_Index].DstAddr = fu32_DstAddr;
300 Cycle_Channel[lu32_Channel_Index].Next = &Cycle_Channel[lu32_Channel_Index];
301 Cycle_Channel[lu32_Channel_Index].Control = (hdma->Instance->CTRL & (~0xFFF)) | fu32_Size;
302
303 /* DMA Channel Enable and enable transfer error interrupt and transfer complete interrupt*/
304 hdma->Instance->CONFIG |= DMA_CHANNEL_CONFIG_ITC | DMA_CHANNEL_CONFIG_IE | DMA_CHANNEL_CONFIG_EN;
305
306 return HAL_OK;
307 }
308
309 /*********************************************************************************
310 * Function : HAL_DMA_Start
311 * Description : DMA transfer start.
312 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
313 * the configuration information for DMA module
314 * Input : fu32_SrcAddr: source address
315 * Input : fu32_DstAddr: desination address
316 * Input : fu32_Size: transfer size (This parameter can be a 12-bit Size)
317 * Output :
318 * Author : Chris_Kyle Data : 2020
319 **********************************************************************************/
HAL_DMA_Start(DMA_HandleTypeDef * hdma,uint32_t fu32_SrcAddr,uint32_t fu32_DstAddr,uint32_t fu32_Size)320 HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t fu32_SrcAddr, uint32_t fu32_DstAddr, uint32_t fu32_Size)
321 {
322 /* Check DMA Parameter */
323 if (!IS_DMA_MODE(hdma->Init.Mode)) return HAL_ERROR;
324
325 if (hdma->Init.Mode == DMA_NORMAL)
326 {
327 return HAL_DMA_NormalMode_Start(hdma, fu32_SrcAddr, fu32_DstAddr, fu32_Size);
328 }
329 else
330 {
331 return HAL_DMA_CycleMode_Start(hdma, fu32_SrcAddr, fu32_DstAddr, fu32_Size);
332 }
333 }
334
335 /*********************************************************************************
336 * Function : HAL_DMA_Start_IT
337 * Description : DMA transfer start with interrupt.
338 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
339 * the configuration information for DMA module
340 * Input : fu32_SrcAddr: source address
341 * Input : fu32_DstAddr: desination address
342 * Input : fu32_Size: transfer size (This parameter can be a 12-bit Size)
343 * Output :
344 * Author : Chris_Kyle Data : 2020
345 **********************************************************************************/
HAL_DMA_Start_IT(DMA_HandleTypeDef * hdma,uint32_t fu32_SrcAddr,uint32_t fu32_DstAddr,uint32_t fu32_Size)346 HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t fu32_SrcAddr, uint32_t fu32_DstAddr, uint32_t fu32_Size)
347 {
348 /* Check DMA Parameter */
349 if (!IS_DMA_MODE(hdma->Init.Mode)) return HAL_ERROR;
350
351 if (hdma->Init.Mode == DMA_NORMAL)
352 {
353 return HAL_DMA_NormalMode_Start_IT(hdma, fu32_SrcAddr, fu32_DstAddr, fu32_Size);
354 }
355 else
356 {
357 return HAL_DMA_CycleMode_Start_IT(hdma, fu32_SrcAddr, fu32_DstAddr, fu32_Size);
358 }
359 }
360
361 /*********************************************************************************
362 * Function : HAL_DMA_Abort
363 * Description : Abort the DMA Transfer
364 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
365 * the configuration information for DMA module
366 * Output :
367 * Author : Chris_Kyle Data : 2020
368 **********************************************************************************/
HAL_DMA_Abort(DMA_HandleTypeDef * hdma)369 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
370 {
371 uint32_t lu32_Channel_Index;
372
373 #if (USE_FULL_ASSERT == 1)
374 /* Check DMA Parameter */
375 if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
376 #endif
377
378 /* Get DMA Channel number */
379 lu32_Channel_Index = ((uint32_t)(hdma->Instance) - (uint32_t)(DMA_Channel0)) / 0x20;
380
381 /* DMA Channel Disable */
382 hdma->Instance->CONFIG &= ~(1 << 0);
383
384 /* Clear TC ERR Falg */
385 DMA->INT_TC_CLR |= (1 << lu32_Channel_Index);
386 DMA->INT_ERR_CLR |= (1 << lu32_Channel_Index);
387
388 return HAL_OK;
389 }
390
391 /*********************************************************************************
392 * Function : HAL_DMA_GetState
393 * Description : Returns the DMA state..
394 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
395 * the configuration information for DMA module
396 * Output :
397 * Author : Data : 2021
398 **********************************************************************************/
HAL_DMA_GetState(DMA_HandleTypeDef * hdma)399 HAL_StatusTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
400 {
401 uint32_t lu32_Channel_Index;
402 HAL_StatusTypeDef States = HAL_ERROR;
403
404 /* Get DMA Channel number */
405 lu32_Channel_Index = ((uint32_t)(hdma->Instance) - (uint32_t)(DMA_Channel0)) / 0x20;
406
407 /* Transfer complete interrupt */
408 if (DMA->RAW_INT_TC_STATUS & (1 << lu32_Channel_Index))
409 {
410 DMA->INT_TC_CLR |= (1 << lu32_Channel_Index);
411
412 States = HAL_OK;
413 }
414
415 /* Transfer error interrupt */
416 if (DMA->RAW_INT_ERR_STATUS & (1 << lu32_Channel_Index))
417 {
418 DMA->INT_ERR_CLR |= (1 << lu32_Channel_Index);
419
420 States = HAL_ERROR;
421 }
422
423 return States;
424 }
425