1 /*
2 * Copyright (c) 2021-2022 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8
9 #ifndef HPM_DMAV2_DRV_H
10 #define HPM_DMAV2_DRV_H
11 #include "hpm_common.h"
12 #include "hpm_soc_feature.h"
13 #include "hpm_dmav2_regs.h"
14
15 /**
16 *
17 * @brief DMA driver APIs
18 * @defgroup dma_interface DMA driver APIs
19 * @ingroup io_interfaces
20 * @{
21 */
22
23 #define DMA_Type DMAV2_Type
24
25 #define DMA_CHANNEL_PRIORITY_LOW (0U)
26 #define DMA_CHANNEL_PRIORITY_HIGH (1U)
27
28 #define DMA_NUM_TRANSFER_PER_BURST_1T (0U)
29 #define DMA_NUM_TRANSFER_PER_BURST_2T (1U)
30 #define DMA_NUM_TRANSFER_PER_BURST_4T (2U)
31 #define DMA_NUM_TRANSFER_PER_BURST_8T (3U)
32 #define DMA_NUM_TRANSFER_PER_BURST_16T (4U)
33 #define DMA_NUM_TRANSFER_PER_BURST_32T (5U)
34 #define DMA_NUM_TRANSFER_PER_BURST_64T (6U)
35 #define DMA_NUM_TRANSFER_PER_BURST_128T (7U)
36 #define DMA_NUM_TRANSFER_PER_BURST_256T (8U)
37 #define DMA_NUM_TRANSFER_PER_BURST_512T (9U)
38 #define DMA_NUM_TRANSFER_PER_BURST_1024T (10U)
39
40 #define DMA_TRANSFER_WIDTH_BYTE (0U)
41 #define DMA_TRANSFER_WIDTH_HALF_WORD (1U)
42 #define DMA_TRANSFER_WIDTH_WORD (2U)
43 #define DMA_TRANSFER_WIDTH_DOUBLE_WORD (3U)
44
45 #define DMA_ALIGN_HALF_WORD(x) (x & ~(1u))
46 #define DMA_ALIGN_WORD(x) (x & ~(3u))
47 #define DMA_ALIGN_DOUBLE_WORD(x) (x & ~(7u))
48
49 #define DMA_CHANNEL_STATUS_ONGOING (1U)
50 #define DMA_CHANNEL_STATUS_ERROR (2U)
51 #define DMA_CHANNEL_STATUS_ABORT (4U)
52 #define DMA_CHANNEL_STATUS_TC (8U)
53 #define DMA_CHANNEL_STATUS_HALF_TC (16U)
54
55 #define DMA_CHANNEL_IRQ_STATUS_ERROR(x) (uint32_t)(1 << x)
56 #define DMA_CHANNEL_IRQ_STATUS_ABORT(x) (uint32_t)(1 << x)
57 #define DMA_CHANNEL_IRQ_STATUS_TC(x) (uint32_t)(1 << x)
58 #define DMA_CHANNEL_IRQ_STATUS_HALF_TC(x) (uint32_t)(1 << x)
59
60 #define DMA_HANDSHAKE_MODE_NORMAL (0U)
61 #define DMA_HANDSHAKE_MODE_HANDSHAKE (1U)
62
63 #define DMA_ADDRESS_CONTROL_INCREMENT (0U)
64 #define DMA_ADDRESS_CONTROL_DECREMENT (1U)
65 #define DMA_ADDRESS_CONTROL_FIXED (2U)
66
67 #define DMA_SRC_BURST_OPT_STANDAND_SIZE (0U)
68 #define DMA_SRC_BURST_OPT_CUSTOM_SIZE (1U)
69
70 #define DMA_HANDSHAKE_OPT_ONE_BURST (0U)
71 #define DMA_HANDSHAKE_OPT_ALL_TRANSIZE (1U)
72
73 #define DMA_INTERRUPT_MASK_NONE (0U)
74 #define DMA_INTERRUPT_MASK_ERROR DMAV2_CHCTRL_CTRL_INTERRMASK_MASK
75 #define DMA_INTERRUPT_MASK_ABORT DMAV2_CHCTRL_CTRL_INTABTMASK_MASK
76 #define DMA_INTERRUPT_MASK_TERMINAL_COUNT DMAV2_CHCTRL_CTRL_INTTCMASK_MASK
77 #define DMA_INTERRUPT_MASK_HALF_TC DMAV2_CHCTRL_CTRL_INTHALFCNTMASK_MASK
78 #define DMA_INTERRUPT_MASK_ALL \
79 (uint8_t)(DMA_INTERRUPT_MASK_TERMINAL_COUNT \
80 | DMA_INTERRUPT_MASK_ABORT \
81 | DMA_INTERRUPT_MASK_ERROR \
82 | DMA_INTERRUPT_MASK_HALF_TC)
83
84 #define DMA_SUPPORT_64BIT_ADDR (0)
85
86
87 enum {
88 dmav2_state_idle = 0,
89 dmav2_state_read,
90 dmav2_state_read_ack,
91 dmav2_state_write,
92 dmav2_state_write_ack,
93 dmav2_state_ll,
94 dmav2_state_end,
95 dmav2_state_end_wait,
96 };
97
98 /**
99 * @brief Linked descriptor
100 *
101 * It is consumed by DMA controlled directly
102 */
103 typedef struct dma_linked_descriptor {
104 uint32_t ctrl; /**< Control */
105 uint32_t trans_size; /**< Transfer size in source width */
106 uint32_t src_addr; /**< Source address */
107 uint32_t req_ctrl; /**< Request select */
108 uint32_t dst_addr; /**< Destination address */
109 uint32_t reserved0; /**< not used on dmav2 */
110 uint32_t linked_ptr; /**< Linked descriptor address */
111 uint32_t reserved1; /**< not used on dmav2 */
112 } dma_linked_descriptor_t;
113
114 /* @brief Channel config */
115 typedef struct dma_channel_config {
116 uint8_t priority; /**< Channel priority */
117 uint8_t src_burst_size; /**< Source burst size */
118 uint8_t src_mode; /**< Source work mode */
119 uint8_t dst_mode; /**< Destination work mode */
120 uint8_t src_width; /**< Source width */
121 uint8_t dst_width; /**< Destination width */
122 uint8_t src_addr_ctrl; /**< Source address control */
123 uint8_t dst_addr_ctrl; /**< Destination address control */
124 uint16_t interrupt_mask; /**< Interrupt mask */
125 uint32_t src_addr; /**< Source address */
126 uint32_t dst_addr; /**< Destination address */
127 uint32_t linked_ptr; /**< Next linked descriptor */
128 uint32_t size_in_byte; /**< Total size to be transferred in byte */
129 bool en_infiniteloop; /**< Infinite loop transfer enable. Attention: only DMAV2 support */
130 uint8_t handshake_opt; /**< Handshake transfer option. Attention: only DMAV2 support */
131 uint8_t burst_opt; /**< Burst size option. Attention: only DMAV2 support */
132 } dma_channel_config_t;
133
134 /* @brief Channel config */
135 typedef struct dma_handshake_config {
136 uint32_t dst;
137 uint32_t src;
138 uint32_t size_in_byte;
139 uint8_t data_width; /* data width, value defined by DMA_TRANSFER_WIDTH_xxx */
140 uint8_t ch_index;
141 bool dst_fixed;
142 bool src_fixed;
143 bool en_infiniteloop;
144 uint16_t interrupt_mask;
145 } dma_handshake_config_t;
146
147
148 /* @brief DMA specific status */
149 enum {
150 status_dma_transfer_done = MAKE_STATUS(status_group_dma, 0),
151 status_dma_transfer_error = MAKE_STATUS(status_group_dma, 1),
152 status_dma_transfer_abort = MAKE_STATUS(status_group_dma, 2),
153 status_dma_transfer_ongoing = MAKE_STATUS(status_group_dma, 3),
154 status_dma_alignment_error = MAKE_STATUS(status_group_dma, 4),
155 status_dma_transfer_half_done = MAKE_STATUS(status_group_dma, 5),
156 };
157
158 #ifdef __cplusplus
159 extern "C" {
160 #endif
161
162 /**
163 * @brief Reset DMA
164 *
165 * @param[in] ptr DMA base address
166 */
dma_reset(DMAV2_Type * ptr)167 static inline void dma_reset(DMAV2_Type *ptr)
168 {
169 ptr->DMACTRL |= DMAV2_DMACTRL_RESET_MASK;
170 }
171
172 /**
173 * @brief Enable DMA channel
174 *
175 * @param[in] ptr DMA base address
176 * @param[in] ch_index Index of the channel to be enabled
177 *
178 * @return status_success if everything's okay
179 */
dma_enable_channel(DMAV2_Type * ptr,uint32_t ch_index)180 static inline hpm_stat_t dma_enable_channel(DMAV2_Type *ptr, uint32_t ch_index)
181 {
182 ptr->CHCTRL[ch_index].CTRL |= DMAV2_CHCTRL_CTRL_ENABLE_MASK;
183
184 if ((ptr->CHEN == 0) || !(ptr->CHEN & 1 << ch_index)) {
185 return status_fail;
186 }
187 return status_success;
188 }
189
190 /**
191 * @brief Disable DMA channel
192 *
193 * @param[in] ptr DMA base address
194 * @param[in] ch_index Index of the channel to be disabled
195 *
196 */
dma_disable_channel(DMAV2_Type * ptr,uint32_t ch_index)197 static inline void dma_disable_channel(DMAV2_Type *ptr, uint32_t ch_index)
198 {
199 ptr->CHCTRL[ch_index].CTRL &= ~DMAV2_CHCTRL_CTRL_ENABLE_MASK;
200 }
201
202 /**
203 * @brief Check whether DMA channel is enable
204 *
205 * @param[in] ptr DMA base address
206 * @param[in] ch_index Index of the channel
207 *
208 * @return true if DMA channel is enable
209 *
210 */
dma_channel_is_enable(DMAV2_Type * ptr,uint32_t ch_index)211 static inline bool dma_channel_is_enable(DMAV2_Type *ptr, uint32_t ch_index)
212 {
213 return (ptr->CHCTRL[ch_index].CTRL & DMAV2_CHCTRL_CTRL_ENABLE_MASK) ? true : false;
214 }
215
216 /**
217 * @brief Set DMA channel priority
218 *
219 * @param[in] ptr DMA base address
220 * @param[in] ch_index Index of the channel
221 * @param[in] priority dma priority
222 * @arg @ref DMA_PRIORITY_LOW
223 * @arg @ref DMA_PRIORITY_HIGH
224 *
225 */
dma_set_priority(DMAV2_Type * ptr,uint32_t ch_index,uint8_t priority)226 static inline void dma_set_priority(DMAV2_Type *ptr, uint32_t ch_index, uint8_t priority)
227 {
228 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_PRIORITY_MASK) | DMAV2_CHCTRL_CTRL_PRIORITY_SET(priority);
229 }
230
231 /**
232 * @brief Set DMA channel source work mode
233 *
234 * @param[in] ptr DMA base address
235 * @param[in] ch_index Index of the channel
236 * @param[in] mode source work mode
237 * @arg @ref DMA_HANDSHAKE_MODE_NORMAL
238 * @arg @ref DMA_HANDSHAKE_MODE_HANDSHAKE
239 *
240 */
dma_set_source_work_mode(DMAV2_Type * ptr,uint32_t ch_index,uint8_t mode)241 static inline void dma_set_source_work_mode(DMAV2_Type *ptr, uint32_t ch_index, uint8_t mode)
242 {
243 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_SRCMODE_MASK) | DMAV2_CHCTRL_CTRL_SRCMODE_SET(mode);
244 }
245
246 /**
247 * @brief Set DMA channel destination work mode
248 *
249 * @param[in] ptr DMA base address
250 * @param[in] ch_index Index of the channel
251 * @param[in] mode destination work mode
252 * @arg @ref DMA_HANDSHAKE_MODE_NORMAL
253 * @arg @ref DMA_HANDSHAKE_MODE_HANDSHAKE
254 *
255 */
dma_set_destination_work_mode(DMAV2_Type * ptr,uint32_t ch_index,uint8_t mode)256 static inline void dma_set_destination_work_mode(DMAV2_Type *ptr, uint32_t ch_index, uint8_t mode)
257 {
258 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_DSTMODE_MASK) | DMAV2_CHCTRL_CTRL_DSTMODE_SET(mode);
259 }
260
261 /**
262 * @brief Set DMA channel source burst size
263 *
264 * @param[in] ptr DMA base address
265 * @param[in] ch_index Index of the channel
266 * @param[in] burstsize source burst size
267 * when BURSTOPT is 0, please reference follows:
268 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_1T
269 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_2T
270 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_4T
271 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_8T
272 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_16T
273 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_32T
274 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_64T
275 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_128T
276 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_256T
277 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_512T
278 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_1024T
279 * when BURSTOPT is 1, burst size is (burstsize + 1).
280 *
281 */
dma_set_source_burst_size(DMAV2_Type * ptr,uint32_t ch_index,uint8_t burstsize)282 static inline void dma_set_source_burst_size(DMAV2_Type *ptr, uint32_t ch_index, uint8_t burstsize)
283 {
284 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_SRCBURSTSIZE_MASK) | DMAV2_CHCTRL_CTRL_SRCBURSTSIZE_SET(burstsize);
285 }
286
287 /**
288 * @brief Get DMA channel remaining transfer size
289 *
290 * @param[in] ptr DMA base address
291 * @param[in] ch_index Index of the channel
292 *
293 * @return remaining transfer size
294 *
295 */
dma_get_remaining_transfer_size(DMAV2_Type * ptr,uint32_t ch_index)296 static inline uint32_t dma_get_remaining_transfer_size(DMAV2_Type *ptr, uint32_t ch_index)
297 {
298 return ptr->CHCTRL[ch_index].TRANSIZE;
299 }
300
301 /**
302 * @brief Set DMA channel transfer size
303 *
304 * @param[in] ptr DMA base address
305 * @param[in] ch_index Index of the channel
306 * @param[in] size_in_width transfer size of the channel. The width is current dma channel configured source width.
307 * Transfer total bytes are (size_in_width * source width).
308 *
309 */
dma_set_transfer_size(DMAV2_Type * ptr,uint32_t ch_index,uint32_t size_in_width)310 static inline void dma_set_transfer_size(DMAV2_Type *ptr, uint32_t ch_index, uint32_t size_in_width)
311 {
312 ptr->CHCTRL[ch_index].TRANSIZE = DMAV2_CHCTRL_TRANSIZE_TRANSIZE_SET(size_in_width);
313 }
314
315 /**
316 * @brief Set DMA channel source width
317 *
318 * @param[in] ptr DMA base address
319 * @param[in] ch_index Index of the channel
320 * @param[in] width transfer source width of the channel
321 * @arg @ref DMA_TRANSFER_WIDTH_BYTE
322 * @arg @ref DMA_TRANSFER_WIDTH_HALF_WORD
323 * @arg @ref DMA_TRANSFER_WIDTH_WORD
324 * @arg @ref DMA_TRANSFER_WIDTH_DOUBLE_WORD
325 */
dma_set_source_width(DMAV2_Type * ptr,uint32_t ch_index,uint8_t width)326 static inline void dma_set_source_width(DMAV2_Type *ptr, uint32_t ch_index, uint8_t width)
327 {
328 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_SRCWIDTH_MASK) | DMAV2_CHCTRL_CTRL_SRCWIDTH_SET(width);
329 }
330
331 /**
332 * @brief Set DMA channel destination width
333 *
334 * @param[in] ptr DMA base address
335 * @param[in] ch_index Index of the channel
336 * @param[in] width transfer destination width of the channel
337 * @arg @ref DMA_TRANSFER_WIDTH_BYTE
338 * @arg @ref DMA_TRANSFER_WIDTH_HALF_WORD
339 * @arg @ref DMA_TRANSFER_WIDTH_WORD
340 * @arg @ref DMA_TRANSFER_WIDTH_DOUBLE_WORD
341 */
dma_set_destination_width(DMAV2_Type * ptr,uint32_t ch_index,uint8_t width)342 static inline void dma_set_destination_width(DMAV2_Type *ptr, uint32_t ch_index, uint8_t width)
343 {
344 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_DSTWIDTH_MASK) | DMAV2_CHCTRL_CTRL_DSTWIDTH_SET(width);
345 }
346
347 /**
348 * @brief Set DMA channel transfer width and size in byte
349 *
350 * @param[in] ptr DMA base address
351 * @param[in] ch_index Index of the channel
352 * @param[in] src_width transfer source width of the channel
353 * @arg @ref DMA_TRANSFER_WIDTH_BYTE
354 * @arg @ref DMA_TRANSFER_WIDTH_HALF_WORD
355 * @arg @ref DMA_TRANSFER_WIDTH_WORD
356 * @arg @ref DMA_TRANSFER_WIDTH_DOUBLE_WORD
357 * @param[in] size_in_byte transfer size in byte of the channel. The dma transfer size is (size_in_byte >> src_width).
358 *
359 */
dma_set_transfer_src_width_byte_size(DMAV2_Type * ptr,uint32_t ch_index,uint8_t src_width,uint32_t size_in_byte)360 static inline void dma_set_transfer_src_width_byte_size(DMAV2_Type *ptr, uint32_t ch_index, uint8_t src_width, uint32_t size_in_byte)
361 {
362 assert((src_width == DMA_TRANSFER_WIDTH_BYTE) || (src_width == DMA_TRANSFER_WIDTH_HALF_WORD)
363 || (src_width == DMA_TRANSFER_WIDTH_WORD) || (src_width == DMA_TRANSFER_WIDTH_DOUBLE_WORD));
364
365 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_SRCWIDTH_MASK) | DMAV2_CHCTRL_CTRL_SRCWIDTH_SET(src_width);
366 ptr->CHCTRL[ch_index].TRANSIZE = DMAV2_CHCTRL_TRANSIZE_TRANSIZE_SET(size_in_byte >> src_width);
367 }
368
369 /**
370 * @brief Set DMA channel source address
371 *
372 * @param[in] ptr DMA base address
373 * @param[in] ch_index Index of the channel
374 * @param[in] addr source address
375 *
376 */
dma_set_source_address(DMAV2_Type * ptr,uint32_t ch_index,uint32_t addr)377 static inline void dma_set_source_address(DMAV2_Type *ptr, uint32_t ch_index, uint32_t addr)
378 {
379 ptr->CHCTRL[ch_index].SRCADDR = addr;
380 }
381
382 /**
383 * @brief Set DMA channel destination address
384 *
385 * @param[in] ptr DMA base address
386 * @param[in] ch_index Index of the channel
387 * @param[in] addr destination address
388 *
389 */
dma_set_destination_address(DMAV2_Type * ptr,uint32_t ch_index,uint32_t addr)390 static inline void dma_set_destination_address(DMAV2_Type *ptr, uint32_t ch_index, uint32_t addr)
391 {
392 ptr->CHCTRL[ch_index].DSTADDR = addr;
393 }
394
395 /**
396 * @brief Set DMA channel source address control mode
397 *
398 * @param[in] ptr DMA base address
399 * @param[in] ch_index Index of the channel
400 * @param[in] addr_ctrl source address control mode
401 * @arg @ref DMA_ADDRESS_CONTROL_INCREMENT
402 * @arg @ref DMA_ADDRESS_CONTROL_DECREMENT
403 * @arg @ref DMA_ADDRESS_CONTROL_FIXED
404 *
405 */
dma_set_source_address_ctrl(DMAV2_Type * ptr,uint32_t ch_index,uint8_t addr_ctrl)406 static inline void dma_set_source_address_ctrl(DMAV2_Type *ptr, uint32_t ch_index, uint8_t addr_ctrl)
407 {
408 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_SRCADDRCTRL_MASK) | DMAV2_CHCTRL_CTRL_SRCADDRCTRL_SET(addr_ctrl);
409 }
410
411 /**
412 * @brief Set DMA channel destination address control mode
413 *
414 * @param[in] ptr DMA base address
415 * @param[in] ch_index Index of the channel
416 * @param[in] addr_ctrl destination address control mode
417 * @arg @ref DMA_ADDRESS_CONTROL_INCREMENT
418 * @arg @ref DMA_ADDRESS_CONTROL_DECREMENT
419 * @arg @ref DMA_ADDRESS_CONTROL_FIXED
420 *
421 */
dma_set_destination_address_ctrl(DMAV2_Type * ptr,uint32_t ch_index,uint8_t addr_ctrl)422 static inline void dma_set_destination_address_ctrl(DMAV2_Type *ptr, uint32_t ch_index, uint8_t addr_ctrl)
423 {
424 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_DSTADDRCTRL_MASK) | DMAV2_CHCTRL_CTRL_DSTADDRCTRL_SET(addr_ctrl);
425 }
426
427 /**
428 * @brief Set DMA channel infinite loop mode
429 *
430 * @param[in] ptr DMA base address
431 * @param[in] ch_index Index of the channel
432 * @param[in] infinite_loop false - normal mode(single times mode); true - infinite loop mode(cycle mode)
433 *
434 */
dma_set_infinite_loop_mode(DMAV2_Type * ptr,uint32_t ch_index,bool infinite_loop)435 static inline void dma_set_infinite_loop_mode(DMAV2_Type *ptr, uint32_t ch_index, bool infinite_loop)
436 {
437 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_INFINITELOOP_MASK) | DMAV2_CHCTRL_CTRL_INFINITELOOP_SET(infinite_loop);
438 }
439
440 /**
441 * @brief Set DMA channel source burst option
442 *
443 * @param[in] ptr DMA base address
444 * @param[in] ch_index Index of the channel
445 * @param[in] burst_opt burst option
446 * @arg @ref DMA_SRC_BURST_OPT_STANDAND_SIZE
447 * @arg @ref DMA_SRC_BURST_OPT_CUSTOM_SIZE
448 *
449 */
dma_set_src_busrt_option(DMAV2_Type * ptr,uint32_t ch_index,uint8_t burst_opt)450 static inline void dma_set_src_busrt_option(DMAV2_Type *ptr, uint32_t ch_index, uint8_t burst_opt)
451 {
452 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_BURSTOPT_MASK) | DMAV2_CHCTRL_CTRL_BURSTOPT_SET(burst_opt);
453 }
454
455 /**
456 * @brief Set DMA channel handshake option
457 *
458 * @param[in] ptr DMA base address
459 * @param[in] ch_index Index of the channel
460 * @param[in] handshake_opt handshake option
461 * @arg @ref DMA_HANDSHAKE_OPT_ONE_BURST
462 * @arg @ref DMA_HANDSHAKE_OPT_ALL_TRANSIZE
463 *
464 */
dma_set_handshake_option(DMAV2_Type * ptr,uint32_t ch_index,uint8_t handshake_opt)465 static inline void dma_set_handshake_option(DMAV2_Type *ptr, uint32_t ch_index, uint8_t handshake_opt)
466 {
467 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_HANDSHAKEOPT_MASK) | DMAV2_CHCTRL_CTRL_HANDSHAKEOPT_SET(handshake_opt);
468 }
469
470 /**
471 * @brief Abort channel transfer with mask
472 *
473 * @param[in] ptr DMA base address
474 * @param[in] ch_index_mask Mask of channels to be aborted
475 */
dma_abort_channel(DMAV2_Type * ptr,uint32_t ch_index_mask)476 static inline void dma_abort_channel(DMAV2_Type *ptr, uint32_t ch_index_mask)
477 {
478 ptr->CHABORT |= DMAV2_CHABORT_CHABORT_SET(ch_index_mask);
479 }
480
481 /**
482 * @brief Check if channels are enabled with mask
483 *
484 * @param[in] ptr DMA base address
485 * @param[in] ch_index_mask Mask of channels to be checked
486 *
487 * @return Enabled channel mask
488 */
dma_check_enabled_channel(DMAV2_Type * ptr,uint32_t ch_index_mask)489 static inline uint32_t dma_check_enabled_channel(DMAV2_Type *ptr,
490 uint32_t ch_index_mask)
491 {
492 return (ch_index_mask & ptr->CHEN);
493 }
494
495 /**
496 * @brief Check if linked pointer has been configured
497 *
498 * @param[in] ptr DMA base address
499 * @param[in] ch_index Target channel index to be checked
500 *
501 * @return true if linked pointer has been configured
502 */
dma_has_linked_pointer_configured(DMAV2_Type * ptr,uint32_t ch_index)503 static inline bool dma_has_linked_pointer_configured(DMAV2_Type *ptr, uint32_t ch_index)
504 {
505 return ptr->CHCTRL[ch_index].LLPOINTER != 0;
506 }
507
508 /**
509 * @brief Check transfer status
510 *
511 * @param[in] ptr DMA base address
512 * @param[in] ch_index Target channel index to be checked
513 *
514 * @retval DMA_CHANNEL_STATUS_ONGOING if transfer is still ongoing
515 * @retval DMA_CHANNEL_STATUS_ERROR if any error occurred during transferring
516 * @retval DMA_CHANNEL_STATUS_ABORT if transfer is aborted
517 * @retval DMA_CHANNEL_STATUS_TC if transfer is finished without error
518 * @retval DMA_CHANNEL_STATUS_HALF_TC if half transfer complete without error
519 */
dma_check_transfer_status(DMAV2_Type * ptr,uint8_t ch_index)520 static inline uint32_t dma_check_transfer_status(DMAV2_Type *ptr, uint8_t ch_index)
521 {
522 uint32_t dma_status = 0;
523
524 if (ptr->INTTCSTS & (1 << ch_index)) {
525 dma_status |= DMA_CHANNEL_STATUS_TC;
526 ptr->INTTCSTS = (1 << ch_index); /* W1C clear status*/
527 }
528 if (ptr->INTHALFSTS & (1 << ch_index)) {
529 dma_status |= DMA_CHANNEL_STATUS_HALF_TC;
530 ptr->INTHALFSTS = (1 << ch_index); /* W1C clear status*/
531 }
532 if (ptr->INTERRSTS & (1 << ch_index)) {
533 dma_status |= DMA_CHANNEL_STATUS_ERROR;
534 ptr->INTERRSTS = (1 << ch_index); /* W1C clear status*/
535 }
536 if (ptr->INTABORTSTS & (1 << ch_index)) {
537 dma_status |= DMA_CHANNEL_STATUS_ABORT;
538 ptr->INTABORTSTS = (1 << ch_index); /* W1C clear status*/
539 }
540 if (dma_status == 0) {
541 dma_status = DMA_CHANNEL_STATUS_ONGOING;
542 }
543 return dma_status;
544 }
545
546 /**
547 * @brief Clear transfer status
548 *
549 * @param[in] ptr DMA base address
550 * @param[in] ch_index Target channel index
551 *
552 */
dma_clear_transfer_status(DMAV2_Type * ptr,uint8_t ch_index)553 static inline void dma_clear_transfer_status(DMAV2_Type *ptr, uint8_t ch_index)
554 {
555 /* W1C */
556 ptr->INTHALFSTS = (1 << ch_index);
557 ptr->INTTCSTS = (1 << ch_index);
558 ptr->INTABORTSTS = (1 << ch_index);
559 ptr->INTERRSTS = (1 << ch_index);
560 }
561
562 /**
563 * @brief Enable DMA Channel interrupt
564 *
565 * @param [in] ptr DMA base address
566 * @param [in] ch_index Target channel index
567 * @param [in] interrupt_mask Interrupt mask
568 */
dma_enable_channel_interrupt(DMAV2_Type * ptr,uint8_t ch_index,int32_t interrupt_mask)569 static inline void dma_enable_channel_interrupt(DMAV2_Type *ptr, uint8_t ch_index, int32_t interrupt_mask)
570 {
571 ptr->CHCTRL[ch_index].CTRL &= ~(interrupt_mask & DMA_INTERRUPT_MASK_ALL);
572 }
573
574 /**
575 * @brief Disable DMA Channel interrupt
576 *
577 * @param [in] ptr DMA base address
578 * @param [in] ch_index Target channel index
579 * @param [in] interrupt_mask Interrupt mask
580 */
dma_disable_channel_interrupt(DMAV2_Type * ptr,uint8_t ch_index,int32_t interrupt_mask)581 static inline void dma_disable_channel_interrupt(DMAV2_Type *ptr, uint8_t ch_index, int32_t interrupt_mask)
582 {
583 ptr->CHCTRL[ch_index].CTRL |= (interrupt_mask & DMA_INTERRUPT_MASK_ALL);
584 }
585
586
587 /**
588 * @brief Check Channel interrupt master
589 *
590 * @param[in] ptr DMA base address
591 * @param[in] ch_index Target channel index to be checked
592 * @return uint32_t Interrupt mask
593 */
dma_check_channel_interrupt_mask(DMAV2_Type * ptr,uint8_t ch_index)594 static inline uint32_t dma_check_channel_interrupt_mask(DMAV2_Type *ptr, uint8_t ch_index)
595 {
596 return ptr->CHCTRL[ch_index].CTRL & DMA_INTERRUPT_MASK_ALL;
597 }
598
599 /**
600 * @brief Get default channel config
601 *
602 * @param[in] ptr DMA base address
603 * @param[in] ch Channel config
604 */
605 void dma_default_channel_config(DMAV2_Type *ptr, dma_channel_config_t *ch);
606
607 /**
608 * @brief Setup DMA channel
609 *
610 * @param[in] ptr DMA base address
611 * @param[in] ch_num Target channel index to be configured
612 * @param[in] ch Channel config
613 * @param[in] start_transfer Set true to start transfer
614 *
615 * @return status_success if everything is okay
616 */
617 hpm_stat_t dma_setup_channel(DMAV2_Type *ptr, uint8_t ch_num,
618 dma_channel_config_t *ch, bool start_transfer);
619
620 /**
621 * @brief Config linked descriptor function
622 *
623 * @param[in] ptr DMA base address
624 * @param[in] descriptor Linked descriptor pointer
625 * @param[in] ch_num Target channel index to be configured
626 * @param[in] config Descriptor config pointer
627 *
628 * @return status_success if everything is okay
629 */
630 hpm_stat_t dma_config_linked_descriptor(DMAV2_Type *ptr, dma_linked_descriptor_t *descriptor, uint8_t ch_num, dma_channel_config_t *config);
631
632 /**
633 * @brief Start DMA copy
634 *
635 * @param[in] ptr DMA base address
636 * @param[in] ch_num Target channel index
637 * @param[in] dst Destination address
638 * @param[in] src Source Address
639 * @param[in] size_in_byte Size in byte
640 * @param[in] burst_len_in_byte Burst length in byte
641 *
642 * @return status_success if everthing is okay
643 * @note: dst, src, size should be aligned with burst_len_in_byte
644 */
645 hpm_stat_t dma_start_memcpy(DMAV2_Type *ptr, uint8_t ch_num,
646 uint32_t dst, uint32_t src,
647 uint32_t size_in_byte, uint32_t burst_len_in_byte);
648
649 /**
650 * @brief Get default handshake config
651 *
652 * @param[in] ptr DMA base address
653 * @param[in] config default config
654 */
655 void dma_default_handshake_config(DMAV2_Type *ptr, dma_handshake_config_t *config);
656
657 /**
658 * @brief config dma handshake function
659 *
660 * @param[in] ptr DMA base address
661 * @param[in] pconfig dma handshake config pointer
662 * @param[in] start_transfer Set true to start transfer
663 *
664 * @return status_success if everything is okay
665 */
666 hpm_stat_t dma_setup_handshake(DMAV2_Type *ptr, dma_handshake_config_t *pconfig, bool start_transfer);
667
668 /**
669 * @brief Check whether DMA is idle
670 * @param [in] ptr DMA base address
671 * @return true DMA is idle
672 * @return false DMA is busy
673 */
dma_is_idle(DMAV2_Type * ptr)674 static inline bool dma_is_idle(DMAV2_Type *ptr)
675 {
676 return (DMAV2_IDMISC_DMASTATE_GET(ptr->IDMISC) == dmav2_state_idle) ? true : false;
677 }
678
679
680 #ifdef __cplusplus
681 }
682 #endif
683 /**
684 * @}
685 */
686 #endif /* HPM_DMAV2_DRV_H */
687