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