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