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