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