1 /*!
2     \file    gd32f403_dma.c
3     \brief   DMA driver
4 
5     \version 2017-02-10, V1.0.0, firmware for gd32f403
6     \version 2018-12-25, V2.0.0, firmware for gd32f403
7     \version 2020-09-30, V2.1.0, firmware for GD32F403
8 */
9 
10 /*
11     Copyright (c) 2020, 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 "gd32f403_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(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
120         DMA_WRONG_HANDLE
121     }
122 
123     /* configure peripheral base address */
124     DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr;
125 
126     /* configure memory base address */
127     DMA_CHMADDR(dma_periph, channelx) = init_struct->memory_addr;
128 
129     /* configure the number of remaining data to be transferred */
130     DMA_CHCNT(dma_periph, channelx) = (init_struct->number & DMA_CHANNEL_CNT_MASK);
131 
132     /* configure peripheral transfer width,memory transfer width and priority */
133     ctl = DMA_CHCTL(dma_periph, channelx);
134     ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO);
135     ctl |= (init_struct->periph_width | init_struct->memory_width | init_struct->priority);
136     DMA_CHCTL(dma_periph, channelx) = ctl;
137 
138     /* configure peripheral increasing mode */
139     if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc){
140         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
141     }else{
142         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
143     }
144 
145     /* configure memory increasing mode */
146     if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc){
147         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
148     }else{
149         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
150     }
151 
152     /* configure the direction of data transfer */
153     if(DMA_PERIPHERAL_TO_MEMORY == init_struct->direction){
154         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR;
155     }else{
156         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR;
157     }
158 }
159 
160 /*!
161     \brief      enable DMA circulation mode
162     \param[in]  dma_periph: DMAx(x=0,1)
163       \arg        DMAx(x=0,1)
164     \param[in]  channelx: specify which DMA channel
165                 only one parameter can be selected which is shown as below:
166       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
167     \param[out] none
168     \retval     none
169 */
dma_circulation_enable(uint32_t dma_periph,dma_channel_enum channelx)170 void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx)
171 {
172     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
173         DMA_WRONG_HANDLE
174     }
175 
176     DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN;
177 }
178 
179 /*!
180     \brief      disable DMA circulation mode
181     \param[in]  dma_periph: DMAx(x=0,1)
182       \arg        DMAx(x=0,1)
183     \param[in]  channelx: specify which DMA channel
184                 only one parameter can be selected which is shown as below:
185       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
186     \param[out] none
187     \retval     none
188 */
dma_circulation_disable(uint32_t dma_periph,dma_channel_enum channelx)189 void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx)
190 {
191     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
192         DMA_WRONG_HANDLE
193     }
194 
195     DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN;
196 }
197 
198 /*!
199     \brief      enable memory to memory mode
200     \param[in]  dma_periph: DMAx(x=0,1)
201       \arg        DMAx(x=0,1)
202     \param[in]  channelx: specify which DMA channel
203                 only one parameter can be selected which is shown as below:
204       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
205     \param[out] none
206     \retval     none
207 */
dma_memory_to_memory_enable(uint32_t dma_periph,dma_channel_enum channelx)208 void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx)
209 {
210     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
211         DMA_WRONG_HANDLE
212     }
213 
214     DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_M2M;
215 }
216 
217 /*!
218     \brief      disable memory to memory mode
219     \param[in]  dma_periph: DMAx(x=0,1)
220       \arg        DMAx(x=0,1)
221     \param[in]  channelx: specify which DMA channel
222                 only one parameter can be selected which is shown as below:
223       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
224     \param[out] none
225     \retval     none
226 */
dma_memory_to_memory_disable(uint32_t dma_periph,dma_channel_enum channelx)227 void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx)
228 {
229     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
230         DMA_WRONG_HANDLE
231     }
232 
233     DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_M2M;
234 }
235 
236 /*!
237     \brief      enable DMA channel
238     \param[in]  dma_periph: DMAx(x=0,1)
239       \arg        DMAx(x=0,1)
240     \param[in]  channelx: specify which DMA channel
241                 only one parameter can be selected which is shown as below:
242       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
243     \param[out] none
244     \retval     none
245 */
dma_channel_enable(uint32_t dma_periph,dma_channel_enum channelx)246 void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx)
247 {
248     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
249         DMA_WRONG_HANDLE
250     }
251 
252     DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CHEN;
253 }
254 
255 /*!
256     \brief      disable DMA channel
257     \param[in]  dma_periph: DMAx(x=0,1)
258       \arg        DMAx(x=0,1)
259     \param[in]  channelx: specify which DMA channel
260                 only one parameter can be selected which is shown as below:
261       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
262     \param[out] none
263     \retval     none
264 */
dma_channel_disable(uint32_t dma_periph,dma_channel_enum channelx)265 void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx)
266 {
267     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
268         DMA_WRONG_HANDLE
269     }
270 
271     DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
272 }
273 
274 /*!
275     \brief      set DMA peripheral base address
276     \param[in]  dma_periph: DMAx(x=0,1)
277       \arg        DMAx(x=0,1)
278     \param[in]  channelx: specify which DMA channel to set peripheral base address
279       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
280     \param[in]  address: peripheral base address
281     \param[out] none
282     \retval     none
283 */
dma_periph_address_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t address)284 void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address)
285 {
286     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
287         DMA_WRONG_HANDLE
288     }
289 
290     DMA_CHPADDR(dma_periph, channelx) = address;
291 }
292 
293 /*!
294     \brief      set DMA memory base address
295     \param[in]  dma_periph: DMAx(x=0,1)
296       \arg        DMAx(x=0,1)
297     \param[in]  channelx: specify which DMA channel to set memory base address
298                 only one parameter can be selected which is shown as below:
299       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
300     \param[in]  address: memory base address
301     \param[out] none
302     \retval     none
303 */
dma_memory_address_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t address)304 void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address)
305 {
306     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
307         DMA_WRONG_HANDLE
308     }
309 
310     DMA_CHMADDR(dma_periph, channelx) = address;
311 }
312 
313 /*!
314     \brief      set the number of remaining data to be transferred by the DMA
315     \param[in]  dma_periph: DMAx(x=0,1)
316       \arg        DMAx(x=0,1)
317     \param[in]  channelx: specify which DMA channel to set number
318                 only one parameter can be selected which is shown as below:
319       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
320     \param[in]  number: the number of remaining data to be transferred by the DMA
321       \arg        0x0000-0xFFFF
322     \param[out] none
323     \retval     none
324 */
dma_transfer_number_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t number)325 void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number)
326 {
327     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
328         DMA_WRONG_HANDLE
329     }
330 
331     DMA_CHCNT(dma_periph, channelx) = (number & DMA_CHANNEL_CNT_MASK);
332 }
333 
334 /*!
335     \brief      get the number of remaining data to be transferred by the DMA
336     \param[in]  dma_periph: DMAx(x=0,1)
337       \arg        DMAx(x=0,1)
338     \param[in]  channelx: specify which DMA channel to set number
339                 only one parameter can be selected which is shown as below:
340       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
341     \param[out] none
342     \retval     uint32_t: the number of remaining data to be transferred by the DMA
343 */
dma_transfer_number_get(uint32_t dma_periph,dma_channel_enum channelx)344 uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx)
345 {
346     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
347         DMA_WRONG_HANDLE
348     }
349 
350     return (uint32_t)DMA_CHCNT(dma_periph, channelx);
351 }
352 
353 /*!
354     \brief      configure priority level of DMA channel
355     \param[in]  dma_periph: DMAx(x=0,1)
356       \arg        DMAx(x=0,1)
357     \param[in]  channelx: specify which DMA channel
358                 only one parameter can be selected which is shown as below:
359       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
360     \param[in]  priority: priority level of this channel
361                 only one parameter can be selected which is shown as below:
362       \arg        DMA_PRIORITY_LOW: low priority
363       \arg        DMA_PRIORITY_MEDIUM: medium priority
364       \arg        DMA_PRIORITY_HIGH: high priority
365       \arg        DMA_PRIORITY_ULTRA_HIGH: ultra high priority
366     \param[out] none
367     \retval     none
368 */
dma_priority_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t priority)369 void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority)
370 {
371     uint32_t ctl;
372 
373     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
374         DMA_WRONG_HANDLE
375     }
376 
377     /* acquire DMA_CHxCTL register */
378     ctl = DMA_CHCTL(dma_periph, channelx);
379     /* assign regiser */
380     ctl &= ~DMA_CHXCTL_PRIO;
381     ctl |= priority;
382     DMA_CHCTL(dma_periph, channelx) = ctl;
383 }
384 
385 /*!
386     \brief      configure transfer data size of memory
387     \param[in]  dma_periph: DMAx(x=0,1)
388       \arg        DMAx(x=0,1)
389     \param[in]  channelx: specify which DMA channel
390                 only one parameter can be selected which is shown as below:
391       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
392     \param[in]  mwidth: transfer data width of memory
393                 only one parameter can be selected which is shown as below:
394       \arg        DMA_MEMORY_WIDTH_8BIT: transfer data width of memory is 8-bit
395       \arg        DMA_MEMORY_WIDTH_16BIT: transfer data width of memory is 16-bit
396       \arg        DMA_MEMORY_WIDTH_32BIT: transfer data width of memory is 32-bit
397     \param[out] none
398     \retval     none
399 */
dma_memory_width_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t mwidth)400 void dma_memory_width_config (uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth)
401 {
402     uint32_t ctl;
403 
404     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
405         DMA_WRONG_HANDLE
406     }
407 
408     /* acquire DMA_CHxCTL register */
409     ctl = DMA_CHCTL(dma_periph, channelx);
410     /* assign regiser */
411     ctl &= ~DMA_CHXCTL_MWIDTH;
412     ctl |= mwidth;
413     DMA_CHCTL(dma_periph, channelx) = ctl;
414 }
415 
416 /*!
417     \brief      configure transfer data size of peripheral
418     \param[in]  dma_periph: DMAx(x=0,1)
419       \arg        DMAx(x=0,1)
420     \param[in]  channelx: specify which DMA channel
421                 only one parameter can be selected which is shown as below:
422       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
423     \param[in]  pwidth: transfer data width of peripheral
424                 only one parameter can be selected which is shown as below:
425       \arg        DMA_PERIPHERAL_WIDTH_8BIT: transfer data width of peripheral is 8-bit
426       \arg        DMA_PERIPHERAL_WIDTH_16BIT: transfer data width of peripheral is 16-bit
427       \arg        DMA_PERIPHERAL_WIDTH_32BIT: transfer data width of peripheral is 32-bit
428     \param[out] none
429     \retval     none
430 */
dma_periph_width_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t pwidth)431 void dma_periph_width_config (uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth)
432 {
433     uint32_t ctl;
434 
435     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
436         DMA_WRONG_HANDLE
437     }
438 
439     /* acquire DMA_CHxCTL register */
440     ctl = DMA_CHCTL(dma_periph, channelx);
441     /* assign regiser */
442     ctl &= ~DMA_CHXCTL_PWIDTH;
443     ctl |= pwidth;
444     DMA_CHCTL(dma_periph, channelx) = ctl;
445 }
446 
447 /*!
448     \brief      enable next address increasement algorithm of memory
449     \param[in]  dma_periph: DMAx(x=0,1)
450       \arg        DMAx(x=0,1)
451     \param[in]  channelx: specify which DMA channel
452                 only one parameter can be selected which is shown as below:
453       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
454     \param[out] none
455     \retval     none
456 */
dma_memory_increase_enable(uint32_t dma_periph,dma_channel_enum channelx)457 void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx)
458 {
459     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
460         DMA_WRONG_HANDLE
461     }
462 
463     DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
464 }
465 
466 /*!
467     \brief      disable next address increasement algorithm of memory
468     \param[in]  dma_periph: DMAx(x=0,1)
469       \arg        DMAx(x=0,1)
470     \param[in]  channelx: specify which DMA channel
471                 only one parameter can be selected which is shown as below:
472       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
473     \param[out] none
474     \retval     none
475 */
dma_memory_increase_disable(uint32_t dma_periph,dma_channel_enum channelx)476 void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx)
477 {
478     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
479         DMA_WRONG_HANDLE
480     }
481 
482     DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
483 }
484 
485 /*!
486     \brief      enable next address increasement algorithm of peripheral
487     \param[in]  dma_periph: DMAx(x=0,1)
488       \arg        DMAx(x=0,1)
489     \param[in]  channelx: specify which DMA channel
490                 only one parameter can be selected which is shown as below:
491       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
492     \param[out] none
493     \retval     none
494 */
dma_periph_increase_enable(uint32_t dma_periph,dma_channel_enum channelx)495 void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx)
496 {
497     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
498         DMA_WRONG_HANDLE
499     }
500 
501     DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
502 }
503 
504 /*!
505     \brief      disable next address increasement algorithm of peripheral
506     \param[in]  dma_periph: DMAx(x=0,1)
507       \arg        DMAx(x=0,1)
508     \param[in]  channelx: specify which DMA channel
509                 only one parameter can be selected which is shown as below:
510       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
511     \param[out] none
512     \retval     none
513 */
dma_periph_increase_disable(uint32_t dma_periph,dma_channel_enum channelx)514 void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx)
515 {
516     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
517         DMA_WRONG_HANDLE
518     }
519 
520     DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
521 }
522 
523 /*!
524     \brief      configure the direction of data transfer on the channel
525     \param[in]  dma_periph: DMAx(x=0,1)
526       \arg        DMAx(x=0,1)
527     \param[in]  channelx: specify which DMA channel
528                 only one parameter can be selected which is shown as below:
529       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
530     \param[in]  direction: specify the direction of data transfer
531                 only one parameter can be selected which is shown as below:
532       \arg        DMA_PERIPHERAL_TO_MEMORY: read from peripheral and write to memory
533       \arg        DMA_MEMORY_TO_PERIPHERAL: read from memory and write to peripheral
534     \param[out] none
535     \retval     none
536 */
dma_transfer_direction_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t direction)537 void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t direction)
538 {
539     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
540         DMA_WRONG_HANDLE
541     }
542 
543     if(DMA_PERIPHERAL_TO_MEMORY == direction){
544         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR;
545     } else {
546         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR;
547     }
548 }
549 
550 /*!
551     \brief      check DMA flag is set or not
552     \param[in]  dma_periph: DMAx(x=0,1)
553       \arg        DMAx(x=0,1)
554     \param[in]  channelx: specify which DMA channel to get flag
555                 only one parameter can be selected which is shown as below:
556       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
557     \param[in]  flag: specify get which flag
558                 only one parameter can be selected which is shown as below:
559       \arg        DMA_FLAG_G: global interrupt flag of channel
560       \arg        DMA_FLAG_FTF: full transfer finish flag of channel
561       \arg        DMA_FLAG_HTF: half transfer finish flag of channel
562       \arg        DMA_FLAG_ERR: error flag of channel
563     \param[out] none
564     \retval     FlagStatus: SET or RESET
565 */
dma_flag_get(uint32_t dma_periph,dma_channel_enum channelx,uint32_t flag)566 FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
567 {
568     FlagStatus reval;
569 
570     /* check whether the flag is set or not */
571     if(RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))){
572         reval = SET;
573     }else{
574         reval = RESET;
575     }
576 
577     return reval;
578 }
579 
580 /*!
581     \brief      clear DMA a channel flag
582     \param[in]  dma_periph: DMAx(x=0,1)
583       \arg        DMAx(x=0,1)
584     \param[in]  channelx: specify which DMA channel to clear flag
585                 only one parameter can be selected which is shown as below:
586       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
587     \param[in]  flag: specify get which flag
588                 only one parameter can be selected which is shown as below:
589       \arg        DMA_FLAG_G: global interrupt flag of channel
590       \arg        DMA_FLAG_FTF: full transfer finish flag of channel
591       \arg        DMA_FLAG_HTF: half transfer finish flag of channel
592       \arg        DMA_FLAG_ERR: error flag of channel
593     \param[out] none
594     \retval     none
595 */
dma_flag_clear(uint32_t dma_periph,dma_channel_enum channelx,uint32_t flag)596 void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
597 {
598     DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx);
599 }
600 
601 /*!
602     \brief      check DMA flag and interrupt enable bit is set or not
603     \param[in]  dma_periph: DMAx(x=0,1)
604       \arg        DMAx(x=0,1)
605     \param[in]  channelx: specify which DMA channel to get flag
606                 only one parameter can be selected which is shown as below:
607       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
608     \param[in]  flag: specify get which flag
609                 only one parameter can be selected which is shown as below:
610       \arg        DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel
611       \arg        DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel
612       \arg        DMA_INT_FLAG_ERR: error interrupt flag of channel
613     \param[out] none
614     \retval     FlagStatus: SET or RESET
615 */
dma_interrupt_flag_get(uint32_t dma_periph,dma_channel_enum channelx,uint32_t flag)616 FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
617 {
618     uint32_t interrupt_enable = 0U, interrupt_flag = 0U;
619 
620     switch(flag){
621         case DMA_INT_FLAG_FTF:
622             interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
623             interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE;
624             break;
625         case DMA_INT_FLAG_HTF:
626             interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
627             interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE;
628             break;
629         case DMA_INT_FLAG_ERR:
630             interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
631             interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE;
632             break;
633         default:
634             DMA_WRONG_HANDLE
635         }
636 
637     /* when the interrupt flag is set and enabled, return SET */
638     if((0U != interrupt_flag) && (0U != interrupt_enable)){
639         return SET;
640     }else{
641         return RESET;
642     }
643 }
644 
645 /*!
646     \brief      clear DMA a channel flag
647     \param[in]  dma_periph: DMAx(x=0,1)
648       \arg        DMAx(x=0,1)
649     \param[in]  channelx: specify which DMA channel to clear flag
650                 only one parameter can be selected which is shown as below:
651       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
652     \param[in]  flag: specify get which flag
653                 only one parameter can be selected which is shown as below:
654       \arg        DMA_INT_FLAG_G: global interrupt flag of channel
655       \arg        DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel
656       \arg        DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel
657       \arg        DMA_INT_FLAG_ERR: error interrupt flag of channel
658     \param[out] none
659     \retval     none
660 */
dma_interrupt_flag_clear(uint32_t dma_periph,dma_channel_enum channelx,uint32_t flag)661 void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
662 {
663     DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx);
664 }
665 
666 /*!
667     \brief      enable DMA interrupt
668     \param[in]  dma_periph: DMAx(x=0,1)
669       \arg        DMAx(x=0,1)
670     \param[in]  channelx: specify which DMA channel
671                 only one parameter can be selected which is shown as below:
672       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
673     \param[in]  source: specify which interrupt to enbale
674                 one or more parameters can be selected which are shown as below
675       \arg        DMA_INT_FTF: channel full transfer finish interrupt
676       \arg        DMA_INT_HTF: channel half transfer finish interrupt
677       \arg        DMA_INT_ERR: channel error interrupt
678     \param[out] none
679     \retval     none
680 */
dma_interrupt_enable(uint32_t dma_periph,dma_channel_enum channelx,uint32_t source)681 void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
682 {
683     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
684         DMA_WRONG_HANDLE
685     }
686 
687     DMA_CHCTL(dma_periph, channelx) |= source;
688 }
689 
690 /*!
691     \brief      disable DMA interrupt
692     \param[in]  dma_periph: DMAx(x=0,1)
693       \arg        DMAx(x=0,1)
694     \param[in]  channelx: specify which DMA channel
695                 only one parameter can be selected which is shown as below:
696       \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
697     \param[in]  source: specify which interrupt to disbale
698                 one or more parameters can be selected which are shown as below
699       \arg        DMA_INT_FTF: channel full transfer finish interrupt
700       \arg        DMA_INT_HTF: channel half transfer finish interrupt
701       \arg        DMA_INT_ERR: channel error interrupt
702     \param[out] none
703     \retval     none
704 */
dma_interrupt_disable(uint32_t dma_periph,dma_channel_enum channelx,uint32_t source)705 void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
706 {
707     if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
708         DMA_WRONG_HANDLE
709     }
710 
711     DMA_CHCTL(dma_periph, channelx) &= ~source;
712 }
713 
714 /*!
715     \brief      check whether peripheral and channels match
716     \param[in]  dma_periph: DMAx(x=0,1)
717       \arg        DMAx(x=0,1)
718     \param[in]  channelx: specify which DMA channel
719                 only one parameter can be selected which is shown as below:
720       \arg        DMA_CHx(x=0..6)
721     \param[out] none
722     \retval     ErrStatus: SUCCESS or ERROR
723 */
dma_periph_and_channel_check(uint32_t dma_periph,dma_channel_enum channelx)724 static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx)
725 {
726     ErrStatus val = SUCCESS;
727 
728     if(DMA1 == dma_periph){
729         /* for DMA1, the channel is from DMA_CH0 to DMA_CH4 */
730         if(channelx > DMA_CH4){
731             val = ERROR;
732         }
733     }
734 
735     return val;
736 }
737