• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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