1 /*!
2     \file    gd32f4xx_dma.c
3     \brief   DMA driver
4     \version 2016-08-15, V1.0.0, firmware for GD32F4xx
5     \version 2018-12-12, V2.0.0, firmware for GD32F4xx
6     \version 2020-09-30, V2.1.0, firmware for GD32F4xx
7     \version 2022-03-09, V3.0.0, firmware for GD32F4xx
8 */
9 
10 /*
11     Copyright (c) 2022, 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 "gd32f4xx_dma.h"
38 
39 /*  DMA register bit offset */
40 #define CHXCTL_PERIEN_OFFSET            ((uint32_t)25U)
41 
42 /*!
43     \brief    deinitialize DMA a channel registers
44     \param[in]  dma_periph: DMAx(x=0,1)
45       \arg        DMAx(x=0,1)
46     \param[in]  channelx: specify which DMA channel is deinitialized
47       \arg        DMA_CHx(x=0..7)
48     \param[out] none
49     \retval     none
50 */
dma_deinit(uint32_t dma_periph,dma_channel_enum channelx)51 void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx)
52 {
53     /* disable DMA a channel */
54     DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
55     /* reset DMA channel registers */
56     DMA_CHCTL(dma_periph, channelx) = DMA_CHCTL_RESET_VALUE;
57     DMA_CHCNT(dma_periph, channelx) = DMA_CHCNT_RESET_VALUE;
58     DMA_CHPADDR(dma_periph, channelx) = DMA_CHPADDR_RESET_VALUE;
59     DMA_CHM0ADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE;
60     DMA_CHM1ADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE;
61     DMA_CHFCTL(dma_periph, channelx) = DMA_CHFCTL_RESET_VALUE;
62     if(channelx < DMA_CH4) {
63         DMA_INTC0(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx);
64     } else {
65         channelx -= (dma_channel_enum)4;
66         DMA_INTC1(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx);
67     }
68 }
69 
70 /*!
71     \brief    initialize the DMA single data mode parameters 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_single_data_para_struct_init(dma_single_data_parameter_struct * init_struct)76 void dma_single_data_para_struct_init(dma_single_data_parameter_struct *init_struct)
77 {
78     /* set the DMA struct with the default values */
79     init_struct->periph_addr         = 0U;
80     init_struct->periph_inc          = DMA_PERIPH_INCREASE_DISABLE;
81     init_struct->memory0_addr        = 0U;
82     init_struct->memory_inc          = DMA_MEMORY_INCREASE_DISABLE;
83     init_struct->periph_memory_width = 0U;
84     init_struct->circular_mode       = DMA_CIRCULAR_MODE_DISABLE;
85     init_struct->direction           = DMA_PERIPH_TO_MEMORY;
86     init_struct->number              = 0U;
87     init_struct->priority            = DMA_PRIORITY_LOW;
88 }
89 
90 /*!
91     \brief    initialize the DMA multi data mode parameters struct with the default values
92     \param[in]  init_struct: the initialization data needed to initialize DMA channel
93     \param[out] none
94     \retval     none
95 */
dma_multi_data_para_struct_init(dma_multi_data_parameter_struct * init_struct)96 void dma_multi_data_para_struct_init(dma_multi_data_parameter_struct *init_struct)
97 {
98     /* set the DMA struct with the default values */
99     init_struct->periph_addr         = 0U;
100     init_struct->periph_width        = 0U;
101     init_struct->periph_inc          = DMA_PERIPH_INCREASE_DISABLE;
102     init_struct->memory0_addr        = 0U;
103     init_struct->memory_width        = 0U;
104     init_struct->memory_inc          = DMA_MEMORY_INCREASE_DISABLE;
105     init_struct->memory_burst_width  = 0U;
106     init_struct->periph_burst_width  = 0U;
107     init_struct->circular_mode       = DMA_CIRCULAR_MODE_DISABLE;
108     init_struct->direction           = DMA_PERIPH_TO_MEMORY;
109     init_struct->number              = 0U;
110     init_struct->priority            = DMA_PRIORITY_LOW;
111 }
112 
113 /*!
114     \brief    initialize DMA single data mode
115     \param[in]  dma_periph: DMAx(x=0,1)
116       \arg        DMAx(x=0,1)
117     \param[in]  channelx: specify which DMA channel is initialized
118       \arg        DMA_CHx(x=0..7)
119     \param[in]  init_struct: the data needed to initialize DMA single data mode
120                   periph_addr: peripheral base address
121                   periph_inc: DMA_PERIPH_INCREASE_ENABLE,DMA_PERIPH_INCREASE_DISABLE,DMA_PERIPH_INCREASE_FIX
122                   memory0_addr: memory base address
123                   memory_inc: DMA_MEMORY_INCREASE_ENABLE,DMA_MEMORY_INCREASE_DISABLE
124                   periph_memory_width: DMA_PERIPH_WIDTH_8BIT,DMA_PERIPH_WIDTH_16BIT,DMA_PERIPH_WIDTH_32BIT
125                   circular_mode: DMA_CIRCULAR_MODE_ENABLE,DMA_CIRCULAR_MODE_DISABLE
126                   direction: DMA_PERIPH_TO_MEMORY,DMA_MEMORY_TO_PERIPH,DMA_MEMORY_TO_MEMORY
127                   number: the number of remaining data to be transferred by the DMA
128                   priority: DMA_PRIORITY_LOW,DMA_PRIORITY_MEDIUM,DMA_PRIORITY_HIGH,DMA_PRIORITY_ULTRA_HIGH
129     \param[out] none
130     \retval     none
131 */
dma_single_data_mode_init(uint32_t dma_periph,dma_channel_enum channelx,dma_single_data_parameter_struct * init_struct)132 void dma_single_data_mode_init(uint32_t dma_periph, dma_channel_enum channelx, dma_single_data_parameter_struct *init_struct)
133 {
134     uint32_t ctl;
135 
136     /* select single data mode */
137     DMA_CHFCTL(dma_periph, channelx) &= ~DMA_CHXFCTL_MDMEN;
138 
139     /* configure peripheral base address */
140     DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr;
141 
142     /* configure memory base address */
143     DMA_CHM0ADDR(dma_periph, channelx) = init_struct->memory0_addr;
144 
145     /* configure the number of remaining data to be transferred */
146     DMA_CHCNT(dma_periph, channelx) = init_struct->number;
147 
148     /* configure peripheral and memory transfer width,channel priotity,transfer mode */
149     ctl = DMA_CHCTL(dma_periph, channelx);
150     ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO | DMA_CHXCTL_TM);
151     ctl |= (init_struct->periph_memory_width | (init_struct->periph_memory_width << 2) | init_struct->priority | init_struct->direction);
152     DMA_CHCTL(dma_periph, channelx) = ctl;
153 
154     /* configure peripheral increasing mode */
155     if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc) {
156         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
157     } else if(DMA_PERIPH_INCREASE_DISABLE == init_struct->periph_inc) {
158         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
159     } else {
160         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PAIF;
161     }
162 
163     /* configure memory increasing mode */
164     if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc) {
165         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
166     } else {
167         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
168     }
169 
170     /* configure DMA circular mode */
171     if(DMA_CIRCULAR_MODE_ENABLE == init_struct->circular_mode) {
172         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN;
173     } else {
174         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN;
175     }
176 }
177 
178 /*!
179     \brief    initialize DMA multi data mode
180     \param[in]  dma_periph: DMAx(x=0,1)
181       \arg        DMAx(x=0,1)
182     \param[in]  channelx: specify which DMA channel is initialized
183       \arg        DMA_CHx(x=0..7)
184     \param[in]  dma_multi_data_parameter_struct: the data needed to initialize DMA multi data mode
185                   periph_addr: peripheral base address
186                   periph_width: DMA_PERIPH_WIDTH_8BIT,DMA_PERIPH_WIDTH_16BIT,DMA_PERIPH_WIDTH_32BIT
187                   periph_inc: DMA_PERIPH_INCREASE_ENABLE,DMA_PERIPH_INCREASE_DISABLE,DMA_PERIPH_INCREASE_FIX
188                   memory0_addr: memory0 base address
189                   memory_width: DMA_MEMORY_WIDTH_8BIT,DMA_MEMORY_WIDTH_16BIT,DMA_MEMORY_WIDTH_32BIT
190                   memory_inc: DMA_MEMORY_INCREASE_ENABLE,DMA_MEMORY_INCREASE_DISABLE
191                   memory_burst_width: DMA_MEMORY_BURST_SINGLE,DMA_MEMORY_BURST_4_BEAT,DMA_MEMORY_BURST_8_BEAT,DMA_MEMORY_BURST_16_BEAT
192                   periph_burst_width: DMA_PERIPH_BURST_SINGLE,DMA_PERIPH_BURST_4_BEAT,DMA_PERIPH_BURST_8_BEAT,DMA_PERIPH_BURST_16_BEAT
193                   critical_value: DMA_FIFO_1_WORD,DMA_FIFO_2_WORD,DMA_FIFO_3_WORD,DMA_FIFO_4_WORD
194                   circular_mode: DMA_CIRCULAR_MODE_ENABLE,DMA_CIRCULAR_MODE_DISABLE
195                   direction: DMA_PERIPH_TO_MEMORY,DMA_MEMORY_TO_PERIPH,DMA_MEMORY_TO_MEMORY
196                   number: the number of remaining data to be transferred by the DMA
197                   priority: DMA_PRIORITY_LOW,DMA_PRIORITY_MEDIUM,DMA_PRIORITY_HIGH,DMA_PRIORITY_ULTRA_HIGH
198     \param[out] none
199     \retval     none
200 */
dma_multi_data_mode_init(uint32_t dma_periph,dma_channel_enum channelx,dma_multi_data_parameter_struct * init_struct)201 void dma_multi_data_mode_init(uint32_t dma_periph, dma_channel_enum channelx, dma_multi_data_parameter_struct *init_struct)
202 {
203     uint32_t ctl;
204 
205     /* select multi data mode and configure FIFO critical value */
206     DMA_CHFCTL(dma_periph, channelx) |= (DMA_CHXFCTL_MDMEN | init_struct->critical_value);
207 
208     /* configure peripheral base address */
209     DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr;
210 
211     /* configure memory base address */
212     DMA_CHM0ADDR(dma_periph, channelx) = init_struct->memory0_addr;
213 
214     /* configure the number of remaining data to be transferred */
215     DMA_CHCNT(dma_periph, channelx) = init_struct->number;
216 
217     /* configure peripheral and memory transfer width,channel priotity,transfer mode,peripheral and memory burst transfer width */
218     ctl = DMA_CHCTL(dma_periph, channelx);
219     ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO | DMA_CHXCTL_TM | DMA_CHXCTL_PBURST | DMA_CHXCTL_MBURST);
220     ctl |= (init_struct->periph_width | (init_struct->memory_width) | init_struct->priority | init_struct->direction | init_struct->memory_burst_width |
221             init_struct->periph_burst_width);
222     DMA_CHCTL(dma_periph, channelx) = ctl;
223 
224     /* configure peripheral increasing mode */
225     if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc) {
226         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
227     } else if(DMA_PERIPH_INCREASE_DISABLE == init_struct->periph_inc) {
228         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
229     } else {
230         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PAIF;
231     }
232 
233     /* configure memory increasing mode */
234     if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc) {
235         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
236     } else {
237         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
238     }
239 
240     /* configure DMA circular mode */
241     if(DMA_CIRCULAR_MODE_ENABLE == init_struct->circular_mode) {
242         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN;
243     } else {
244         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN;
245     }
246 }
247 
248 /*!
249     \brief    set DMA peripheral base address
250     \param[in]  dma_periph: DMAx(x=0,1)
251       \arg        DMAx(x=0,1)
252     \param[in]  channelx: specify which DMA channel to set peripheral base address
253       \arg        DMA_CHx(x=0..7)
254     \param[in]  address: peripheral base address
255     \param[out] none
256     \retval     none
257 */
dma_periph_address_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t address)258 void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address)
259 {
260     DMA_CHPADDR(dma_periph, channelx) = address;
261 }
262 
263 /*!
264     \brief    set DMA Memory0 base address
265     \param[in]  dma_periph: DMAx(x=0,1)
266       \arg        DMAx(x=0,1)
267     \param[in]  channelx: specify which DMA channel to set Memory base address
268       \arg        DMA_CHx(x=0..7)
269     \param[in]  memory_flag: DMA_MEMORY_x(x=0,1)
270     \param[in]  address: Memory base address
271     \param[out] none
272     \retval     none
273 */
dma_memory_address_config(uint32_t dma_periph,dma_channel_enum channelx,uint8_t memory_flag,uint32_t address)274 void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t memory_flag, uint32_t address)
275 {
276     if(memory_flag) {
277         DMA_CHM1ADDR(dma_periph, channelx) = address;
278     } else {
279         DMA_CHM0ADDR(dma_periph, channelx) = address;
280     }
281 }
282 
283 /*!
284     \brief    set the number of remaining data to be transferred by the DMA
285     \param[in]  dma_periph: DMAx(x=0,1)
286       \arg        DMAx(x=0,1)
287     \param[in]  channelx: specify which DMA channel to set number
288       \arg        DMA_CHx(x=0..7)
289     \param[in]  number: the number of remaining data to be transferred by the DMA
290     \param[out] none
291     \retval     none
292 */
dma_transfer_number_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t number)293 void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number)
294 {
295     DMA_CHCNT(dma_periph, channelx) = number;
296 }
297 
298 /*!
299     \brief    get the number of remaining data to be transferred by the DMA
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 number
303       \arg        DMA_CHx(x=0..7)
304     \param[out] none
305     \retval     uint32_t: the number of remaining data to be transferred by the DMA
306 */
dma_transfer_number_get(uint32_t dma_periph,dma_channel_enum channelx)307 uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx)
308 {
309     return (uint32_t)DMA_CHCNT(dma_periph, channelx);
310 }
311 
312 /*!
313     \brief    configure priority level of DMA channel
314     \param[in]  dma_periph: DMAx(x=0,1)
315       \arg        DMAx(x=0,1)
316     \param[in]  channelx: specify which DMA channel
317       \arg        DMA_CHx(x=0..7)
318     \param[in]  priority: priority Level of this channel
319                 only one parameter can be selected which is shown as below:
320       \arg        DMA_PRIORITY_LOW: low priority
321       \arg        DMA_PRIORITY_MEDIUM: medium priority
322       \arg        DMA_PRIORITY_HIGH: high priority
323       \arg        DMA_PRIORITY_ULTRA_HIGH: ultra high priority
324     \param[out] none
325     \retval     none
326 */
dma_priority_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t priority)327 void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority)
328 {
329     uint32_t ctl;
330     /* acquire DMA_CHxCTL register */
331     ctl = DMA_CHCTL(dma_periph, channelx);
332     /* assign regiser */
333     ctl &= ~DMA_CHXCTL_PRIO;
334     ctl |= priority;
335     DMA_CHCTL(dma_periph, channelx) = ctl;
336 }
337 
338 /*!
339     \brief    configure transfer burst beats of memory
340     \param[in]  dma_periph: DMAx(x=0,1)
341       \arg        DMAx(x=0,1)
342     \param[in]  channelx: specify which DMA channel
343       \arg        DMA_CHx(x=0..7)
344     \param[in]  mbeat: transfer burst beats
345       \arg        DMA_MEMORY_BURST_SINGLE: memory transfer single burst
346       \arg        DMA_MEMORY_BURST_4_BEAT: memory transfer 4-beat burst
347       \arg        DMA_MEMORY_BURST_8_BEAT: memory transfer 8-beat burst
348       \arg        DMA_MEMORY_BURST_16_BEAT: memory transfer 16-beat burst
349     \param[out] none
350     \retval     none
351 */
dma_memory_burst_beats_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t mbeat)352 void dma_memory_burst_beats_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mbeat)
353 {
354     uint32_t ctl;
355     /* acquire DMA_CHxCTL register */
356     ctl = DMA_CHCTL(dma_periph, channelx);
357     /* assign regiser */
358     ctl &= ~DMA_CHXCTL_MBURST;
359     ctl |= mbeat;
360     DMA_CHCTL(dma_periph, channelx) = ctl;
361 }
362 
363 /*!
364     \brief    configure transfer burst beats of peripheral
365     \param[in]  dma_periph: DMAx(x=0,1)
366       \arg        DMAx(x=0,1)
367     \param[in]  channelx: specify which DMA channel
368       \arg        DMA_CHx(x=0..7)
369     \param[in]  pbeat: transfer burst beats
370                 only one parameter can be selected which is shown as below:
371       \arg        DMA_PERIPH_BURST_SINGLE: peripheral transfer single burst
372       \arg        DMA_PERIPH_BURST_4_BEAT: peripheral transfer 4-beat burst
373       \arg        DMA_PERIPH_BURST_8_BEAT: peripheral transfer 8-beat burst
374       \arg        DMA_PERIPH_BURST_16_BEAT: peripheral transfer 16-beat burst
375     \param[out] none
376     \retval     none
377 */
dma_periph_burst_beats_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t pbeat)378 void dma_periph_burst_beats_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t pbeat)
379 {
380     uint32_t ctl;
381     /* acquire DMA_CHxCTL register */
382     ctl = DMA_CHCTL(dma_periph, channelx);
383     /* assign regiser */
384     ctl &= ~DMA_CHXCTL_PBURST;
385     ctl |= pbeat;
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       \arg        DMA_CHx(x=0..7)
395     \param[in]  msize: transfer data size of memory
396                 only one parameter can be selected which is shown as below:
397       \arg        DMA_MEMORY_WIDTH_8BIT: transfer data size of memory is 8-bit
398       \arg        DMA_MEMORY_WIDTH_16BIT: transfer data size of memory is 16-bit
399       \arg        DMA_MEMORY_WIDTH_32BIT: transfer data size of memory is 32-bit
400     \param[out] none
401     \retval     none
402 */
dma_memory_width_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t msize)403 void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t msize)
404 {
405     uint32_t ctl;
406     /* acquire DMA_CHxCTL register */
407     ctl = DMA_CHCTL(dma_periph, channelx);
408     /* assign regiser */
409     ctl &= ~DMA_CHXCTL_MWIDTH;
410     ctl |= msize;
411     DMA_CHCTL(dma_periph, channelx) = ctl;
412 }
413 
414 /*!
415     \brief    configure transfer data size of peripheral
416     \param[in]  dma_periph: DMAx(x=0,1)
417       \arg        DMAx(x=0,1)
418     \param[in]  channelx: specify which DMA channel
419       \arg        DMA_CHx(x=0..7)
420     \param[in]  msize: transfer data size of peripheral
421                 only one parameter can be selected which is shown as below:
422       \arg        DMA_PERIPHERAL_WIDTH_8BIT: transfer data size of peripheral is 8-bit
423       \arg        DMA_PERIPHERAL_WIDTH_16BIT: transfer data size of peripheral is 16-bit
424       \arg        DMA_PERIPHERAL_WIDTH_32BIT: transfer data size of peripheral is 32-bit
425     \param[out] none
426     \retval     none
427 */
dma_periph_width_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t psize)428 void dma_periph_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t psize)
429 {
430     uint32_t ctl;
431     /* acquire DMA_CHxCTL register */
432     ctl = DMA_CHCTL(dma_periph, channelx);
433     /* assign regiser */
434     ctl &= ~DMA_CHXCTL_PWIDTH;
435     ctl |= psize;
436     DMA_CHCTL(dma_periph, channelx) = ctl;
437 }
438 
439 /*!
440     \brief    configure memory address generation generation_algorithm
441     \param[in]  dma_periph: DMAx(x=0,1)
442       \arg        DMAx(x=0,1)
443     \param[in]  channelx: specify which DMA channel
444       \arg        DMA_CHx(x=0..7)
445     \param[in]  generation_algorithm: the address generation algorithm
446                 only one parameter can be selected which is shown as below:
447       \arg        DMA_MEMORY_INCREASE_ENABLE: next address of memory is increasing address mode
448       \arg        DMA_MEMORY_INCREASE_DISABLE: next address of memory is fixed address mode
449     \param[out] none
450     \retval     none
451 */
dma_memory_address_generation_config(uint32_t dma_periph,dma_channel_enum channelx,uint8_t generation_algorithm)452 void dma_memory_address_generation_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t generation_algorithm)
453 {
454     if(DMA_MEMORY_INCREASE_ENABLE == generation_algorithm) {
455         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
456     } else {
457         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
458     }
459 }
460 
461 /*!
462     \brief    configure peripheral address generation_algorithm
463     \param[in]  dma_periph: DMAx(x=0,1)
464       \arg        DMAx(x=0,1)
465     \param[in]  channelx: specify which DMA channel
466       \arg        DMA_CHx(x=0..7)
467     \param[in]  generation_algorithm: the address generation algorithm
468                 only one parameter can be selected which is shown as below:
469       \arg        DMA_PERIPH_INCREASE_ENABLE: next address of peripheral is increasing address mode
470       \arg        DMA_PERIPH_INCREASE_DISABLE: next address of peripheral is fixed address mode
471       \arg        DMA_PERIPH_INCREASE_FIX: increasing steps of peripheral address is fixed
472     \param[out] none
473     \retval     none
474 */
dma_peripheral_address_generation_config(uint32_t dma_periph,dma_channel_enum channelx,uint8_t generation_algorithm)475 void dma_peripheral_address_generation_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t generation_algorithm)
476 {
477     if(DMA_PERIPH_INCREASE_ENABLE == generation_algorithm) {
478         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
479     } else if(DMA_PERIPH_INCREASE_DISABLE == generation_algorithm) {
480         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
481     } else {
482         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
483         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PAIF;
484     }
485 }
486 
487 /*!
488     \brief    enable DMA circulation mode
489     \param[in]  dma_periph: DMAx(x=0,1)
490       \arg        DMAx(x=0,1)
491     \param[in]  channelx: specify which DMA channel
492       \arg        DMA_CHx(x=0..7)
493     \param[out] none
494     \retval     none
495 */
dma_circulation_enable(uint32_t dma_periph,dma_channel_enum channelx)496 void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx)
497 {
498     DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN;
499 }
500 
501 /*!
502     \brief    disable DMA circulation mode
503     \param[in]  dma_periph: DMAx(x=0,1)
504       \arg        DMAx(x=0,1)
505     \param[in]  channelx: specify which DMA channel
506       \arg        DMA_CHx(x=0..7)
507     \param[out] none
508     \retval     none
509 */
dma_circulation_disable(uint32_t dma_periph,dma_channel_enum channelx)510 void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx)
511 {
512     DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN;
513 }
514 
515 /*!
516     \brief    enable DMA channel
517     \param[in]  dma_periph: DMAx(x=0,1)
518       \arg        DMAx(x=0,1)
519     \param[in]  channelx: specify which DMA channel
520       \arg        DMA_CHx(x=0..7)
521     \param[out] none
522     \retval     none
523 */
dma_channel_enable(uint32_t dma_periph,dma_channel_enum channelx)524 void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx)
525 {
526     DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CHEN;
527 }
528 
529 /*!
530     \brief    disable DMA channel
531     \param[in]  dma_periph: DMAx(x=0,1)
532       \arg        DMAx(x=0,1)
533     \param[in]  channelx: specify which DMA channel
534       \arg        DMA_CHx(x=0..7)
535     \param[out] none
536     \retval     none
537 */
dma_channel_disable(uint32_t dma_periph,dma_channel_enum channelx)538 void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx)
539 {
540     DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
541 }
542 
543 /*!
544     \brief    configure the direction of  data transfer on the channel
545     \param[in]  dma_periph: DMAx(x=0,1)
546       \arg        DMAx(x=0,1)
547     \param[in]  channelx: specify which DMA channel
548       \arg        DMA_CHx(x=0..7)
549     \param[in]  direction: specify the direction of  data transfer
550                 only one parameter can be selected which is shown as below:
551       \arg        DMA_PERIPH_TO_MEMORY: read from peripheral and write to memory
552       \arg        DMA_MEMORY_TO_PERIPH: read from memory and write to peripheral
553       \arg        DMA_MEMORY_TO_MEMORY: read from memory and write to memory
554     \param[out] none
555     \retval     none
556 */
dma_transfer_direction_config(uint32_t dma_periph,dma_channel_enum channelx,uint8_t direction)557 void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction)
558 {
559     uint32_t ctl;
560     /* acquire DMA_CHxCTL register */
561     ctl = DMA_CHCTL(dma_periph, channelx);
562     /* assign regiser */
563     ctl &= ~DMA_CHXCTL_TM;
564     ctl |= direction;
565 
566     DMA_CHCTL(dma_periph, channelx) = ctl;
567 }
568 
569 /*!
570     \brief    DMA switch buffer mode config
571     \param[in]  dma_periph: DMAx(x=0,1)
572       \arg        DMAx(x=0,1)
573     \param[in]  channelx: specify which DMA channel
574       \arg        DMA_CHx(x=0..7)
575     \param[in]  memory1_addr: memory1 base address
576     \param[in]  memory_select: DMA_MEMORY_0 or DMA_MEMORY_1
577     \param[out] none
578     \retval     none
579 */
dma_switch_buffer_mode_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t memory1_addr,uint32_t memory_select)580 void dma_switch_buffer_mode_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t memory1_addr, uint32_t memory_select)
581 {
582     /* configure memory1 base address */
583     DMA_CHM1ADDR(dma_periph, channelx) = memory1_addr;
584 
585     if(DMA_MEMORY_0 == memory_select) {
586         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MBS;
587     } else {
588         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MBS;
589     }
590 }
591 
592 /*!
593     \brief    DMA using memory get
594     \param[in]  dma_periph: DMAx(x=0,1)
595       \arg        DMAx(x=0,1)
596     \param[in]  channelx: specify which DMA channel
597       \arg        DMA_CHx(x=0..7)
598     \param[out] none
599     \retval     the using memory
600 */
dma_using_memory_get(uint32_t dma_periph,dma_channel_enum channelx)601 uint32_t dma_using_memory_get(uint32_t dma_periph, dma_channel_enum channelx)
602 {
603     if((DMA_CHCTL(dma_periph, channelx)) & DMA_CHXCTL_MBS) {
604         return DMA_MEMORY_1;
605     } else {
606         return DMA_MEMORY_0;
607     }
608 }
609 
610 /*!
611     \brief    DMA channel peripheral select
612     \param[in]  dma_periph: DMAx(x=0,1)
613       \arg        DMAx(x=0,1)
614     \param[in]  channelx: specify which DMA channel
615       \arg        DMA_CHx(x=0..7)
616     \param[in]  sub_periph: specify DMA channel peripheral
617       \arg        DMA_SUBPERIx(x=0..7)
618     \param[out] none
619     \retval     none
620 */
dma_channel_subperipheral_select(uint32_t dma_periph,dma_channel_enum channelx,dma_subperipheral_enum sub_periph)621 void dma_channel_subperipheral_select(uint32_t dma_periph, dma_channel_enum channelx, dma_subperipheral_enum sub_periph)
622 {
623     uint32_t ctl;
624     /* acquire DMA_CHxCTL register */
625     ctl = DMA_CHCTL(dma_periph, channelx);
626     /* assign regiser */
627     ctl &= ~DMA_CHXCTL_PERIEN;
628     ctl |= ((uint32_t)sub_periph << CHXCTL_PERIEN_OFFSET);
629 
630     DMA_CHCTL(dma_periph, channelx) = ctl;
631 }
632 
633 /*!
634     \brief    DMA flow controller configure
635     \param[in]  dma_periph: DMAx(x=0,1)
636       \arg        DMAx(x=0,1)
637     \param[in]  channelx: specify which DMA channel
638       \arg        DMA_CHx(x=0..7)
639     \param[in]  controller: specify DMA flow controler
640                 only one parameter can be selected which is shown as below:
641       \arg        DMA_FLOW_CONTROLLER_DMA: DMA is the flow controller
642       \arg        DMA_FLOW_CONTROLLER_PERI: peripheral is the flow controller
643     \param[out] none
644     \retval     none
645 */
dma_flow_controller_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t controller)646 void dma_flow_controller_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t controller)
647 {
648     if(DMA_FLOW_CONTROLLER_DMA == controller) {
649         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_TFCS;
650     } else {
651         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_TFCS;
652     }
653 }
654 
655 /*!
656     \brief    DMA switch buffer mode enable
657     \param[in]  dma_periph: DMAx(x=0,1)
658       \arg        DMAx(x=0,1)
659     \param[in]  channelx: specify which DMA channel
660       \arg        DMA_CHx(x=0..7)
661     \param[in]  newvalue: ENABLE or DISABLE
662     \param[out] none
663     \retval     none
664 */
dma_switch_buffer_mode_enable(uint32_t dma_periph,dma_channel_enum channelx,ControlStatus newvalue)665 void dma_switch_buffer_mode_enable(uint32_t dma_periph, dma_channel_enum channelx, ControlStatus newvalue)
666 {
667     if(ENABLE == newvalue) {
668         /* switch buffer mode enable */
669         DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_SBMEN;
670     } else {
671         /* switch buffer mode disable */
672         DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_SBMEN;
673     }
674 }
675 
676 /*!
677     \brief    DMA FIFO status get
678     \param[in]  dma_periph: DMAx(x=0,1)
679       \arg        DMAx(x=0,1)
680     \param[in]  channelx: specify which DMA channel
681       \arg        DMA_CHx(x=0..7)
682     \param[out] none
683     \retval     the using memory
684 */
dma_fifo_status_get(uint32_t dma_periph,dma_channel_enum channelx)685 uint32_t dma_fifo_status_get(uint32_t dma_periph, dma_channel_enum channelx)
686 {
687     return (DMA_CHFCTL(dma_periph, channelx) & DMA_CHXFCTL_FCNT);
688 }
689 
690 /*!
691     \brief    get DMA flag is set or not
692     \param[in]  dma_periph: DMAx(x=0,1)
693       \arg        DMAx(x=0,1)
694     \param[in]  channelx: specify which DMA channel to get flag
695       \arg        DMA_CHx(x=0..7)
696     \param[in]  flag: specify get which flag
697                 only one parameter can be selected which is shown as below:
698       \arg        DMA_FLAG_FEE: FIFO error and exception flag
699       \arg        DMA_FLAG_SDE: single data mode exception flag
700       \arg        DMA_FLAG_TAE: transfer access error flag
701       \arg        DMA_FLAG_HTF: half transfer finish flag
702       \arg        DMA_FLAG_FTF: full transger finish flag
703     \param[out] none
704     \retval     FlagStatus: SET or RESET
705 */
dma_flag_get(uint32_t dma_periph,dma_channel_enum channelx,uint32_t flag)706 FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
707 {
708     if(channelx < DMA_CH4) {
709         if(DMA_INTF0(dma_periph) & DMA_FLAG_ADD(flag, channelx)) {
710             return SET;
711         } else {
712             return RESET;
713         }
714     } else {
715         channelx -= (dma_channel_enum)4;
716         if(DMA_INTF1(dma_periph) & DMA_FLAG_ADD(flag, channelx)) {
717             return SET;
718         } else {
719             return RESET;
720         }
721     }
722 }
723 
724 /*!
725     \brief    clear DMA a channel flag
726     \param[in]  dma_periph: DMAx(x=0,1)
727       \arg        DMAx(x=0,1)
728     \param[in]  channelx: specify which DMA channel to get flag
729       \arg        DMA_CHx(x=0..7)
730     \param[in]  flag: specify get which flag
731                 only one parameter can be selected which is shown as below:
732       \arg        DMA_FLAG_FEE: FIFO error and exception flag
733       \arg        DMA_FLAG_SDE: single data mode exception flag
734       \arg        DMA_FLAG_TAE: transfer access error flag
735       \arg        DMA_FLAG_HTF: half transfer finish flag
736       \arg        DMA_FLAG_FTF: full transger finish flag
737     \param[out] none
738     \retval     none
739 */
dma_flag_clear(uint32_t dma_periph,dma_channel_enum channelx,uint32_t flag)740 void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
741 {
742     if(channelx < DMA_CH4) {
743         DMA_INTC0(dma_periph) |= DMA_FLAG_ADD(flag, channelx);
744     } else {
745         channelx -= (dma_channel_enum)4;
746         DMA_INTC1(dma_periph) |= DMA_FLAG_ADD(flag, channelx);
747     }
748 }
749 
750 /*!
751     \brief    enable DMA interrupt
752     \param[in]  dma_periph: DMAx(x=0,1)
753       \arg        DMAx(x=0,1)
754     \param[in]  channelx: specify which DMA channel
755       \arg        DMA_CHx(x=0..7)
756     \param[in]  source: specify which interrupt to enbale
757                 only one parameters can be selected which are shown as below:
758       \arg        DMA_CHXCTL_SDEIE: single data mode exception interrupt enable
759       \arg        DMA_CHXCTL_TAEIE: tranfer access error interrupt enable
760       \arg        DMA_CHXCTL_HTFIE: half transfer finish interrupt enable
761       \arg        DMA_CHXCTL_FTFIE: full transfer finish interrupt enable
762       \arg        DMA_CHXFCTL_FEEIE: FIFO exception interrupt enable
763     \param[out] none
764     \retval     none
765 */
dma_interrupt_enable(uint32_t dma_periph,dma_channel_enum channelx,uint32_t source)766 void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
767 {
768     if(DMA_CHXFCTL_FEEIE != source) {
769         DMA_CHCTL(dma_periph, channelx) |= source;
770     } else {
771         DMA_CHFCTL(dma_periph, channelx) |= source;
772     }
773 }
774 
775 /*!
776     \brief    disable DMA interrupt
777     \param[in]  dma_periph: DMAx(x=0,1)
778       \arg        DMAx(x=0,1)
779     \param[in]  channelx: specify which DMA channel
780       \arg        DMA_CHx(x=0..7)
781     \param[in]  source: specify which interrupt to disbale
782                 only one parameters can be selected which are shown as below:
783       \arg        DMA_CHXCTL_SDEIE: single data mode exception interrupt enable
784       \arg        DMA_CHXCTL_TAEIE: tranfer access error interrupt enable
785       \arg        DMA_CHXCTL_HTFIE: half transfer finish interrupt enable
786       \arg        DMA_CHXCTL_FTFIE: full transfer finish interrupt enable
787       \arg        DMA_CHXFCTL_FEEIE: FIFO exception interrupt enable
788     \param[out] none
789     \retval     none
790 */
dma_interrupt_disable(uint32_t dma_periph,dma_channel_enum channelx,uint32_t source)791 void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
792 {
793     if(DMA_CHXFCTL_FEEIE != source) {
794         DMA_CHCTL(dma_periph, channelx) &= ~source;
795     } else {
796         DMA_CHFCTL(dma_periph, channelx) &= ~source;
797     }
798 }
799 
800 /*!
801     \brief    get DMA interrupt flag is set or not
802     \param[in]  dma_periph: DMAx(x=0,1)
803       \arg        DMAx(x=0,1)
804     \param[in]  channelx: specify which DMA channel to get interrupt flag
805       \arg        DMA_CHx(x=0..7)
806     \param[in]  interrupt: specify get which flag
807                 only one parameter can be selected which is shown as below:
808       \arg        DMA_INT_FLAG_FEE: FIFO error and exception flag
809       \arg        DMA_INT_FLAG_SDE: single data mode exception flag
810       \arg        DMA_INT_FLAG_TAE: transfer access error flag
811       \arg        DMA_INT_FLAG_HTF: half transfer finish flag
812       \arg        DMA_INT_FLAG_FTF: full transger finish flag
813     \param[out] none
814     \retval     FlagStatus: SET or RESET
815 */
dma_interrupt_flag_get(uint32_t dma_periph,dma_channel_enum channelx,uint32_t interrupt)816 FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t interrupt)
817 {
818     uint32_t interrupt_enable = 0U, interrupt_flag = 0U;
819     dma_channel_enum channel_flag_offset = channelx;
820     if(channelx < DMA_CH4) {
821         switch(interrupt) {
822         case DMA_INTF_FEEIF:
823             interrupt_flag = DMA_INTF0(dma_periph) & DMA_FLAG_ADD(interrupt, channelx);
824             interrupt_enable = DMA_CHFCTL(dma_periph, channelx) & DMA_CHXFCTL_FEEIE;
825             break;
826         case DMA_INTF_SDEIF:
827             interrupt_flag = DMA_INTF0(dma_periph) & DMA_FLAG_ADD(interrupt, channelx);
828             interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_SDEIE;
829             break;
830         case DMA_INTF_TAEIF:
831             interrupt_flag = DMA_INTF0(dma_periph) & DMA_FLAG_ADD(interrupt, channelx);
832             interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_TAEIE;
833             break;
834         case DMA_INTF_HTFIF:
835             interrupt_flag = DMA_INTF0(dma_periph) & DMA_FLAG_ADD(interrupt, channelx);
836             interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE;
837             break;
838         case DMA_INTF_FTFIF:
839             interrupt_flag = (DMA_INTF0(dma_periph) & DMA_FLAG_ADD(interrupt, channelx));
840             interrupt_enable = (DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE);
841             break;
842         default:
843             break;
844         }
845     } else {
846         channel_flag_offset -= (dma_channel_enum)4;
847         switch(interrupt) {
848         case DMA_INTF_FEEIF:
849             interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(interrupt, channel_flag_offset);
850             interrupt_enable = DMA_CHFCTL(dma_periph, channelx) & DMA_CHXFCTL_FEEIE;
851             break;
852         case DMA_INTF_SDEIF:
853             interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(interrupt, channel_flag_offset);
854             interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_SDEIE;
855             break;
856         case DMA_INTF_TAEIF:
857             interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(interrupt, channel_flag_offset);
858             interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_TAEIE;
859             break;
860         case DMA_INTF_HTFIF:
861             interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(interrupt, channel_flag_offset);
862             interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE;
863             break;
864         case DMA_INTF_FTFIF:
865             interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(interrupt, channel_flag_offset);
866             interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE;
867             break;
868         default:
869             break;
870         }
871     }
872 
873     if(interrupt_flag && interrupt_enable) {
874         return SET;
875     } else {
876         return RESET;
877     }
878 }
879 
880 /*!
881     \brief    clear DMA a channel interrupt flag
882     \param[in]  dma_periph: DMAx(x=0,1)
883       \arg        DMAx(x=0,1)
884     \param[in]  channelx: specify which DMA channel to clear interrupt flag
885       \arg        DMA_CHx(x=0..7)
886     \param[in]  interrupt: specify get which flag
887                 only one parameter can be selected which is shown as below:
888       \arg        DMA_INT_FLAG_FEE: FIFO error and exception flag
889       \arg        DMA_INT_FLAG_SDE: single data mode exception flag
890       \arg        DMA_INT_FLAG_TAE: transfer access error flag
891       \arg        DMA_INT_FLAG_HTF: half transfer finish flag
892       \arg        DMA_INT_FLAG_FTF: full transger finish flag
893     \param[out] none
894     \retval     none
895 */
dma_interrupt_flag_clear(uint32_t dma_periph,dma_channel_enum channelx,uint32_t interrupt)896 void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t interrupt)
897 {
898     if(channelx < DMA_CH4) {
899         DMA_INTC0(dma_periph) |= DMA_FLAG_ADD(interrupt, channelx);
900     } else {
901         channelx -= (dma_channel_enum)4;
902         DMA_INTC1(dma_periph) |= DMA_FLAG_ADD(interrupt, channelx);
903     }
904 }
905