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