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