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