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