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 hdma->Instance->CTRL = DMA_CHANNEL_CTRL_ITC;
105 /* Source or Desination address increase */
106 hdma->Instance->CTRL |= (hdma->Init.Desination_Inc | hdma->Init.Source_Inc);
107 /* Source or Desination date width */
108 hdma->Instance->CTRL |= (hdma->Init.Desination_Width | hdma->Init.Source_Width);
109
110 return HAL_OK;
111 }
112
113 /*********************************************************************************
114 * Function : HAL_DMA_DeInit
115 * Description : DMA De-initial with parameters.
116 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
117 * the configuration information for DMA module
118 * Output :
119 * Author : Chris_Kyle Data : 2020
120 **********************************************************************************/
HAL_DMA_DeInit(DMA_HandleTypeDef * hdma)121 HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
122 {
123 #if (USE_FULL_ASSERT == 1)
124 /* Check DMA Parameter */
125 if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
126 if (!IS_DMA_DATA_FLOW(hdma->Init.Data_Flow)) return HAL_ERROR;
127 if (!IS_DMA_REQUEST_ID(hdma->Init.Request_ID)) return HAL_ERROR;
128 if (!IS_DMA_SRC_WIDTH(hdma->Init.Source_Width)) return HAL_ERROR;
129 if (!IS_DMA_DST_WIDTH(hdma->Init.Desination_Width)) return HAL_ERROR;
130 #endif
131
132 /* Reset DMA Module */
133 System_Module_Reset(RST_DMA);
134
135 /* Disable DMA Module */
136 System_Module_Disable(EN_DMA);
137
138 /* Disable Interrupt */
139 NVIC_ClearPendingIRQ(DMA_IRQn);
140 NVIC_DisableIRQ(DMA_IRQn);
141
142 hdma->DMA_IE_Callback = NULL;
143 hdma->DMA_ITC_Callback = NULL;
144
145 memset(&hdma->Init, 0, sizeof(hdma->Init));
146
147 return HAL_OK;
148 }
149
150 /*********************************************************************************
151 * Function : HAL_DMA_NormalMode_Start
152 * Description : DMA transfer start.
153 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
154 * the configuration information for DMA module
155 * Input : fu32_SrcAddr: source address
156 * Input : fu32_DstAddr: desination address
157 * Input : fu32_Size: transfer size (This parameter can be a 12-bit Size)
158 * Output :
159 * Author : Chris_Kyle Data : 2020
160 **********************************************************************************/
HAL_DMA_NormalMode_Start(DMA_HandleTypeDef * hdma,uint32_t fu32_SrcAddr,uint32_t fu32_DstAddr,uint32_t fu32_Size)161 HAL_StatusTypeDef HAL_DMA_NormalMode_Start(DMA_HandleTypeDef *hdma, uint32_t fu32_SrcAddr, uint32_t fu32_DstAddr, uint32_t fu32_Size)
162 {
163 #if (USE_FULL_ASSERT == 1)
164 /* Check DMA Parameter */
165 if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
166 #endif
167
168 if (fu32_Size > 0xFFF)
169 {
170 return HAL_ERROR;
171 }
172
173 /* Set source address and desination address */
174 hdma->Instance->SRC_ADDR = fu32_SrcAddr;
175 hdma->Instance->DEST_ADDR = fu32_DstAddr;
176
177 /* Set Transfer Size */
178 hdma->Instance->CTRL = (hdma->Instance->CTRL & (~0xFFF)) | fu32_Size;
179
180 /* DMA Channel Enable */
181 hdma->Instance->CONFIG |= DMA_CHANNEL_CONFIG_EN;
182
183 return HAL_OK;
184 }
185
186 /*********************************************************************************
187 * Function : HAL_DMA_NormalMode_Start_IT
188 * Description : DMA transfer start with interrupt.
189 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
190 * the configuration information for DMA module
191 * Input : fu32_SrcAddr: source address
192 * Input : fu32_DstAddr: desination address
193 * Input : fu32_Size: transfer size (This parameter can be a 12-bit Size)
194 * Output :
195 * Author : Chris_Kyle Data : 2020
196 **********************************************************************************/
HAL_DMA_NormalMode_Start_IT(DMA_HandleTypeDef * hdma,uint32_t fu32_SrcAddr,uint32_t fu32_DstAddr,uint32_t fu32_Size)197 HAL_StatusTypeDef HAL_DMA_NormalMode_Start_IT(DMA_HandleTypeDef *hdma, uint32_t fu32_SrcAddr, uint32_t fu32_DstAddr, uint32_t fu32_Size)
198 {
199 #if (USE_FULL_ASSERT == 1)
200 /* Check DMA Parameter */
201 if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
202 #endif
203
204 /* Set source address and desination address */
205 hdma->Instance->SRC_ADDR = fu32_SrcAddr;
206 hdma->Instance->DEST_ADDR = fu32_DstAddr;
207
208 /* Set Transfer Size and enable LLI interrupt */
209 hdma->Instance->CTRL = (hdma->Instance->CTRL & (~0xFFF)) | fu32_Size;
210
211 /* DMA Channel Enable and enable transfer error interrupt and transfer complete interrupt*/
212 hdma->Instance->CONFIG |= DMA_CHANNEL_CONFIG_ITC | DMA_CHANNEL_CONFIG_IE | DMA_CHANNEL_CONFIG_EN;
213
214 return HAL_OK;
215 }
216
217 /*********************************************************************************
218 * Function : HAL_DMA_CycleMode_Start
219 * Description : DMA Cycle transfer start.
220 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
221 * the configuration information for DMA module
222 * Input : fu32_SrcAddr: source address
223 * Input : fu32_DstAddr: desination address
224 * Input : fu32_Size: transfer size (This parameter can be a 12-bit Size)
225 * Output :
226 * Author : Chris_Kyle Data : 2020
227 **********************************************************************************/
HAL_DMA_CycleMode_Start(DMA_HandleTypeDef * hdma,uint32_t fu32_SrcAddr,uint32_t fu32_DstAddr,uint32_t fu32_Size)228 HAL_StatusTypeDef HAL_DMA_CycleMode_Start(DMA_HandleTypeDef *hdma, uint32_t fu32_SrcAddr, uint32_t fu32_DstAddr, uint32_t fu32_Size)
229 {
230 uint32_t lu32_Channel_Index;
231
232 #if (USE_FULL_ASSERT == 1)
233 /* Check DMA Parameter */
234 if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
235 #endif
236
237 /* Get DMA Channel number */
238 lu32_Channel_Index = ((uint32_t)(hdma->Instance) - (uint32_t)(DMA_Channel0)) / 0x20;
239
240 /* Set source address and desination address */
241 hdma->Instance->SRC_ADDR = fu32_SrcAddr;
242 hdma->Instance->DEST_ADDR = fu32_DstAddr;
243
244 /* Set Next Link */
245 hdma->Instance->LLI = (uint32_t)&Cycle_Channel[lu32_Channel_Index];
246
247 /* Set Transfer Size */
248 hdma->Instance->CTRL = (hdma->Instance->CTRL & (~0xFFF)) | fu32_Size;
249
250 /* The list point to oneself */
251 Cycle_Channel[lu32_Channel_Index].SrcAddr = fu32_SrcAddr;
252 Cycle_Channel[lu32_Channel_Index].DstAddr = fu32_DstAddr;
253 Cycle_Channel[lu32_Channel_Index].Next = &Cycle_Channel[lu32_Channel_Index];
254 Cycle_Channel[lu32_Channel_Index].Control = (hdma->Instance->CTRL & (~0xFFF)) | fu32_Size;
255
256 /* DMA Channel Enable */
257 hdma->Instance->CONFIG |= DMA_CHANNEL_CONFIG_EN;
258
259 return HAL_OK;
260 }
261
262 /*********************************************************************************
263 * Function : HAL_DMA_CycleMode_Start_IT
264 * Description : DMA Cycle transfer start with interrupt.
265 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
266 * the configuration information for DMA module
267 * Input : fu32_SrcAddr: source address
268 * Input : fu32_DstAddr: desination address
269 * Input : fu32_Size: transfer size (This parameter can be a 12-bit Size)
270 * Output :
271 * Author : Chris_Kyle Data : 2020
272 **********************************************************************************/
HAL_DMA_CycleMode_Start_IT(DMA_HandleTypeDef * hdma,uint32_t fu32_SrcAddr,uint32_t fu32_DstAddr,uint32_t fu32_Size)273 HAL_StatusTypeDef HAL_DMA_CycleMode_Start_IT(DMA_HandleTypeDef *hdma, uint32_t fu32_SrcAddr, uint32_t fu32_DstAddr, uint32_t fu32_Size)
274 {
275 uint32_t lu32_Channel_Index;
276
277 #if (USE_FULL_ASSERT == 1)
278 /* Check DMA Parameter */
279 if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
280 #endif
281
282 /* Get DMA Channel number */
283 lu32_Channel_Index = ((uint32_t)(hdma->Instance) - (uint32_t)(DMA_Channel0)) / 0x20;
284
285 /* Set source address and desination address */
286 hdma->Instance->SRC_ADDR = fu32_SrcAddr;
287 hdma->Instance->DEST_ADDR = fu32_DstAddr;
288
289 /* Set Next Link */
290 hdma->Instance->LLI = (uint32_t)&Cycle_Channel[lu32_Channel_Index];
291
292 /* Set Transfer Size */
293 hdma->Instance->CTRL = (hdma->Instance->CTRL & (~0xFFF)) | fu32_Size;
294
295 /* The list point to oneself */
296 Cycle_Channel[lu32_Channel_Index].SrcAddr = fu32_SrcAddr;
297 Cycle_Channel[lu32_Channel_Index].DstAddr = fu32_DstAddr;
298 Cycle_Channel[lu32_Channel_Index].Next = &Cycle_Channel[lu32_Channel_Index];
299 Cycle_Channel[lu32_Channel_Index].Control = (hdma->Instance->CTRL & (~0xFFF)) | fu32_Size;
300
301 /* DMA Channel Enable and enable transfer error interrupt and transfer complete interrupt*/
302 hdma->Instance->CONFIG |= DMA_CHANNEL_CONFIG_ITC | DMA_CHANNEL_CONFIG_IE | DMA_CHANNEL_CONFIG_EN;
303
304 return HAL_OK;
305 }
306
307 /*********************************************************************************
308 * Function : HAL_DMA_Start
309 * Description : DMA transfer start.
310 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
311 * the configuration information for DMA module
312 * Input : fu32_SrcAddr: source address
313 * Input : fu32_DstAddr: desination address
314 * Input : fu32_Size: transfer size (This parameter can be a 12-bit Size)
315 * Output :
316 * Author : Chris_Kyle Data : 2020
317 **********************************************************************************/
HAL_DMA_Start(DMA_HandleTypeDef * hdma,uint32_t fu32_SrcAddr,uint32_t fu32_DstAddr,uint32_t fu32_Size)318 HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t fu32_SrcAddr, uint32_t fu32_DstAddr, uint32_t fu32_Size)
319 {
320 /* Check DMA Parameter */
321 if (!IS_DMA_MODE(hdma->Init.Mode)) return HAL_ERROR;
322
323 if (hdma->Init.Mode == DMA_NORMAL)
324 {
325 return HAL_DMA_NormalMode_Start(hdma, fu32_SrcAddr, fu32_DstAddr, fu32_Size);
326 }
327 else
328 {
329 return HAL_DMA_CycleMode_Start(hdma, fu32_SrcAddr, fu32_DstAddr, fu32_Size);
330 }
331 }
332
333 /*********************************************************************************
334 * Function : HAL_DMA_Start_IT
335 * Description : DMA transfer start with interrupt.
336 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
337 * the configuration information for DMA module
338 * Input : fu32_SrcAddr: source address
339 * Input : fu32_DstAddr: desination address
340 * Input : fu32_Size: transfer size (This parameter can be a 12-bit Size)
341 * Output :
342 * Author : Chris_Kyle Data : 2020
343 **********************************************************************************/
HAL_DMA_Start_IT(DMA_HandleTypeDef * hdma,uint32_t fu32_SrcAddr,uint32_t fu32_DstAddr,uint32_t fu32_Size)344 HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t fu32_SrcAddr, uint32_t fu32_DstAddr, uint32_t fu32_Size)
345 {
346 /* Check DMA Parameter */
347 if (!IS_DMA_MODE(hdma->Init.Mode)) return HAL_ERROR;
348
349 if (hdma->Init.Mode == DMA_NORMAL)
350 {
351 return HAL_DMA_NormalMode_Start_IT(hdma, fu32_SrcAddr, fu32_DstAddr, fu32_Size);
352 }
353 else
354 {
355 return HAL_DMA_CycleMode_Start_IT(hdma, fu32_SrcAddr, fu32_DstAddr, fu32_Size);
356 }
357 }
358
359 /*********************************************************************************
360 * Function : HAL_DMA_Abort
361 * Description : Abort the DMA Transfer
362 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
363 * the configuration information for DMA module
364 * Output :
365 * Author : Chris_Kyle Data : 2020
366 **********************************************************************************/
HAL_DMA_Abort(DMA_HandleTypeDef * hdma)367 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
368 {
369 uint32_t lu32_Channel_Index;
370
371 #if (USE_FULL_ASSERT == 1)
372 /* Check DMA Parameter */
373 if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
374 #endif
375
376 /* Get DMA Channel number */
377 lu32_Channel_Index = ((uint32_t)(hdma->Instance) - (uint32_t)(DMA_Channel0)) / 0x20;
378
379 /* DMA Channel Disable */
380 hdma->Instance->CONFIG &= ~(1 << 0);
381
382 /* Clear TC ERR Falg */
383 DMA->INT_TC_CLR |= (1 << lu32_Channel_Index);
384 DMA->INT_ERR_CLR |= (1 << lu32_Channel_Index);
385
386 return HAL_OK;
387 }
388
389 /*********************************************************************************
390 * Function : HAL_DMA_GetState
391 * Description : Returns the DMA state..
392 * Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
393 * the configuration information for DMA module
394 * Output :
395 * Author : Data : 2021
396 **********************************************************************************/
HAL_DMA_GetState(DMA_HandleTypeDef * hdma)397 HAL_StatusTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
398 {
399 uint32_t lu32_Channel_Index;
400 HAL_StatusTypeDef States = HAL_ERROR;
401
402 /* Get DMA Channel number */
403 lu32_Channel_Index = ((uint32_t)(hdma->Instance) - (uint32_t)(DMA_Channel0)) / 0x20;
404
405 /* Transfer complete interrupt */
406 if (DMA->RAW_INT_TC_STATUS & (1 << lu32_Channel_Index))
407 {
408 DMA->INT_TC_CLR |= (1 << lu32_Channel_Index);
409
410 States = HAL_OK;
411 }
412
413 /* Transfer error interrupt */
414 if (DMA->RAW_INT_ERR_STATUS & (1 << lu32_Channel_Index))
415 {
416 DMA->INT_ERR_CLR |= (1 << lu32_Channel_Index);
417
418 States = HAL_ERROR;
419 }
420
421 return States;
422 }
423