1 /*!
2     \file    gd32e10x_dma.c
3     \brief   DMA driver
4 
5     \version 2017-12-26, V1.0.0, firmware for GD32E10x
6     \version 2020-09-30, V1.1.0, firmware for GD32E10x
7     \version 2020-12-31, V1.2.0, firmware for GD32E10x
8     \version 2022-06-30, V1.3.0, firmware for GD32E10x
9 */
10 
11 /*
12     Copyright (c) 2022, GigaDevice Semiconductor Inc.
13 
14     Redistribution and use in source and binary forms, with or without modification,
15 are permitted provided that the following conditions are met:
16 
17     1. Redistributions of source code must retain the above copyright notice, this
18        list of conditions and the following disclaimer.
19     2. Redistributions in binary form must reproduce the above copyright notice,
20        this list of conditions and the following disclaimer in the documentation
21        and/or other materials provided with the distribution.
22     3. Neither the name of the copyright holder nor the names of its contributors
23        may be used to endorse or promote products derived from this software without
24        specific prior written permission.
25 
26     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
30 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
35 OF SUCH DAMAGE.
36 */
37 
38 #include "gd32e10x_dma.h"
39 #include <stdio.h>
40 
41 #define DMA_WRONG_HANDLE        while(1){}
42 
43 /* check whether peripheral matches channels or not */
44 static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx);
45 
46 /*!
47     \brief      deinitialize DMA a channel registers
48     \param[in]  dma_periph: DMAx(x=0,1)
49       \arg        DMAx(x=0,1)
50     \param[in]  channelx: specified DMA channel is deinitialized
51                 only one parameter can be selected which is shown as below:
52       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
53     \param[out] none
54     \retval     none
55 */
dma_deinit(uint32_t dma_periph,dma_channel_enum channelx)56 void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx)
57 {
58     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
59         DMA_WRONG_HANDLE
60     }
61 
62     /* disable the DMA channel */
63     DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
64     /* reset DMA channel registers */
65     DMA_CHCTL(dma_periph, channelx) = DMA_CHCTL_RESET_VALUE;
66     DMA_CHCNT(dma_periph, channelx) = DMA_CHCNT_RESET_VALUE;
67     DMA_CHPADDR(dma_periph, channelx) = DMA_CHPADDR_RESET_VALUE;
68     DMA_CHMADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE;
69     DMA_INTC(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx);
70 }
71 
72 /*!
73     \brief      initialize the parameters of DMA struct with the default values
74     \param[in]  init_struct: the initialization data needed to initialize DMA channel
75     \param[out] none
76     \retval     none
77 */
dma_struct_para_init(dma_parameter_struct * init_struct)78 void dma_struct_para_init(dma_parameter_struct* init_struct)
79 {
80     if(NULL == init_struct){
81         DMA_WRONG_HANDLE
82     }
83 
84     /* set the DMA struct with the default values */
85     init_struct->periph_addr  = 0U;
86     init_struct->periph_width = 0U;
87     init_struct->periph_inc   = DMA_PERIPH_INCREASE_DISABLE;
88     init_struct->memory_addr  = 0U;
89     init_struct->memory_width = 0U;
90     init_struct->memory_inc   = DMA_MEMORY_INCREASE_DISABLE;
91     init_struct->number       = 0U;
92     init_struct->direction    = DMA_PERIPHERAL_TO_MEMORY;
93     init_struct->priority     = DMA_PRIORITY_LOW;
94 }
95 
96 /*!
97     \brief      initialize DMA channel
98     \param[in]  dma_periph: DMAx(x=0,1)
99       \arg        DMAx(x=0,1)
100     \param[in]  channelx: specified DMA channel is initialized
101                 only one parameter can be selected which is shown as below:
102       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
103     \param[in]  init_struct: the data needed to initialize DMA channel
104                   periph_addr: peripheral base address
105                   periph_width: DMA_PERIPHERAL_WIDTH_8BIT, DMA_PERIPHERAL_WIDTH_16BIT, DMA_PERIPHERAL_WIDTH_32BIT
106                   periph_inc: DMA_PERIPH_INCREASE_ENABLE, DMA_PERIPH_INCREASE_DISABLE
107                   memory_addr: memory base address
108                   memory_width: DMA_MEMORY_WIDTH_8BIT, DMA_MEMORY_WIDTH_16BIT, DMA_MEMORY_WIDTH_32BIT
109                   memory_inc: DMA_MEMORY_INCREASE_ENABLE, DMA_MEMORY_INCREASE_DISABLE
110                   direction: DMA_PERIPHERAL_TO_MEMORY, DMA_MEMORY_TO_PERIPHERAL
111                   number: the number of remaining data to be transferred by the DMA
112                   priority: DMA_PRIORITY_LOW, DMA_PRIORITY_MEDIUM, DMA_PRIORITY_HIGH, DMA_PRIORITY_ULTRA_HIGH
113     \param[out] none
114     \retval     none
115 */
dma_init(uint32_t dma_periph,dma_channel_enum channelx,dma_parameter_struct * init_struct)116 void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct* init_struct)
117 {
118     uint32_t ctl;
119 
120     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
121         DMA_WRONG_HANDLE
122     }
123 
124     /* configure peripheral base address */
125     DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr;
126 
127     /* configure memory base address */
128     DMA_CHMADDR(dma_periph, channelx) = init_struct->memory_addr;
129 
130     /* configure the number of remaining data to be transferred */
131     DMA_CHCNT(dma_periph, channelx) = (init_struct->number & DMA_CHANNEL_CNT_MASK);
132 
133     /* configure peripheral transfer width,memory transfer width and priority */
134     ctl = DMA_CHCTL(dma_periph, channelx);
135     ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO);
136     ctl |= (init_struct->periph_width | init_struct->memory_width | init_struct->priority);
137     DMA_CHCTL(dma_periph, channelx) = ctl;
138 
139     /* configure peripheral increasing mode */
140     if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc){
141         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
142     }else{
143         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
144     }
145 
146     /* configure memory increasing mode */
147     if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc){
148         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
149     }else{
150         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
151     }
152 
153     /* configure the direction of data transfer */
154     if(DMA_PERIPHERAL_TO_MEMORY == init_struct->direction){
155         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR;
156     }else{
157         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR;
158     }
159 }
160 
161 /*!
162     \brief      enable DMA circulation mode
163     \param[in]  dma_periph: DMAx(x=0,1)
164       \arg        DMAx(x=0,1)
165     \param[in]  channelx: specified DMA channel
166                 only one parameter can be selected which is shown as below:
167       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
168     \param[out] none
169     \retval     none
170 */
dma_circulation_enable(uint32_t dma_periph,dma_channel_enum channelx)171 void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx)
172 {
173     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
174         DMA_WRONG_HANDLE
175     }
176 
177     DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN;
178 }
179 
180 /*!
181     \brief      disable DMA circulation mode
182     \param[in]  dma_periph: DMAx(x=0,1)
183       \arg        DMAx(x=0,1)
184     \param[in]  channelx: specified DMA channel
185                 only one parameter can be selected which is shown as below:
186       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
187     \param[out] none
188     \retval     none
189 */
dma_circulation_disable(uint32_t dma_periph,dma_channel_enum channelx)190 void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx)
191 {
192     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
193         DMA_WRONG_HANDLE
194     }
195 
196     DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN;
197 }
198 
199 /*!
200     \brief      enable memory to memory mode
201     \param[in]  dma_periph: DMAx(x=0,1)
202       \arg        DMAx(x=0,1)
203     \param[in]  channelx: specified DMA channel
204                 only one parameter can be selected which is shown as below:
205       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
206     \param[out] none
207     \retval     none
208 */
dma_memory_to_memory_enable(uint32_t dma_periph,dma_channel_enum channelx)209 void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx)
210 {
211     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
212         DMA_WRONG_HANDLE
213     }
214 
215     DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_M2M;
216 }
217 
218 /*!
219     \brief      disable memory to memory mode
220     \param[in]  dma_periph: DMAx(x=0,1)
221       \arg        DMAx(x=0,1)
222     \param[in]  channelx: specified DMA channel
223                 only one parameter can be selected which is shown as below:
224       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
225     \param[out] none
226     \retval     none
227 */
dma_memory_to_memory_disable(uint32_t dma_periph,dma_channel_enum channelx)228 void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx)
229 {
230     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
231         DMA_WRONG_HANDLE
232     }
233 
234     DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_M2M;
235 }
236 
237 /*!
238     \brief      enable DMA channel
239     \param[in]  dma_periph: DMAx(x=0,1)
240       \arg        DMAx(x=0,1)
241     \param[in]  channelx: specified DMA channel
242                 only one parameter can be selected which is shown as below:
243       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
244     \param[out] none
245     \retval     none
246 */
dma_channel_enable(uint32_t dma_periph,dma_channel_enum channelx)247 void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx)
248 {
249     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
250         DMA_WRONG_HANDLE
251     }
252 
253     DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CHEN;
254 }
255 
256 /*!
257     \brief      disable DMA channel
258     \param[in]  dma_periph: DMAx(x=0,1)
259       \arg        DMAx(x=0,1)
260     \param[in]  channelx: specified DMA channel
261                 only one parameter can be selected which is shown as below:
262       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
263     \param[out] none
264     \retval     none
265 */
dma_channel_disable(uint32_t dma_periph,dma_channel_enum channelx)266 void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx)
267 {
268     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
269         DMA_WRONG_HANDLE
270     }
271 
272     DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
273 }
274 
275 /*!
276     \brief      set DMA peripheral base address
277     \param[in]  dma_periph: DMAx(x=0,1)
278       \arg        DMAx(x=0,1)
279     \param[in]  channelx: specified DMA channel
280                 only one parameter can be selected which is shown as below:
281       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
282     \param[in]  address: peripheral base address
283     \param[out] none
284     \retval     none
285 */
dma_periph_address_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t address)286 void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address)
287 {
288     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
289         DMA_WRONG_HANDLE
290     }
291 
292     DMA_CHPADDR(dma_periph, channelx) = address;
293 }
294 
295 /*!
296     \brief      set DMA memory base address
297     \param[in]  dma_periph: DMAx(x=0,1)
298       \arg        DMAx(x=0,1)
299     \param[in]  channelx: specified DMA channel
300                 only one parameter can be selected which is shown as below:
301       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
302     \param[in]  address: memory base address
303     \param[out] none
304     \retval     none
305 */
dma_memory_address_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t address)306 void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address)
307 {
308     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
309         DMA_WRONG_HANDLE
310     }
311 
312     DMA_CHMADDR(dma_periph, channelx) = address;
313 }
314 
315 /*!
316     \brief      set the number of remaining data to be transferred by the DMA
317     \param[in]  dma_periph: DMAx(x=0,1)
318       \arg        DMAx(x=0,1)
319     \param[in]  channelx: specified DMA channel
320                 only one parameter can be selected which is shown as below:
321       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
322     \param[in]  number: the number of remaining data to be transferred by the DMA
323       \arg        0x0000-0xFFFF
324     \param[out] none
325     \retval     none
326 */
dma_transfer_number_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t number)327 void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number)
328 {
329     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
330         DMA_WRONG_HANDLE
331     }
332 
333     DMA_CHCNT(dma_periph, channelx) = (number & DMA_CHANNEL_CNT_MASK);
334 }
335 
336 /*!
337     \brief      get the number of remaining data to be transferred by the DMA
338     \param[in]  dma_periph: DMAx(x=0,1)
339       \arg        DMAx(x=0,1)
340     \param[in]  channelx: specified DMA channel
341                 only one parameter can be selected which is shown as below:
342       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
343     \param[out] none
344     \retval     uint32_t: the number of remaining data to be transferred by the DMA
345 */
dma_transfer_number_get(uint32_t dma_periph,dma_channel_enum channelx)346 uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx)
347 {
348     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
349         DMA_WRONG_HANDLE
350     }
351 
352     return (uint32_t)DMA_CHCNT(dma_periph, channelx);
353 }
354 
355 /*!
356     \brief      configure priority level of DMA channel
357     \param[in]  dma_periph: DMAx(x=0,1)
358       \arg        DMAx(x=0,1)
359     \param[in]  channelx: specified DMA channel
360                 only one parameter can be selected which is shown as below:
361       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
362     \param[in]  priority: priority level of this channel
363                 only one parameter can be selected which is shown as below:
364       \arg        DMA_PRIORITY_LOW: low priority
365       \arg        DMA_PRIORITY_MEDIUM: medium priority
366       \arg        DMA_PRIORITY_HIGH: high priority
367       \arg        DMA_PRIORITY_ULTRA_HIGH: ultra high priority
368     \param[out] none
369     \retval     none
370 */
dma_priority_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t priority)371 void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority)
372 {
373     uint32_t ctl;
374 
375     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
376         DMA_WRONG_HANDLE
377     }
378 
379     /* acquire DMA_CHxCTL register */
380     ctl = DMA_CHCTL(dma_periph, channelx);
381     /* assign register */
382     ctl &= ~DMA_CHXCTL_PRIO;
383     ctl |= priority;
384     DMA_CHCTL(dma_periph, channelx) = ctl;
385 }
386 
387 /*!
388     \brief      configure transfer data size of memory
389     \param[in]  dma_periph: DMAx(x=0,1)
390       \arg        DMAx(x=0,1)
391     \param[in]  channelx: specified DMA channel
392                 only one parameter can be selected which is shown as below:
393       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
394     \param[in]  mwidth: transfer data width of memory
395                 only one parameter can be selected which is shown as below:
396       \arg        DMA_MEMORY_WIDTH_8BIT: transfer data width of memory is 8-bit
397       \arg        DMA_MEMORY_WIDTH_16BIT: transfer data width of memory is 16-bit
398       \arg        DMA_MEMORY_WIDTH_32BIT: transfer data width of memory is 32-bit
399     \param[out] none
400     \retval     none
401 */
dma_memory_width_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t mwidth)402 void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth)
403 {
404     uint32_t ctl;
405 
406     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
407         DMA_WRONG_HANDLE
408     }
409 
410     /* acquire DMA_CHxCTL register */
411     ctl = DMA_CHCTL(dma_periph, channelx);
412     /* assign regiser */
413     ctl &= ~DMA_CHXCTL_MWIDTH;
414     ctl |= mwidth;
415     DMA_CHCTL(dma_periph, channelx) = ctl;
416 }
417 
418 /*!
419     \brief      configure transfer data size of peripheral
420     \param[in]  dma_periph: DMAx(x=0,1)
421       \arg        DMAx(x=0,1)
422     \param[in]  channelx: specified DMA channel
423                 only one parameter can be selected which is shown as below:
424       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
425     \param[in]  pwidth: transfer data width of peripheral
426                 only one parameter can be selected which is shown as below:
427       \arg        DMA_PERIPHERAL_WIDTH_8BIT: transfer data width of peripheral is 8-bit
428       \arg        DMA_PERIPHERAL_WIDTH_16BIT: transfer data width of peripheral is 16-bit
429       \arg        DMA_PERIPHERAL_WIDTH_32BIT: transfer data width of peripheral is 32-bit
430     \param[out] none
431     \retval     none
432 */
dma_periph_width_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t pwidth)433 void dma_periph_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth)
434 {
435     uint32_t ctl;
436 
437     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
438         DMA_WRONG_HANDLE
439     }
440 
441     /* acquire DMA_CHxCTL register */
442     ctl = DMA_CHCTL(dma_periph, channelx);
443     /* assign register */
444     ctl &= ~DMA_CHXCTL_PWIDTH;
445     ctl |= pwidth;
446     DMA_CHCTL(dma_periph, channelx) = ctl;
447 }
448 
449 /*!
450     \brief      enable next address increment algorithm of memory
451     \param[in]  dma_periph: DMAx(x=0,1)
452       \arg        DMAx(x=0,1)
453     \param[in]  channelx: specified DMA channel
454                 only one parameter can be selected which is shown as below:
455       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
456     \param[out] none
457     \retval     none
458 */
dma_memory_increase_enable(uint32_t dma_periph,dma_channel_enum channelx)459 void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx)
460 {
461     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
462         DMA_WRONG_HANDLE
463     }
464 
465     DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
466 }
467 
468 /*!
469     \brief      disable next address increment algorithm of memory
470     \param[in]  dma_periph: DMAx(x=0,1)
471       \arg        DMAx(x=0,1)
472     \param[in]  channelx: specified DMA channel
473                 only one parameter can be selected which is shown as below:
474       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
475     \param[out] none
476     \retval     none
477 */
dma_memory_increase_disable(uint32_t dma_periph,dma_channel_enum channelx)478 void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx)
479 {
480     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
481         DMA_WRONG_HANDLE
482     }
483 
484     DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
485 }
486 
487 /*!
488     \brief      enable next address increment algorithm of peripheral
489     \param[in]  dma_periph: DMAx(x=0,1)
490       \arg        DMAx(x=0,1)
491     \param[in]  channelx: specified DMA channel
492                 only one parameter can be selected which is shown as below:
493       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
494     \param[out] none
495     \retval     none
496 */
dma_periph_increase_enable(uint32_t dma_periph,dma_channel_enum channelx)497 void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx)
498 {
499     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
500         DMA_WRONG_HANDLE
501     }
502 
503     DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
504 }
505 
506 /*!
507     \brief      disable next address increment algorithm of peripheral
508     \param[in]  dma_periph: DMAx(x=0,1)
509       \arg        DMAx(x=0,1)
510     \param[in]  channelx: specified DMA channel
511                 only one parameter can be selected which is shown as below:
512       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
513     \param[out] none
514     \retval     none
515 */
dma_periph_increase_disable(uint32_t dma_periph,dma_channel_enum channelx)516 void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx)
517 {
518     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
519         DMA_WRONG_HANDLE
520     }
521 
522     DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
523 }
524 
525 /*!
526     \brief      configure the direction of data transfer on the channel
527     \param[in]  dma_periph: DMAx(x=0,1)
528       \arg        DMAx(x=0,1)
529     \param[in]  channelx: specified DMA channel
530                 only one parameter can be selected which is shown as below:
531       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
532     \param[in]  direction: specify the direction of data transfer
533                 only one parameter can be selected which is shown as below:
534       \arg        DMA_PERIPHERAL_TO_MEMORY: read from peripheral and write to memory
535       \arg        DMA_MEMORY_TO_PERIPHERAL: read from memory and write to peripheral
536     \param[out] none
537     \retval     none
538 */
dma_transfer_direction_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t direction)539 void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t direction)
540 {
541     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
542         DMA_WRONG_HANDLE
543     }
544 
545     if(DMA_PERIPHERAL_TO_MEMORY == direction){
546         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR;
547     } else {
548         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR;
549     }
550 }
551 
552 /*!
553     \brief      check DMA flag is set or not
554     \param[in]  dma_periph: DMAx(x=0,1)
555       \arg        DMAx(x=0,1)
556     \param[in]  channelx: specified DMA channel to get flag
557       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
558     \param[in]  flag: specify get which flag
559                 only one parameter can be selected which is shown as below:
560       \arg        DMA_FLAG_G: global interrupt flag of channel
561       \arg        DMA_FLAG_FTF: full transfer finish flag of channel
562       \arg        DMA_FLAG_HTF: half transfer finish flag of channel
563       \arg        DMA_FLAG_ERR: error flag of channel
564     \param[out] none
565     \retval     FlagStatus: SET or RESET
566 */
dma_flag_get(uint32_t dma_periph,dma_channel_enum channelx,uint32_t flag)567 FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
568 {
569     FlagStatus reval;
570 
571     /* check whether the flag is set or not */
572     if(RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))){
573         reval = SET;
574     }else{
575         reval = RESET;
576     }
577 
578     return reval;
579 }
580 
581 /*!
582     \brief      clear the flag of a DMA channel
583     \param[in]  dma_periph: DMAx(x=0,1)
584       \arg        DMAx(x=0,1)
585     \param[in]  channelx: specified DMA channel to clear flag
586                 only one parameter can be selected which is shown as below:
587       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
588     \param[in]  flag: specify get which flag
589                 only one parameter can be selected which is shown as below:
590       \arg        DMA_FLAG_G: global interrupt flag of channel
591       \arg        DMA_FLAG_FTF: full transfer finish flag of channel
592       \arg        DMA_FLAG_HTF: half transfer finish flag of channel
593       \arg        DMA_FLAG_ERR: error flag of channel
594     \param[out] none
595     \retval     none
596 */
dma_flag_clear(uint32_t dma_periph,dma_channel_enum channelx,uint32_t flag)597 void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
598 {
599     DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx);
600 }
601 
602 /*!
603     \brief      check DMA flag and interrupt enable bit is set or not
604     \param[in]  dma_periph: DMAx(x=0,1)
605       \arg        DMAx(x=0,1)
606     \param[in]  channelx: specified DMA channel to get flag
607                 only one parameter can be selected which is shown as below:
608       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
609     \param[in]  flag: specify get which flag
610                 only one parameter can be selected which is shown as below:
611       \arg        DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel
612       \arg        DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel
613       \arg        DMA_INT_FLAG_ERR: error interrupt flag of channel
614     \param[out] none
615     \retval     FlagStatus: SET or RESET
616 */
dma_interrupt_flag_get(uint32_t dma_periph,dma_channel_enum channelx,uint32_t flag)617 FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
618 {
619     uint32_t interrupt_enable = 0U, interrupt_flag = 0U;
620 
621     switch(flag){
622         case DMA_INT_FLAG_FTF:
623             /* check whether the full transfer finish interrupt flag is set and enabled */
624             interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
625             interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE;
626             break;
627         case DMA_INT_FLAG_HTF:
628             /* check whether the half transfer finish interrupt flag is set and enabled */
629             interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
630             interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE;
631             break;
632         case DMA_INT_FLAG_ERR:
633             /* check whether the error interrupt flag is set and enabled */
634             interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
635             interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE;
636             break;
637         default:
638             DMA_WRONG_HANDLE
639         }
640 
641     /* when the interrupt flag is set and enabled, return SET */
642     if((0U != interrupt_flag) && (0U != interrupt_enable)){
643         return SET;
644     }else{
645         return RESET;
646     }
647 }
648 
649 /*!
650     \brief      clear the interrupt flag of a DMA channel
651     \param[in]  dma_periph: DMAx(x=0,1)
652       \arg        DMAx(x=0,1)
653     \param[in]  channelx: specified DMA channel
654                 only one parameter can be selected which is shown as below:
655       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
656     \param[in]  flag: specify get which flag
657                 only one parameter can be selected which is shown as below:
658       \arg        DMA_INT_FLAG_G: global interrupt flag of channel
659       \arg        DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel
660       \arg        DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel
661       \arg        DMA_INT_FLAG_ERR: error interrupt flag of channel
662     \param[out] none
663     \retval     none
664 */
dma_interrupt_flag_clear(uint32_t dma_periph,dma_channel_enum channelx,uint32_t flag)665 void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
666 {
667     DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx);
668 }
669 
670 /*!
671     \brief      enable DMA interrupt
672     \param[in]  dma_periph: DMAx(x=0,1)
673       \arg        DMAx(x=0,1)
674     \param[in]  channelx: specified DMA channel
675                 only one parameter can be selected which is shown as below:
676       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
677     \param[in]  source: specify which interrupt to enable
678                 one or more parameters can be selected which are shown as below
679       \arg        DMA_INT_FTF: channel full transfer finish interrupt
680       \arg        DMA_INT_HTF: channel half transfer finish interrupt
681       \arg        DMA_INT_ERR: channel error interrupt
682     \param[out] none
683     \retval     none
684 */
dma_interrupt_enable(uint32_t dma_periph,dma_channel_enum channelx,uint32_t source)685 void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
686 {
687     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
688         DMA_WRONG_HANDLE
689     }
690 
691     DMA_CHCTL(dma_periph, channelx) |= source;
692 }
693 
694 /*!
695     \brief      disable DMA interrupt
696     \param[in]  dma_periph: DMAx(x=0,1)
697       \arg        DMAx(x=0,1)
698     \param[in]  channelx: specified DMA channel
699                 only one parameter can be selected which is shown as below:
700       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
701     \param[in]  source: specify which interrupt to disable
702                 one or more parameters can be selected which are shown as below
703       \arg        DMA_INT_FTF: channel full transfer finish interrupt
704       \arg        DMA_INT_HTF: channel half transfer finish interrupt
705       \arg        DMA_INT_ERR: channel error interrupt
706     \param[out] none
707     \retval     none
708 */
dma_interrupt_disable(uint32_t dma_periph,dma_channel_enum channelx,uint32_t source)709 void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
710 {
711     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
712         DMA_WRONG_HANDLE
713     }
714 
715     DMA_CHCTL(dma_periph, channelx) &= ~source;
716 }
717 
718 /*!
719     \brief      check whether peripheral matches channels or not
720     \param[in]  dma_periph: DMAx(x=0,1)
721       \arg        DMAx(x=0,1)
722     \param[in]  channelx: specified DMA channel
723                 only one parameter can be selected which is shown as below:
724       \arg        DMA_CHx(x=0..6)
725     \param[out] none
726     \retval     ErrStatus: SUCCESS or ERROR
727 */
dma_periph_and_channel_check(uint32_t dma_periph,dma_channel_enum channelx)728 static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx)
729 {
730     ErrStatus val = SUCCESS;
731 
732     if(DMA1 == dma_periph){
733         /* for DMA1, the channel is from DMA_CH0 to DMA_CH4 */
734         if(channelx > DMA_CH4){
735             val = ERROR;
736         }
737     }
738 
739     return val;
740 }
741