1 /***************************************************************************//**
2 * \file cyhal_dma.h
3 *
4 * \brief
5 * Provides a high level interface for interacting with the Infineon DMA.
6 * This interface abstracts out the chip specific details. If any chip specific
7 * functionality is necessary, or performance is critical the low level functions
8 * can be used directly.
9 *
10 ********************************************************************************
11 * \copyright
12 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
13 * an affiliate of Cypress Semiconductor Corporation
14 *
15 * SPDX-License-Identifier: Apache-2.0
16 *
17 * Licensed under the Apache License, Version 2.0 (the "License");
18 * you may not use this file except in compliance with the License.
19 * You may obtain a copy of the License at
20 *
21 *     http://www.apache.org/licenses/LICENSE-2.0
22 *
23 * Unless required by applicable law or agreed to in writing, software
24 * distributed under the License is distributed on an "AS IS" BASIS,
25 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26 * See the License for the specific language governing permissions and
27 * limitations under the License.
28 *******************************************************************************/
29 
30 /**
31  * \addtogroup group_hal_dma DMA (Direct Memory Access)
32  * \ingroup group_hal
33  * \{
34  * High level interface for interacting with the direct memory access (DMA). The DMA driver allows
35  * for initializing and configuring a DMA channel in order to trigger data transfers to and from
36  * memory and peripherals. The transfers occur independently of the CPU and can be triggered by
37  * software or hardware. Multiple channels can be active at the same time each with their own
38  * user-selectable priority and transfer characteristics.
39  *
40  * \section section_dma_features Features
41  * * CPU independent memory access
42  * * Access to memory and peripherals
43  * * Multiple independent channels
44  * * Configurable transer sizes and bursts
45  * * Configurable priorities
46  * * Event completion notification
47  *
48  * \section Usage Flow
49  * The operational flow of the driver is listed below. This shows the basic order in which each of
50  * the functions would generally be called. While Initialize must always be first and Release always
51  * last, with care, the other functions can be reordered based on the implementation needs.
52  * -# Initialize: \ref cyhal_dma_init or \ref cyhal_dma_init_adv or \ref cyhal_dma_init_cfg
53  * -# Configure: \ref cyhal_dma_configure
54  * -# Setup: \ref cyhal_dma_register_callback, \ref cyhal_dma_enable_event, \ref cyhal_dma_connect_digital, or \ref cyhal_dma_enable_output
55  * -# Enable: \ref cyhal_dma_enable
56  * -# Trigger: \ref cyhal_dma_start_transfer or via a hardware signal
57  * -# Status/ReEnable (optional): \ref cyhal_dma_is_busy, \ref cyhal_dma_enable
58  * -# Cleanup (optional): \ref cyhal_dma_disable, \ref cyhal_dma_enable_event, \ref cyhal_dma_disconnect_digital, or \ref cyhal_dma_disable_output
59  * -# Release (optional): \ref cyhal_dma_free
60  *
61  * \section section_dma_quickstart Quick Start
62  *
63  * See \ref subsection_dma_snippet_1 for a code snippet that sets up a DMA
64  * transfer to move memory from one location to another.
65  *
66  * \section section_dma_snippets Code snippets
67  * \note Error handling code has been intentionally left out of snippets to highlight API usage.
68  *
69  * \subsection subsection_dma_snippet_1 Snippet 1: Simple DMA initialization and transfer
70  * The following snippet initializes a DMA channel and uses it to transfer a a single block of memory.
71  * The DMA channel is reserved by calling \ref cyhal_dma_init. It then needs to be configured with
72  * \ref cyhal_dma_configure and then the transfer is started with \ref cyhal_dma_start_transfer.<br>
73  * If the DMA channel is not needed anymore, it can be released by calling \ref cyhal_dma_free
74  *
75  * \snippet hal_dma.c snippet_cyhal_dma_simple_init
76  *
77  *
78  * \subsection subsection_dma_snippet_2 Snippet 2: Configuring the DMA channel based on memory requirements
79  * \ref cyhal_dma_configure can be used after DMA initialization to handle a variety of memory layouts.
80  *
81  * \snippet hal_dma.c snippet_cyhal_dma_configure
82  *
83  *
84  * \subsection subsection_dma_snippet_3 Snippet 3: Interrupts and retriggering DMA transfers
85  * DMA events like transfer complete or error events can be used to trigger a callback function. <br>
86  * This snippet uses \ref cyhal_dma_configure to break the full transfer into multiple bursts. This
87  * allows higher priority items access to the memory bus if necessary while the DMA operation is still
88  * in progress. It then uses \ref cyhal_dma_enable_event() to enable the transfer complete event to
89  * trigger the callback function registered by \ref cyhal_dma_register_callback().
90  *
91  * \snippet hal_dma.c snippet_cyhal_dma_events
92  *
93  *
94  * \subsection subsection_dma_snippet_4 Snippet 4: Using hardware signals with DMA
95  * DMA operations can be initiated by a hardware signal, or initiate a hardware signal on completion.
96  * <br>This snippet shows how either can be done with a timer object.
97  * \note Not all devices have the same internal connections. As a result, it may not be possible to
98  * setup connections exactly as shown in the snippet on your device.
99  *
100  * In the first case, the DMA output signal (\ref cyhal_dma_enable_output) is used so that when the
101  * DMA operation complets it in turn causes the timer to run.
102  * <br>NOTE: The \ref cyhal_dma_init_adv can also be used insted of \ref cyhal_dma_enable_output to
103  * enable the output. The advantage of using init_adv is it makes sure the DMA instance that is
104  * allocated is able to connected to the specified signal.
105  *
106  * \snippet hal_dma.c snippet_cyhal_dma_triggers_output
107  *
108  * The second snippet shows how a timer overflow can be used to trigger a DMA operation. It uses
109  * \ref cyhal_dma_init_adv to setup the connection, but \ref cyhal_dma_connect_digital could be used
110  * instead; with the same note as above about ensuring a connection between instances.
111  *
112  * \snippet hal_dma.c snippet_cyhal_dma_triggers_input
113  *
114  *
115  * \subsection subsection_dma_snippet_5 Snippet 5: DMA transfers with D-cache
116  * If CPU D-cache is enabled, DMA transfers must be handled using cache management API when dealing with cacheable memory
117  * in order to maintain CPU data cache coherency.
118  * Regarding the CPU data cache coherence with DMA, the general rules are, <br>
119  * - Source and destination buffers must be cacheline aligned (__SCB_DCACHE_LINE_SIZE) <br>
120  * - D-cache of DMA descriptor and D-cache of source's buffers must be cleaned before a DMA transfer <br>
121  * - D-cache of destination buffer must be invalidated after a DMA transfer <br>
122  *
123  * The following snippet initializes a DMA channel and uses it to transfer a single block from one cacheable memory
124  * to another cacheable memory. Cleaning D-cache of DMA descriptor is done by calling \ref cyhal_dma_configure.
125  * Cleaning D-cache of source's buffer and Invalidating D-cache of destination's buffer should be done explicitly.
126  *
127  * Refer to \ref DCACHE_Management for more information.
128  *
129  * \snippet hal_dma.c snippet_cyhal_dma_with_dcache
130  */
131 
132 #pragma once
133 
134 #include <stdbool.h>
135 #include <stdint.h>
136 #include "cy_result.h"
137 #include "cyhal_hw_types.h"
138 
139 #if defined(__cplusplus)
140 extern "C" {
141 #endif
142 
143 /** \addtogroup group_hal_results_dma DMA HAL Results
144  *  DMA specific return codes
145  *  \ingroup group_hal_results
146  *  \{ *//**
147  */
148 
149 /** Invalid transfer width parameter error */
150 #define CYHAL_DMA_RSLT_ERR_INVALID_TRANSFER_WIDTH       \
151     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_DMA, 0))
152 /** Invalid parameter error */
153 #define CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER            \
154     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_DMA, 1))
155 /** Invalid priority parameter error */
156 #define CYHAL_DMA_RSLT_ERR_INVALID_PRIORITY             \
157     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_DMA, 2))
158 /** Invalid src or dst addr alignment error */
159 #define CYHAL_DMA_RSLT_ERR_INVALID_ALIGNMENT            \
160     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_DMA, 3))
161 /** Invalid burst_size paramenter error */
162 #define CYHAL_DMA_RSLT_ERR_INVALID_BURST_SIZE           \
163     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_DMA, 4))
164 /** Channel busy error */
165 #define CYHAL_DMA_RSLT_ERR_CHANNEL_BUSY                 \
166     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_DMA, 5))
167 /** Transfer has already been started warning */
168 #define CYHAL_DMA_RSLT_WARN_TRANSFER_ALREADY_STARTED    \
169     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_WARNING, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_DMA, 6))
170 /** Unsupported hardware error */
171 #define CYHAL_DMA_RSLT_FATAL_UNSUPPORTED_HARDWARE       \
172     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_FATAL, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_DMA, 7))
173 /** Requested transfer size is not supported */
174 #define CYHAL_DMA_RSLT_ERR_INVALID_TRANSFER_SIZE        \
175     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_FATAL, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_DMA, 8))
176 
177 /**
178  * \}
179  */
180 
181 /** Direction for DMA transfers. */
182 typedef enum
183 {
184     CYHAL_DMA_DIRECTION_MEM2MEM,       //!< Memory to memory
185     CYHAL_DMA_DIRECTION_MEM2PERIPH,    //!< Memory to peripheral
186     CYHAL_DMA_DIRECTION_PERIPH2MEM,    //!< Peripheral to memory
187     CYHAL_DMA_DIRECTION_PERIPH2PERIPH, //!< Peripheral to peripheral
188 } cyhal_dma_direction_t;
189 
190 /** Flags enum of DMA events. Multiple events can be enabled via \ref cyhal_dma_enable_event and
191  * the callback from \ref cyhal_dma_register_callback will be run to notify. */
192 typedef enum
193 {
194     CYHAL_DMA_NO_INTR             = 0,      //!< No interrupt
195     CYHAL_DMA_TRANSFER_COMPLETE   = 1 << 0, /**< Indicates that an individual transfer (burst or
196                                                  full) has completed based on the specified \ref
197                                                  cyhal_dma_transfer_action_t */
198     CYHAL_DMA_DESCRIPTOR_COMPLETE = 1 << 1, //!< Indicates that the full transfer has completed
199     CYHAL_DMA_SRC_BUS_ERROR       = 1 << 2, //!< Indicates that there is a source bus error
200     CYHAL_DMA_DST_BUS_ERROR       = 1 << 3, //!< Indicates that there is a destination bus error
201     CYHAL_DMA_SRC_MISAL           = 1 << 4, //!< Indicates that the source address is not aligned
202     CYHAL_DMA_DST_MISAL           = 1 << 5, //!< Indicates that the destination address is not aligned
203     CYHAL_DMA_CURR_PTR_NULL       = 1 << 6, //!< Indicates that the current descriptor pointer is null
204     CYHAL_DMA_ACTIVE_CH_DISABLED  = 1 << 7, //!< Indicates that the active channel is disabled
205     CYHAL_DMA_DESCR_BUS_ERROR     = 1 << 8, //!< Indicates that there has been a descriptor bus error
206 } cyhal_dma_event_t;
207 
208 /** Specifies the transfer type to trigger when an input signal is received. */
209 typedef enum
210 {
211     CYHAL_DMA_INPUT_TRIGGER_SINGLE_ELEMENT, //!< Transfer a single element when an input signal is received
212     CYHAL_DMA_INPUT_TRIGGER_SINGLE_BURST,   //!< Transfer a single burst when an input signal is received
213     CYHAL_DMA_INPUT_TRIGGER_ALL_ELEMENTS,   //!< Transfer all elements when an input signal is received
214 } cyhal_dma_input_t;
215 
216 /** Specifies the transfer completion event that triggers a signal output. */
217 typedef enum
218 {
219     CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_ELEMENT, //!< Trigger an output when a single element is transferred
220     CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_BURST,   //!< Trigger an output when a single burst is transferred
221     CYHAL_DMA_OUTPUT_TRIGGER_ALL_ELEMENTS,   //!< Trigger an output when all elements are transferred
222 } cyhal_dma_output_t;
223 
224 /** This defines the behavior of the the channel when transfers are initiated. It can specify both
225  * how the transfer is broken up and what happens at the end of the transfer.
226  * If burst_size from \ref cyhal_dma_cfg_t is used, this specifies the granularity of operations
227  * that occur. Using \ref CYHAL_DMA_TRANSFER_BURST or \ref CYHAL_DMA_TRANSFER_BURST_DISABLE means
228  * a single trigger will transfer a single burst (of burst_size) and raise the \ref
229  * CYHAL_DMA_TRANSFER_COMPLETE interrupt. Using \ref CYHAL_DMA_TRANSFER_FULL means a single trigger
230  * will transfer all bursts (total size length) and raise the \ref CYHAL_DMA_TRANSFER_COMPLETE
231  * interrupt. If burst_size is not used, this has no impact and a single trigger will perform a
232  * complete transfer and raise a single interrupt at the end.
233  * When the transfer is complete, the channel can be left enabled, or automatically disabled. When
234  * left enabled (\ref CYHAL_DMA_TRANSFER_BURST or \ref CYHAL_DMA_TRANSFER_FULL) subsequent triggers
235  * will re-start the transfers. If the channel is diabled on completion (\ref
236  * CYHAL_DMA_TRANSFER_BURST_DISABLE or \ref CYHAL_DMA_TRANSFER_FULL_DISABLE), \ref
237  * cyhal_dma_configure must be called to reconfigure the channel for future transfers.
238  *
239  * \note When using \ref cyhal_dma_connect_digital for a hardware input trigger, the
240  * \ref cyhal_dma_input_t argument defines how much of the transfer is initiated at a time. This
241  * enum will still define when interrupts are raised. */
242 typedef enum
243 {
244     /** A single burst is triggered and a \ref CYHAL_DMA_TRANSFER_COMPLETE will occur after
245      * each burst. The channel will be left enabled and can continue to be triggered. */
246     CYHAL_DMA_TRANSFER_BURST,
247     /** All bursts are triggered and a single \ref CYHAL_DMA_TRANSFER_COMPLETE will occur at
248      * the end. The channel will be left enabled and can continue to be triggered. */
249     CYHAL_DMA_TRANSFER_FULL,
250     /** A single burst is triggered and a \ref CYHAL_DMA_TRANSFER_COMPLETE will occur after
251      * each burst. When all bursts are complete, the channel will be disabled. */
252     CYHAL_DMA_TRANSFER_BURST_DISABLE,
253     /** All bursts are triggered and a single \ref CYHAL_DMA_TRANSFER_COMPLETE will occur at
254      * the end. When complete, the channel will be disabled. */
255     CYHAL_DMA_TRANSFER_FULL_DISABLE,
256 } cyhal_dma_transfer_action_t;
257 
258 /** \brief Configuration of a DMA channel. When configuring address,
259  * increments, and transfer width keep in mind your hardware may have more
260  * stringent address and data alignment requirements. */
261 typedef struct
262 {
263     uint32_t src_addr;                  //!< Source address. Some devices can apply special requirements for user data arrays. Please refer to implementation-specific documentation to see whether any limitations exist for used device.
264     int16_t  src_increment;             //!< Source address auto increment amount in multiples of transfer_width
265     uint32_t dst_addr;                  //!< Destination address. Some devices can apply special requirements for user data arrays. Please refer to implementation-specific documentation to see whether any limitations exist for used device.
266     int16_t  dst_increment;             //!< Destination address auto increment amount in multiples of transfer_width
267     uint8_t  transfer_width;            //!< Transfer width in bits. Valid values are: 8, 16, or 32
268     uint32_t length;                    //!< Number of elements to be transferred in total
269     uint32_t burst_size;                //!< Number of elements to be transferred per trigger. If set to 0 every element is transferred, otherwise burst_size must evenly divide length.
270     cyhal_dma_transfer_action_t action; //!< Sets the behavior of the channel when triggered (using start_transfer). Ignored if burst_size is not configured.
271 } cyhal_dma_cfg_t;
272 
273 /** Event handler for DMA interrupts */
274 typedef void (*cyhal_dma_event_callback_t)(void *callback_arg, cyhal_dma_event_t event);
275 
276 /** DMA input connection information to setup while initializing the driver. */
277 typedef struct
278 {
279     cyhal_source_t      source; //!< Source of signal to DMA; obtained from another driver's cyhal_<PERIPH>_enable_output
280     cyhal_dma_input_t   input;  //!< DMA input signal to be driven
281 } cyhal_dma_src_t;
282 
283 /** DMA output connection information to setup while initializing the driver. */
284 typedef struct
285 {
286     cyhal_dma_output_t  output; //!< Output signal of DMA
287     cyhal_dest_t        dest;   //!< Destination of DMA signal
288 } cyhal_dma_dest_t;
289 
290 /** Initialize the DMA peripheral.
291  *
292  * If a source signal is provided for \p src, this will connect the provided signal to the DMA
293  * just as would be done by calling \ref cyhal_dma_connect_digital. Similarly, if a destination
294  * target is provided for \p dest this will enable the specified output just as would be done
295  * by calling \ref cyhal_dma_enable_output.
296  * @param[out] obj  Pointer to a DMA object. The caller must allocate the memory
297  *  for this object but the init function will initialize its contents.
298  * @param[in]  src          An optional source signal to connect to the DMA
299  * @param[in]  dest         An optional destination signal to drive from the DMA
300  * @param[out] dest_source  An optional pointer to user-allocated source signal object which
301  * will be initialized by enable_output. If \p dest is non-null, this must also be non-null.
302  * \p dest_source should be passed to (dis)connect_digital functions to (dis)connect the
303  * associated endpoints.
304  * @param[in]  priority     The priority of this DMA operation relative to others. The number of
305  * priority levels which are supported is hardware dependent. All implementations define a
306  * #CYHAL_DMA_PRIORITY_DEFAULT constant which is always valid. If supported, implementations will
307  * also define #CYHAL_DMA_PRIORITY_HIGH, #CYHAL_DMA_PRIORITY_MEDIUM, and #CYHAL_DMA_PRIORITY_LOW.
308  * The behavior of any other value is implementation defined. See the implementation-specific DMA
309  * documentation for more details.
310  * @param[in]  direction    The direction memory is copied
311  * @return The status of the init request
312  */
313 cy_rslt_t cyhal_dma_init_adv(cyhal_dma_t *obj, cyhal_dma_src_t *src, cyhal_dma_dest_t *dest, cyhal_source_t *dest_source, uint8_t priority, cyhal_dma_direction_t direction);
314 
315 /** Initialize the DMA peripheral.
316  *
317  * @param[out] obj          Pointer to a DMA object. The caller must allocate the memory for this
318  * object but the init function will initialize its contents.
319  * @param[in]  priority     The priority of this DMA operation relative to others. The number of
320  * priority levels which are supported is hardware dependent. All implementations define a
321  * #CYHAL_DMA_PRIORITY_DEFAULT constant which is always valid. If supported, implementations will
322  * also define #CYHAL_DMA_PRIORITY_HIGH, #CYHAL_DMA_PRIORITY_MEDIUM, and #CYHAL_DMA_PRIORITY_LOW.
323  * The behavior of any other value is implementation defined. See the implementation-specific DMA
324  * documentation for more details.
325  * @param[in]  direction    The direction memory is copied
326  * @return The status of the init request
327  */
328 #define cyhal_dma_init(obj, priority, direction)    (cyhal_dma_init_adv(obj, NULL, NULL, NULL, priority, direction))
329 
330 /** Initialize the DMA peripheral using data provided by the configurator.
331  *
332  * \note Depending on what the configurator allows filling it, it is likely that at least the source
333  * and destination addresses of the transfer(s) still need to be setup.
334  *
335  * @param[out] obj  Pointer to a DMA object. The caller must allocate the memory for this
336  * object but the init function will initialize its contents.
337  * @param[in]  cfg  Configuration structure generated by a configurator.
338  * @return The status of the init request
339  */
340 cy_rslt_t cyhal_dma_init_cfg(cyhal_dma_t *obj, const cyhal_dma_configurator_t *cfg);
341 
342 /** Free the DMA object. Freeing a DMA object while a transfer is in progress
343  * (\ref cyhal_dma_is_busy) is invalid.
344  *
345  * @param[in,out] obj The DMA object
346  */
347 void cyhal_dma_free(cyhal_dma_t *obj);
348 
349 /** Setup the DMA channel behavior. This will also enable the channel to allow it to be triggered.
350  * The transfer can be software triggered by calling \ref cyhal_dma_start_transfer or by hardware.
351  * A hardware input signal is setup by \ref cyhal_dma_connect_digital or \ref cyhal_dma_init_adv.
352  * \note If hardware triggers are used, any necessary event callback setup (\ref
353  * cyhal_dma_register_callback and \ref cyhal_dma_enable_event) should be done before calling
354  * this function to ensure the handlers are in place before the transfer can happen.
355  * \note The automatic enablement of the channel as part of this function is expected to change
356  * in a future update. This would only happen on a new major release (eg: 1.0 -> 2.0).
357  * \note If the DMA was setup using \ref cyhal_dma_init_cfg, this function should not be used.
358  * \note If D-cache is enabled, this function cleans D-cache of DMA descriptor.
359  *
360  * @param[in] obj    The DMA object
361  * @param[in] cfg    Configuration parameters for the transfer
362  * @return The status of the configure request
363  */
364 cy_rslt_t cyhal_dma_configure(cyhal_dma_t *obj, const cyhal_dma_cfg_t *cfg);
365 
366 /** Enable the DMA transfer so that it can start transferring data when triggered. A trigger is
367  * caused either by calling \ref cyhal_dma_start_transfer or by hardware as a result of a connection
368  * made in either \ref cyhal_dma_connect_digital or \ref cyhal_dma_init_adv. The DMA can be disabled
369  * by calling \ref cyhal_dma_disable or by setting the \ref cyhal_dma_cfg_t action to \ref
370  * CYHAL_DMA_TRANSFER_BURST_DISABLE, or \ref CYHAL_DMA_TRANSFER_FULL_DISABLE.
371  *
372  * @param[in] obj    The DMA object
373  * @return The status of the enable request
374  */
375 cy_rslt_t cyhal_dma_enable(cyhal_dma_t *obj);
376 
377 /** Disable the DMA transfer so that it does not continue to trigger. It can be reenabled by calling
378  * \ref cyhal_dma_enable or \ref cyhal_dma_configure.
379  *
380  * @param[in] obj    The DMA object
381  * @return The status of the enable request
382  */
383 cy_rslt_t cyhal_dma_disable(cyhal_dma_t *obj);
384 
385 /** Initiates DMA channel transfer for specified DMA object. This should only be done after the
386  * channel has been configured (\ref cyhal_dma_configure) and any necessary event callbacks setup
387  * (\ref cyhal_dma_register_callback \ref cyhal_dma_enable_event)
388  *
389  * @param[in] obj    The DMA object
390  * @return The status of the start_transfer request
391  */
392 cy_rslt_t cyhal_dma_start_transfer(cyhal_dma_t *obj);
393 
394 /** Checks if the transfer has been triggered, but not yet complete (eg: is pending, blocked or running)
395  *
396  * @param[in] obj    The DMA object
397  * @return True if DMA channel is busy
398  */
399 bool cyhal_dma_is_busy(cyhal_dma_t *obj);
400 
401 /** Register a DMA callback handler.
402  *
403  * This function will be called when one of the events enabled by \ref cyhal_dma_enable_event occurs.
404  *
405  * @param[in] obj          The DMA object
406  * @param[in] callback     The callback handler which will be invoked when an event triggers
407  * @param[in] callback_arg Generic argument that will be provided to the callback when called
408  */
409 void cyhal_dma_register_callback(cyhal_dma_t *obj, cyhal_dma_event_callback_t callback, void *callback_arg);
410 
411 /** Configure DMA event enablement.
412  *
413  * When an enabled event occurs, the function specified by \ref cyhal_dma_register_callback will be called.
414  *
415  * @param[in] obj            The DMA object
416  * @param[in] event          The DMA event type
417  * @param[in] intr_priority  The priority for NVIC interrupt events. The priority from the most
418  * recent call will take precedence, i.e all events will have the same priority.
419  * @param[in] enable         True to turn on interrupts, False to turn off
420  */
421 void cyhal_dma_enable_event(cyhal_dma_t *obj, cyhal_dma_event_t event, uint8_t intr_priority, bool enable);
422 
423 /** Connects a source signal and enables the specified input to the DMA channel. This connection
424  * can also be setup automatically on initialization via \ref cyhal_dma_init_adv. If the signal
425  * needs to be disconnected later, \ref cyhal_dma_disconnect_digital can be used.
426  *
427  * @param[in] obj         The DMA object
428  * @param[in] source      Source signal obtained from another driver's cyhal_<PERIPH>_enable_output
429  * @param[in] input       Which input to enable
430  * @return The status of the connection
431  */
432 cy_rslt_t cyhal_dma_connect_digital(cyhal_dma_t *obj, cyhal_source_t source, cyhal_dma_input_t input);
433 
434 /** Enables the specified output signal from a DMA channel that is triggered when a transfer is
435  * completed. This can also be setup automatically on initialization via \ref cyhal_dma_init_adv.
436  * If the output is not needed in the future, \ref cyhal_dma_disable_output can be used.
437  *
438  * @param[in]  obj         The DMA object
439  * @param[in]  output      Which event triggers the output
440  * @param[out] source      Pointer to user-allocated source signal object which
441  * will be initialized by enable_output. \p source should be passed to
442  * (dis)connect_digital functions to (dis)connect the associated endpoints.
443  * @return The status of the output enable
444  */
445 cy_rslt_t cyhal_dma_enable_output(cyhal_dma_t *obj, cyhal_dma_output_t output, cyhal_source_t *source);
446 
447 /** Disconnects a source signal and disables the specified input to the DMA channel. This removes
448  * the connection that was established by either \ref cyhal_dma_init_adv or \ref
449  * cyhal_dma_connect_digital.
450  *
451  * @param[in] obj         The DMA object
452  * @param[in] source      Source signal from cyhal_<PERIPH>_enable_output to disable
453  * @param[in] input       Which input to disable
454  * @return The status of the disconnect
455  */
456 cy_rslt_t cyhal_dma_disconnect_digital(cyhal_dma_t *obj, cyhal_source_t source, cyhal_dma_input_t input);
457 
458 /** Disables the specified output signal from a DMA channel. This turns off the signal that was
459  * enabled by either \ref cyhal_dma_init_adv or \ref cyhal_dma_enable_output. It is recommended
460  * that the signal is disconnected (cyhal_<PERIPH>_disconnect_digital) from anything it might be
461  * driving before being disabled.
462  *
463  * @param[in]  obj         The DMA object
464  * @param[in]  output      Which output to disable
465  * @return The status of the disablement
466  * */
467 cy_rslt_t cyhal_dma_disable_output(cyhal_dma_t *obj, cyhal_dma_output_t output);
468 
469 #if defined(__cplusplus)
470 }
471 #endif
472 
473 #ifdef CYHAL_DMA_IMPL_HEADER
474 #include CYHAL_DMA_IMPL_HEADER
475 #endif /* CYHAL_DMA_IMPL_HEADER */
476 
477 /** \} group_hal_dma */
478