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