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