1 /***************************************************************************//**
2 * \file cyhal_dma_dmac.c
3 *
4 * \brief
5 * Implements a high level interface for interacting with the Infineon DMAC.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or
10 * an affiliate of Cypress Semiconductor Corporation
11 *
12 * SPDX-License-Identifier: Apache-2.0
13 *
14 * Licensed under the Apache License, Version 2.0 (the "License");
15 * you may not use this file except in compliance with the License.
16 * You may obtain a copy of the License at
17 *
18 * http://www.apache.org/licenses/LICENSE-2.0
19 *
20 * Unless required by applicable law or agreed to in writing, software
21 * distributed under the License is distributed on an "AS IS" BASIS,
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the License for the specific language governing permissions and
24 * limitations under the License.
25 *******************************************************************************/
26
27 #include "cyhal_dma.h"
28 #include "cyhal_dma_dmac.h"
29 #include "cyhal_dma_impl.h"
30 #include "cyhal_hwmgr_impl.h"
31 #include "cyhal_interconnect.h"
32 #include "cyhal_syspm.h"
33 #include "cyhal_utils.h"
34 #include "cyhal_triggers.h"
35
36 #if defined(__cplusplus)
37 extern "C" {
38 #endif
39
40 #if (_CYHAL_DRIVER_AVAILABLE_DMA_DMAC)
41
42 #if defined(CY_IP_M4CPUSS_DMAC)
43 #define DMAC0_IRQn (cpuss_interrupts_dmac_0_IRQn)
44 #define GET_RESOURCE_DATA(x) (x.dmac)
45 typedef DMAC_Type cyhal_dmac_hw_type;
46 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
47 #define DMAC0_IRQn (cpuss_interrupt_dma_IRQn)
48 #define GET_RESOURCE_DATA(x) (x)
49 #define CY_TRIGGER_TWO_CYCLES (2)
50 typedef DMAC_Type cyhal_dmac_hw_type;
51 #elif defined(CY_IP_MXAHBDMAC)
52 #define DMAC0_IRQn (cpuss_interrupts_dmac0_0_IRQn)
53 #define DMAC1_IRQn (cpuss_interrupts_dmac1_0_IRQn)
54 #define GET_RESOURCE_DATA(x) (x.dmac)
55 typedef MXAHBDMAC_Type cyhal_dmac_hw_type;
56 #endif
57
58 #if defined(CPUSS_DMAC0_CH_NR) && defined(CPUSS_DMAC1_CH_NR)
59 #define NUM_DMAC_CHANNELS (CPUSS_DMAC0_CH_NR + CPUSS_DMAC1_CH_NR)
60 #elif defined(CPUSS_DMAC_CH_NR)
61 #define NUM_DMAC_CHANNELS (CPUSS_DMAC_CH_NR)
62 #define CPUSS_DMAC0_CH_NR (CPUSS_DMAC_CH_NR)
63 #define CYHAL_TRIGGER_CPUSS_DMAC0_TR_IN0 (CYHAL_TRIGGER_CPUSS_DMAC_TR_IN0)
64 #define _CYHAL_TRIGGER_CPUSS_DMAC0_TR_OUT0 (_CYHAL_TRIGGER_CPUSS_DMAC_TR_OUT0)
65 #endif
66
67
68
69 static cyhal_dma_t* _cyhal_dma_dmac_config_structs[NUM_DMAC_CHANNELS];
70
71 /** Default dmac descriptor config */
72 static const cy_stc_dmac_descriptor_config_t _cyhal_dma_dmac_default_descriptor_config =
73 {
74 .srcAddress = 0, // Overriden by cyhal_dma_cfg_t.src_addr
75 .dstAddress = 0, // Overriden by cyhal_dma_cfg_t.dst_addr
76 .dataSize = CY_DMAC_WORD, // Overridden by cyhal_dma_cfg_t.transfer_width
77 .dstTransferSize = CY_DMAC_TRANSFER_SIZE_DATA, // Overriden by direction
78 .srcTransferSize = CY_DMAC_TRANSFER_SIZE_DATA, // Overriden by direction
79 .retrigger = CY_DMAC_RETRIG_IM,
80 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
81 .interruptType = CY_DMAC_DESCR, // Overridden by cyhal_dma_cfg_t.action
82 .triggerOutType = CY_DMAC_DESCR_CHAIN, // Overridden by [en/dis]able_output()
83 .channelState = CY_DMAC_CHANNEL_ENABLED,
84 .triggerInType = CY_DMAC_DESCR, // Overridden by cyhal_dma_cfg_t.action & [dis]connect_digital()
85 .dataPrefetch = false,
86 .descriptorType = CY_DMAC_1D_TRANSFER, // Overriden by cyhal_dma_cfg_t.burst_size
87 .srcXincrement = 1U, // Overriden by cyhal_dma_cfg_t.src_increment
88 .dstXincrement = 1U, // Overriden by cyhal_dma_cfg_t.dst_increment
89 .xCount = 1UL, // Overriden by cyhal_dma_cfg_t.length/burst_size
90 .srcYincrement = 0U, // Overriden by cyhal_dma_cfg_t.burst_size
91 .dstYincrement = 0U, // Overriden by cyhal_dma_cfg_t.burst_size
92 .yCount = 1UL, // Overriden by cyhal_dma_cfg_t.length
93 .nextDescriptor = 0,
94 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
95 .triggerType = CY_DMAC_SINGLE_DESCR,
96 .dataCount = 1, // Overriden by cyhal_dma_cfg_t.length
97 .dstAddrIncrement = true, // Overriden by cyhal_dma_cfg_t.dst_increment
98 .srcAddrIncrement = true, // Overriden by cyhal_dma_cfg_t.src_increment
99 .interrupt = true,
100 .preemptable = true,
101 .flipping = false,
102 #endif
103 };
104
105 /** Default dmac channel config */
106 static const cy_stc_dmac_channel_config_t _cyhal_dma_dmac_default_channel_config =
107 {
108 .priority = 1, // Overriden by config().priority
109 .enable = false,
110 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
111 .bufferable = false,
112 .descriptor = 0, // Overriden by config()
113 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
114 .descriptor = CY_DMAC_DESCRIPTOR_PING, // Overriden by config()
115 #endif
116 };
117
118 static bool _cyhal_dma_dmac_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg);
119
120 static cyhal_syspm_callback_data_t _cyhal_dma_dmac_pm_callback_args = {
121 .callback = &_cyhal_dma_dmac_pm_callback,
122 .states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE),
123 .next = NULL,
124 .args = NULL,
125 .ignore_modes = CYHAL_SYSPM_BEFORE_TRANSITION,
126 };
127 static bool _cyhal_dma_dmac_pm_transition_pending = false;
_cyhal_dma_dmac_has_enabled(void)128 static bool _cyhal_dma_dmac_has_enabled(void)
129 {
130 for (uint8_t i = 0; i < NUM_DMAC_CHANNELS; i++)
131 if (_cyhal_dma_dmac_config_structs[i])
132 return true;
133 return false;
134 }
135
_cyhal_dma_dmac_pm_callback(cyhal_syspm_callback_state_t state,cyhal_syspm_callback_mode_t mode,void * callback_arg)136 static bool _cyhal_dma_dmac_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
137 {
138 CY_UNUSED_PARAMETER(state);
139 CY_UNUSED_PARAMETER(callback_arg);
140 bool block_transition = false;
141 switch(mode)
142 {
143 case CYHAL_SYSPM_CHECK_READY:
144 for (uint8_t i = 0; (i < NUM_DMAC_CHANNELS) && !block_transition; i++)
145 {
146 block_transition |= (_cyhal_dma_dmac_config_structs[i] != NULL) && _cyhal_dma_dmac_is_busy(_cyhal_dma_dmac_config_structs[i]);
147 }
148 _cyhal_dma_dmac_pm_transition_pending = !block_transition;
149 break;
150 case CYHAL_SYSPM_CHECK_FAIL:
151 case CYHAL_SYSPM_AFTER_TRANSITION:
152 _cyhal_dma_dmac_pm_transition_pending = false;
153 break;
154 default:
155 CY_ASSERT(false);
156 break;
157 }
158 return _cyhal_dma_dmac_pm_transition_pending;
159 }
160
161 /** Gets the dmac configuration struct offset */
_cyhal_dma_dmac_get_cfg_offset(const cyhal_dma_t * obj)162 static inline uint8_t _cyhal_dma_dmac_get_cfg_offset(const cyhal_dma_t* obj)
163 {
164 return (obj->resource.block_num * CPUSS_DMAC0_CH_NR) + obj->resource.channel_num;
165 }
166
167 /** Sets the dmac configuration struct */
_cyhal_dma_dmac_set_obj(cyhal_dma_t * obj)168 static inline void _cyhal_dma_dmac_set_obj(cyhal_dma_t *obj)
169 {
170 _cyhal_dma_dmac_config_structs[_cyhal_dma_dmac_get_cfg_offset(obj)] = obj;
171 }
172
173 /** Zeros the dmac configuration struct */
_cyhal_dma_dmac_free_obj(cyhal_dma_t * obj)174 static inline void _cyhal_dma_dmac_free_obj(cyhal_dma_t *obj)
175 {
176 _cyhal_dma_dmac_config_structs[_cyhal_dma_dmac_get_cfg_offset(obj)] = NULL;
177 }
178
179 /** Gets the dmac configuration struct from block and channel */
_cyhal_dma_dmac_get_obj(uint8_t block,uint8_t channel)180 static inline cyhal_dma_t* _cyhal_dma_dmac_get_obj(uint8_t block, uint8_t channel)
181 {
182 return _cyhal_dma_dmac_config_structs[(block * CPUSS_DMAC0_CH_NR) + channel];
183 }
184
185 /** Gets the dmac block number from irq number */
186 /** This should never be called from a non-dma IRQn */
_cyhal_dma_dmac_get_block_from_irqn(IRQn_Type irqn)187 static inline uint8_t _cyhal_dma_dmac_get_block_from_irqn(IRQn_Type irqn)
188 {
189 uint8_t diff = irqn - DMAC0_IRQn;
190 #if defined(CPUSS_DMAC0_CH_NR) && !defined(CPUSS_DMAC1_CH_NR)
191 CY_ASSERT(diff < CPUSS_DMAC0_CH_NR);
192
193 if (diff < CPUSS_DMAC0_CH_NR)
194 return 0;
195 #elif defined(CPUSS_DMAC0_CH_NR) && defined(CPUSS_DMAC1_CH_NR)
196 CY_ASSERT(diff < CPUSS_DMAC0_CH_NR + CPUSS_DMAC1_CH_NR);
197
198 if (diff < CPUSS_DMAC0_CH_NR)
199 return 0;
200 if (diff < CPUSS_DMAC0_CH_NR + CPUSS_DMAC1_CH_NR)
201 return 1;
202 #endif
203
204 // Should never reach here. Just silencing compiler warnings.
205 CY_ASSERT(false);
206 return 0xFF;
207 }
208
209 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
210 /** Gets the dmac channel number from irq number */
211 /** This should never be called from a non-dma IRQn */
_cyhal_dma_dmac_get_channel_from_irqn(IRQn_Type irqn)212 static inline uint8_t _cyhal_dma_dmac_get_channel_from_irqn(IRQn_Type irqn)
213 {
214 uint8_t diff = irqn - DMAC0_IRQn;
215 #if defined(CPUSS_DMAC0_CH_NR) && !defined(CPUSS_DMAC1_CH_NR)
216 CY_ASSERT(diff < CPUSS_DMAC0_CH_NR);
217
218 if (diff < CPUSS_DMAC0_CH_NR)
219 return diff;
220 #elif defined(CPUSS_DMAC0_CH_NR) && defined(CPUSS_DMAC1_CH_NR)
221 CY_ASSERT(diff < CPUSS_DMAC0_CH_NR + CPUSS_DW1_CH_NR);
222
223 if (diff < CPUSS_DMAC0_CH_NR)
224 return diff;
225 else
226 return diff - CPUSS_DMAC0_CH_NR;
227 #endif
228
229 // Should never reach here. Just silencing compiler warnings.
230 CY_ASSERT(false);
231 return 0xFF;
232 }
233 #endif
234
235 /** Gets the irqn corresponding to a particular cyhal_dma_t config struct */
_cyhal_dma_dmac_get_irqn(cyhal_dma_t * obj)236 static inline IRQn_Type _cyhal_dma_dmac_get_irqn(cyhal_dma_t *obj)
237 {
238 #if defined(CY_IP_M0S8CPUSSV3_DMAC)
239 CY_UNUSED_PARAMETER(obj);
240 /* This IP has a single ganged IRQ for all DMA channels */
241 return DMAC0_IRQn;
242 #else
243 return (IRQn_Type)((uint8_t)DMAC0_IRQn + _cyhal_dma_dmac_get_cfg_offset(obj));
244 #endif
245 }
246
247 /** Gets the dmac base pointer from block number */
_cyhal_dma_dmac_get_base(uint8_t block_num)248 static inline cyhal_dmac_hw_type* _cyhal_dma_dmac_get_base(uint8_t block_num)
249 {
250 #if defined(CPUSS_DMAC0_CH_NR) && !defined(CPUSS_DMAC1_CH_NR)
251 CY_UNUSED_PARAMETER(block_num);
252 return DMAC;
253 #elif defined(CPUSS_DMAC0_CH_NR) && defined(CPUSS_DMAC1_CH_NR)
254 return (block_num == 0) ? MXAHBDMAC0 : MXAHBDMAC1;
255 #endif
256 }
257
258 /** Uses tables provided as part of the hal interconnect driver to determine mux
259 * trigger group and mux trigger index and then construct the trigger line
260 * input parameter to Cy_TrigMux_SwTrigger. */
_cyhal_dma_dmac_get_trigger_line(uint8_t block_num,uint8_t channel_num)261 static inline uint32_t _cyhal_dma_dmac_get_trigger_line(uint8_t block_num, uint8_t channel_num)
262 {
263 /* cyhal_dest_t triggers are guaranteed to be sorted by trigger type, block
264 * num, then channel num, therefore, we can just directly find the proper
265 * trigger by calculating an offset. */
266 cyhal_dest_t trigger = (cyhal_dest_t)(CYHAL_TRIGGER_CPUSS_DMAC0_TR_IN0 + (block_num * CPUSS_DMAC0_CH_NR) + channel_num);
267
268 /* One to one triggers have bit 8 set in cyhal_dest_to_mux but
269 * Cy_TrigMux_SwTrigger wants the trigger group field to have bit 5 set to
270 * denote one to one triggers. */
271 uint8_t trig_group = cyhal_dest_to_mux[trigger];
272 /* If hal one to one triggers bit is set: mask it out and set pdl one to
273 * one bit */
274 if(trig_group & _CYHAL_DMA_TRIGGERS_1TO1_MASK)
275 trig_group = (trig_group & ~_CYHAL_DMA_TRIGGERS_1TO1_MASK) | _CYHAL_DMA_PDL_TRIGGERS_1TO1_MASK;
276
277 /* Construct trigger line which consists of three fields packed into a
278 * uint32_t:
279 * Bits 30: Input/output bit. Set to 1 for output.
280 * Bits 12-8: Trigger group selection.
281 * Bits 7-0: Select the output trigger number in the trigger group. */
282 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
283 return PERI_TR_CMD_OUT_SEL_Msk | ((uint32_t)trig_group << 8) | cyhal_mux_dest_index[trigger];
284 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
285 return PERI_TR_CTL_TR_OUT_Msk | ((uint32_t)trig_group << 8) | cyhal_mux_dest_index[trigger];
286 #endif
287 }
288
289 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
290 /** Convert PDL interrupt cause to hal dma event */
_cyhal_dma_dmac_convert_interrupt_cause(cyhal_dma_t * obj,uint32_t cause)291 static inline cyhal_dma_event_t _cyhal_dma_dmac_convert_interrupt_cause(cyhal_dma_t *obj, uint32_t cause)
292 {
293 static const cyhal_dma_event_t hal[] =
294 {
295 CYHAL_DMA_TRANSFER_COMPLETE,
296 CYHAL_DMA_SRC_BUS_ERROR,
297 CYHAL_DMA_DST_BUS_ERROR,
298 CYHAL_DMA_SRC_MISAL,
299 CYHAL_DMA_DST_MISAL,
300 CYHAL_DMA_CURR_PTR_NULL,
301 CYHAL_DMA_ACTIVE_CH_DISABLED,
302 CYHAL_DMA_DESCR_BUS_ERROR
303 };
304
305 cyhal_dma_event_t hal_rslt = CYHAL_DMA_NO_INTR;
306 for (uint8_t i = 0; cause > 0 && i < sizeof(hal)/sizeof(cyhal_dma_event_t); i++)
307 {
308 if ((cause & (1 << i)) > 0)
309 hal_rslt |= hal[i];
310 }
311
312 if ((uint32_t)(hal_rslt & CYHAL_DMA_TRANSFER_COMPLETE) > 0 && obj->expected_bursts > 0)
313 {
314 obj->expected_bursts--;
315 if (0 == obj->expected_bursts)
316 {
317 hal_rslt |= CYHAL_DMA_DESCRIPTOR_COMPLETE;
318 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
319 obj->expected_bursts = (GET_RESOURCE_DATA(obj->descriptor_config).interruptType == CY_DMAC_X_LOOP)
320 ? GET_RESOURCE_DATA(obj->descriptor_config).yCount
321 : 1;
322 #else
323 obj->expected_bursts = 1;
324 #endif
325 }
326 }
327
328 return hal_rslt;
329 }
330 #endif
331
332 /** DMAC irq handler */
_cyhal_dma_dmac_irq_handler(void)333 static void _cyhal_dma_dmac_irq_handler(void)
334 {
335 /* Use irqn to get appropriate config structure */
336 uint8_t block = _cyhal_dma_dmac_get_block_from_irqn(_CYHAL_UTILS_GET_CURRENT_IRQN());
337 DMAC_Type* base = _cyhal_dma_dmac_get_base(block);
338 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
339 uint8_t channel = _cyhal_dma_dmac_get_channel_from_irqn(_CYHAL_UTILS_GET_CURRENT_IRQN());
340 cyhal_dma_t *obj = _cyhal_dma_dmac_get_obj(block, channel);
341
342 /* Get interrupt type and call users event callback if they have enabled that event */
343 uint32_t cause = Cy_DMAC_Channel_GetInterruptStatusMasked(base, channel);
344 cyhal_dma_event_t event_type = _cyhal_dma_dmac_convert_interrupt_cause(obj, cause);
345 uint32_t events_to_callback = event_type & obj->irq_cause;
346 if(obj->callback_data.callback != NULL && events_to_callback)
347 {
348 ((cyhal_dma_event_callback_t)obj->callback_data.callback)(obj->callback_data.callback_arg, (cyhal_dma_event_t)events_to_callback);
349 }
350
351 /* Clear all interrupts */
352 Cy_DMAC_Channel_ClearInterrupt(base, channel, CY_DMAC_INTR_MASK);
353 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
354 uint32_t channels = Cy_DMAC_GetInterruptStatusMasked(base);
355 for(int i = 0 ; ((uint32_t)(1 << i)) <= channels ; i++)
356 {
357 cyhal_dma_t *obj = _cyhal_dma_dmac_get_obj(block, i);
358 if (obj != NULL)
359 {
360 if (((channels & (1 << i)) != 0) && (obj->callback_data.callback != NULL))
361 {
362 ((cyhal_dma_event_callback_t)obj->callback_data.callback)(obj->callback_data.callback_arg, CYHAL_DMA_TRANSFER_COMPLETE);
363 }
364 }
365 }
366 Cy_DMAC_ClearInterrupt(_cyhal_dma_dmac_get_base(block), channels);
367 #endif
368 }
369
_cyhal_dma_dmac_get_src(uint8_t block_num,uint8_t channel_num)370 static cyhal_source_t _cyhal_dma_dmac_get_src(uint8_t block_num, uint8_t channel_num)
371 {
372 return (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE((_CYHAL_TRIGGER_CPUSS_DMAC0_TR_OUT0 + (block_num * CPUSS_DMAC0_CH_NR) + channel_num), CYHAL_SIGNAL_TYPE_EDGE);
373 }
374
_cyhal_dma_dmac_get_dest(uint8_t block_num,uint8_t channel_num)375 static cyhal_dest_t _cyhal_dma_dmac_get_dest(uint8_t block_num, uint8_t channel_num)
376 {
377 return (cyhal_dest_t)(CYHAL_TRIGGER_CPUSS_DMAC0_TR_IN0 + (block_num * CPUSS_DMAC0_CH_NR) + channel_num);
378 }
379
_cyhal_dma_dmac_stage(cyhal_dma_t * obj)380 static cy_rslt_t _cyhal_dma_dmac_stage(cyhal_dma_t *obj)
381 {
382 cyhal_dmac_hw_type* base = _cyhal_dma_dmac_get_base(obj->resource.block_num);
383 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
384 cy_rslt_t rslt = Cy_DMAC_Descriptor_Init(GET_RESOURCE_DATA(&obj->descriptor), GET_RESOURCE_DATA(&obj->descriptor_config));
385 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
386 cy_rslt_t rslt = Cy_DMAC_Descriptor_Init(base, obj->resource.channel_num, obj->descriptor, GET_RESOURCE_DATA(&obj->descriptor_config));
387 #endif
388 if(CY_DMAC_SUCCESS != rslt)
389 return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
390
391 /* Setup channel and enable */
392 if(CY_DMAC_SUCCESS != Cy_DMAC_Channel_Init(base, obj->resource.channel_num, GET_RESOURCE_DATA(&obj->channel_config)))
393 return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
394
395
396 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
397 Cy_DMAC_Channel_SetInterruptMask(base, obj->resource.channel_num, CY_DMAC_INTR_MASK);
398 #endif
399
400 Cy_DMAC_Enable(base);
401
402 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
403 /* src_misal and dst_misal interrupts are triggered immediately on enable
404 * so return those errors here */
405 uint32_t status = Cy_DMAC_Channel_GetInterruptStatus(base, obj->resource.channel_num);
406 if((status & CY_DMAC_INTR_SRC_MISAL) ||
407 (status & CY_DMAC_INTR_DST_MISAL))
408 {
409 /* Clear all interrupts and return error */
410 Cy_DMAC_Channel_ClearInterrupt(base, obj->resource.channel_num, CY_DMAC_INTR_MASK);
411 return CYHAL_DMA_RSLT_ERR_INVALID_ALIGNMENT;
412 }
413 #endif
414
415 /* Enable interrupt for this channel; preserve user priority if they enabled an interrupt */
416 IRQn_Type irqn = _cyhal_dma_dmac_get_irqn(obj);
417 uint32_t priority = (CYHAL_DMA_NO_INTR == obj->irq_cause)
418 ? CYHAL_ISR_PRIORITY_DEFAULT
419 : NVIC_GetPriority(irqn);
420
421 cy_stc_sysint_t irqCfg = { irqn, priority };
422 if(CY_SYSINT_SUCCESS != Cy_SysInt_Init(&irqCfg, _cyhal_dma_dmac_irq_handler))
423 return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
424 NVIC_EnableIRQ(irqCfg.intrSrc);
425
426 return CY_RSLT_SUCCESS;
427 }
428
_cyhal_dma_dmac_init(cyhal_dma_t * obj,cyhal_source_t * src,cyhal_dest_t * dest,uint8_t priority)429 cy_rslt_t _cyhal_dma_dmac_init(cyhal_dma_t *obj, cyhal_source_t *src, cyhal_dest_t *dest, uint8_t priority)
430 {
431 if(!CY_DMAC_IS_PRIORITY_VALID(priority))
432 return CYHAL_DMA_RSLT_ERR_INVALID_PRIORITY;
433
434 if (_cyhal_dma_dmac_pm_transition_pending)
435 {
436 return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
437 }
438
439 cy_rslt_t rslt = _cyhal_hwmgr_allocate_with_connection(
440 CYHAL_RSC_DMA, src, dest, _cyhal_dma_dmac_get_src, _cyhal_dma_dmac_get_dest, &obj->resource);
441 if(rslt != CY_RSLT_SUCCESS)
442 return rslt;
443
444 obj->callback_data.callback = NULL;
445
446 /* Setup descriptor and channel configs */
447 GET_RESOURCE_DATA(obj->descriptor_config) = _cyhal_dma_dmac_default_descriptor_config;
448 GET_RESOURCE_DATA(obj->channel_config) = _cyhal_dma_dmac_default_channel_config;
449 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
450 GET_RESOURCE_DATA(obj->channel_config).descriptor = GET_RESOURCE_DATA(&obj->descriptor);
451 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
452 obj->descriptor = obj->channel_config.descriptor;
453 #endif
454 GET_RESOURCE_DATA(obj->channel_config).priority = priority;
455
456 if (!_cyhal_dma_dmac_has_enabled())
457 {
458 _cyhal_syspm_register_peripheral_callback(&_cyhal_dma_dmac_pm_callback_args);
459 }
460
461 _cyhal_dma_dmac_set_obj(obj);
462
463 return CY_RSLT_SUCCESS;
464 }
465
_cyhal_dma_dmac_init_cfg(cyhal_dma_t * obj,const cyhal_dma_configurator_t * cfg)466 cy_rslt_t _cyhal_dma_dmac_init_cfg(cyhal_dma_t *obj, const cyhal_dma_configurator_t *cfg)
467 {
468 if (_cyhal_dma_dmac_pm_transition_pending)
469 {
470 return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
471 }
472
473 obj->resource = *(cfg->resource);
474 obj->callback_data.callback = NULL;
475
476 /* Setup descriptor and channel configs */
477 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
478 obj->descriptor_config.dmac = *(cfg->dmac_descriptor_config);
479 obj->channel_config.dmac = *(cfg->dmac_channel_config);
480 GET_RESOURCE_DATA(obj->channel_config).descriptor = GET_RESOURCE_DATA(&obj->descriptor);
481 obj->expected_bursts = cfg->dmac_descriptor_config->yCount;
482 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
483 obj->descriptor_config = *(cfg->descriptor_config);
484 obj->channel_config = *(cfg->channel_config);
485 obj->descriptor = obj->channel_config.descriptor;
486 obj->expected_bursts = 1;
487 #endif
488
489 if (!_cyhal_dma_dmac_has_enabled())
490 {
491 _cyhal_syspm_register_peripheral_callback(&_cyhal_dma_dmac_pm_callback_args);
492 }
493
494 _cyhal_dma_dmac_set_obj(obj);
495
496 return _cyhal_dma_dmac_stage(obj);
497 }
498
_cyhal_dma_dmac_free(cyhal_dma_t * obj)499 void _cyhal_dma_dmac_free(cyhal_dma_t *obj)
500 {
501 cyhal_dmac_hw_type* base = _cyhal_dma_dmac_get_base(obj->resource.block_num);
502 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
503 Cy_DMAC_Descriptor_DeInit(GET_RESOURCE_DATA(&obj->descriptor));
504 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
505 Cy_DMAC_Descriptor_DeInit(base, obj->resource.channel_num, obj->descriptor);
506 #endif
507
508 Cy_DMAC_Channel_DeInit(base, obj->resource.channel_num);
509
510 NVIC_DisableIRQ(_cyhal_dma_dmac_get_irqn(obj));
511
512 _cyhal_dma_dmac_free_obj(obj);
513
514 if (!_cyhal_dma_dmac_has_enabled())
515 {
516 _cyhal_syspm_unregister_peripheral_callback(&_cyhal_dma_dmac_pm_callback_args);
517 _cyhal_dma_dmac_pm_transition_pending = false;
518 }
519 }
520
521 /* Initialize descriptor, initialize channel, enable channel, enable channel
522 * interrupt, and enable DMAC controller */
_cyhal_dma_dmac_configure(cyhal_dma_t * obj,const cyhal_dma_cfg_t * cfg)523 cy_rslt_t _cyhal_dma_dmac_configure(cyhal_dma_t *obj, const cyhal_dma_cfg_t *cfg)
524 {
525 /* Do not reconfigure if transfer is pending/active already */
526 if(_cyhal_dma_dmac_is_busy(obj))
527 return CYHAL_DMA_RSLT_ERR_CHANNEL_BUSY;
528
529 // DMAC only supports <=65536 byte burst and <=65536 bytes per burst
530 if ((cfg->burst_size > 65536) ||
531 ((cfg->burst_size <= 1) && (cfg->length > 65536)) ||
532 ((cfg->burst_size > 0) && (cfg->length > (cfg->burst_size * 65536))))
533 return CYHAL_DMA_RSLT_ERR_INVALID_TRANSFER_SIZE;
534
535 #if defined(CY_IP_M0S8CPUSSV3_DMAC)
536 // PSoC™ 4 devices do not support automatically disabling the channel on completion
537 if ((cfg->action == CYHAL_DMA_TRANSFER_BURST_DISABLE) ||
538 (cfg->action == CYHAL_DMA_TRANSFER_FULL_DISABLE))
539 {
540 return CYHAL_DMA_RSLT_FATAL_UNSUPPORTED_HARDWARE;
541 }
542 #endif
543
544 GET_RESOURCE_DATA(obj->descriptor_config).srcAddress = (void*)cfg->src_addr;
545 GET_RESOURCE_DATA(obj->descriptor_config).dstAddress = (void*)cfg->dst_addr;
546
547 if(cfg->transfer_width == 8)
548 GET_RESOURCE_DATA(obj->descriptor_config).dataSize = CY_DMAC_BYTE;
549 else if(cfg->transfer_width == 16)
550 GET_RESOURCE_DATA(obj->descriptor_config).dataSize = CY_DMAC_HALFWORD;
551 else if(cfg->transfer_width == 32)
552 GET_RESOURCE_DATA(obj->descriptor_config).dataSize = CY_DMAC_WORD;
553 else
554 return CYHAL_DMA_RSLT_ERR_INVALID_TRANSFER_WIDTH;
555
556 /* By default, transfer what the user set for dataSize. However, if transfering between memory
557 * and a peripheral, make sure the peripheral access is using words. */
558 GET_RESOURCE_DATA(obj->descriptor_config).srcTransferSize =
559 GET_RESOURCE_DATA(obj->descriptor_config).dstTransferSize = CY_DMAC_TRANSFER_SIZE_DATA;
560 if (obj->direction == CYHAL_DMA_DIRECTION_PERIPH2MEM)
561 GET_RESOURCE_DATA(obj->descriptor_config).srcTransferSize = CY_DMAC_TRANSFER_SIZE_WORD;
562 else if (obj->direction == CYHAL_DMA_DIRECTION_MEM2PERIPH)
563 GET_RESOURCE_DATA(obj->descriptor_config).dstTransferSize = CY_DMAC_TRANSFER_SIZE_WORD;
564
565 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
566 GET_RESOURCE_DATA(obj->descriptor_config).nextDescriptor = GET_RESOURCE_DATA(&obj->descriptor);
567 if ((cfg->action == CYHAL_DMA_TRANSFER_BURST) || (cfg->action == CYHAL_DMA_TRANSFER_FULL))
568 {
569 GET_RESOURCE_DATA(obj->descriptor_config).channelState = CY_DMAC_CHANNEL_ENABLED;
570 }
571 else
572 {
573 GET_RESOURCE_DATA(obj->descriptor_config).channelState = CY_DMAC_CHANNEL_DISABLED;
574 }
575
576 GET_RESOURCE_DATA(obj->descriptor_config).srcXincrement = cfg->src_increment;
577 GET_RESOURCE_DATA(obj->descriptor_config).dstXincrement = cfg->dst_increment;
578
579 /* Setup 2D transfer if burst_size is being used otherwise set up 1D
580 * transfer */
581 if(cfg->burst_size != 0)
582 {
583 /* Length must be a multiple of burst_size */
584 if(cfg->length % cfg->burst_size != 0)
585 return CYHAL_DMA_RSLT_ERR_INVALID_BURST_SIZE;
586
587 GET_RESOURCE_DATA(obj->descriptor_config).descriptorType = CY_DMAC_2D_TRANSFER;
588 GET_RESOURCE_DATA(obj->descriptor_config).xCount = cfg->burst_size;
589 GET_RESOURCE_DATA(obj->descriptor_config).yCount = cfg->length / cfg->burst_size;
590 GET_RESOURCE_DATA(obj->descriptor_config).srcYincrement = cfg->src_increment * cfg->burst_size;
591 GET_RESOURCE_DATA(obj->descriptor_config).dstYincrement = cfg->dst_increment * cfg->burst_size;
592 }
593 else
594 {
595 GET_RESOURCE_DATA(obj->descriptor_config).descriptorType = CY_DMAC_1D_TRANSFER;
596 GET_RESOURCE_DATA(obj->descriptor_config).xCount = cfg->length;
597 }
598
599 /* If burst action, configure trigger and interrupt actions */
600 if (cfg->burst_size != 0 &&
601 (cfg->action == CYHAL_DMA_TRANSFER_BURST || cfg->action == CYHAL_DMA_TRANSFER_BURST_DISABLE))
602 {
603 obj->expected_bursts = GET_RESOURCE_DATA(obj->descriptor_config).yCount;
604 GET_RESOURCE_DATA(obj->descriptor_config).interruptType = CY_DMAC_X_LOOP;
605 if (obj->source == CYHAL_TRIGGER_CPUSS_ZERO) // If not overridden by connect_digital()
606 GET_RESOURCE_DATA(obj->descriptor_config).triggerInType = CY_DMAC_X_LOOP;
607 }
608 else
609 {
610 obj->expected_bursts = 1;
611 GET_RESOURCE_DATA(obj->descriptor_config).interruptType = CY_DMAC_DESCR;
612 if (obj->source == CYHAL_TRIGGER_CPUSS_ZERO) // If not overridden by connect_digital()
613 GET_RESOURCE_DATA(obj->descriptor_config).triggerInType = CY_DMAC_DESCR;
614 }
615 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
616 if(cfg->burst_size != 0)
617 {
618 return CYHAL_DMA_RSLT_ERR_INVALID_BURST_SIZE;
619 }
620 else
621 {
622 GET_RESOURCE_DATA(obj->descriptor_config).dataCount = cfg->length;
623 GET_RESOURCE_DATA(obj->descriptor_config).srcAddrIncrement = cfg->src_increment;
624 GET_RESOURCE_DATA(obj->descriptor_config).dstAddrIncrement = cfg->dst_increment;
625 obj->expected_bursts = 1;
626 }
627 #endif
628
629 return _cyhal_dma_dmac_stage(obj);
630 }
631
_cyhal_dma_dmac_enable(cyhal_dma_t * obj)632 cy_rslt_t _cyhal_dma_dmac_enable(cyhal_dma_t *obj)
633 {
634 cyhal_dmac_hw_type* base = _cyhal_dma_dmac_get_base(obj->resource.block_num);
635 Cy_DMAC_Channel_Enable(base, obj->resource.channel_num);
636 return CY_RSLT_SUCCESS;
637 }
638
_cyhal_dma_dmac_disable(cyhal_dma_t * obj)639 cy_rslt_t _cyhal_dma_dmac_disable(cyhal_dma_t *obj)
640 {
641 cyhal_dmac_hw_type* base = _cyhal_dma_dmac_get_base(obj->resource.block_num);
642 Cy_DMAC_Channel_Disable(base, obj->resource.channel_num);
643 return CY_RSLT_SUCCESS;
644 }
645
_cyhal_dma_dmac_start_transfer(cyhal_dma_t * obj)646 cy_rslt_t _cyhal_dma_dmac_start_transfer(cyhal_dma_t *obj)
647 {
648 /* Return warning if channel is busy */
649 if(_cyhal_dma_dmac_is_busy(obj))
650 return CYHAL_DMA_RSLT_WARN_TRANSFER_ALREADY_STARTED;
651
652 if (_cyhal_dma_dmac_pm_transition_pending)
653 return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
654
655 uint32_t trigline = _cyhal_dma_dmac_get_trigger_line(obj->resource.block_num, obj->resource.channel_num);
656 cy_en_trigmux_status_t trig_status = Cy_TrigMux_SwTrigger(trigline, CY_TRIGGER_TWO_CYCLES);
657
658 /* Also return warning if SW trigger is already initiated but DMA hardware
659 * has not seen it yet */
660 if(trig_status == CY_TRIGMUX_INVALID_STATE)
661 return CYHAL_DMA_RSLT_WARN_TRANSFER_ALREADY_STARTED;
662 else
663 return CY_RSLT_SUCCESS;
664 }
665
_cyhal_dma_dmac_enable_event(cyhal_dma_t * obj,cyhal_dma_event_t event,uint8_t intr_priority,bool enable)666 void _cyhal_dma_dmac_enable_event(cyhal_dma_t *obj, cyhal_dma_event_t event, uint8_t intr_priority, bool enable)
667 {
668 #if defined (CY_IP_M0S8CPUSSV3_DMAC)
669 DMAC_Type *base = _cyhal_dma_dmac_get_base(obj->resource.block_num);
670 uint32_t mask = Cy_DMAC_GetInterruptMask(base);
671 #endif
672 if(enable)
673 {
674 #if defined (CY_IP_M0S8CPUSSV3_DMAC)
675 Cy_DMAC_SetInterruptMask(base, mask | (1 << obj->resource.channel_num));
676 #endif
677 obj->irq_cause |= event;
678 }
679 else
680 {
681 #if defined (CY_IP_M0S8CPUSSV3_DMAC)
682 Cy_DMAC_SetInterruptMask(base, mask & ~(1 << obj->resource.channel_num));
683 #endif
684 obj->irq_cause &= ~event;
685 }
686
687 NVIC_SetPriority(_cyhal_dma_dmac_get_irqn(obj), intr_priority);
688 }
689
_cyhal_dma_dmac_is_busy(cyhal_dma_t * obj)690 bool _cyhal_dma_dmac_is_busy(cyhal_dma_t *obj)
691 {
692 /* The value is a bit field of all pending or active channels */
693 return Cy_DMAC_GetActiveChannel(_cyhal_dma_dmac_get_base(obj->resource.block_num)) & (1 << obj->resource.channel_num);
694 }
695
696 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
_cyhal_convert_input_t(cyhal_dma_input_t input)697 static cy_en_dmac_trigger_type_t _cyhal_convert_input_t(cyhal_dma_input_t input)
698 {
699 switch(input)
700 {
701 case CYHAL_DMA_INPUT_TRIGGER_SINGLE_ELEMENT:
702 return CY_DMAC_1ELEMENT;
703 case CYHAL_DMA_INPUT_TRIGGER_SINGLE_BURST:
704 return CY_DMAC_X_LOOP;
705 case CYHAL_DMA_INPUT_TRIGGER_ALL_ELEMENTS:
706 return CY_DMAC_DESCR;
707 default:
708 // Should never reach here. Just silencing compiler warnings.
709 CY_ASSERT(false);
710 return CY_DMAC_DESCR;
711 }
712 }
713
_cyhal_convert_output_t(cyhal_dma_output_t output)714 static cy_en_dmac_trigger_type_t _cyhal_convert_output_t(cyhal_dma_output_t output)
715 {
716 switch(output)
717 {
718 case CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_ELEMENT:
719 return CY_DMAC_1ELEMENT;
720 case CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_BURST:
721 return CY_DMAC_X_LOOP;
722 case CYHAL_DMA_OUTPUT_TRIGGER_ALL_ELEMENTS:
723 return CY_DMAC_DESCR;
724 default:
725 // Should never reach here. Just silencing compiler warnings.
726 CY_ASSERT(false);
727 return CY_DMAC_DESCR;
728 }
729 }
730
_cyhal_dma_dmac_connect_digital(cyhal_dma_t * obj,cyhal_source_t source,cyhal_dma_input_t input)731 cy_rslt_t _cyhal_dma_dmac_connect_digital(cyhal_dma_t *obj, cyhal_source_t source, cyhal_dma_input_t input)
732 {
733 if(input != CYHAL_DMA_INPUT_TRIGGER_SINGLE_ELEMENT &&
734 input != CYHAL_DMA_INPUT_TRIGGER_SINGLE_BURST &&
735 input != CYHAL_DMA_INPUT_TRIGGER_ALL_ELEMENTS)
736 return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
737
738 obj->descriptor_config.dmac.triggerInType = _cyhal_convert_input_t(input);
739 Cy_DMAC_Channel_Disable(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num);
740 obj->descriptor.dmac.ctl &= ~DMAC_CH_V2_DESCR_CTL_TR_IN_TYPE_Msk;
741 obj->descriptor.dmac.ctl |= _VAL2FLD(DMAC_CH_V2_DESCR_CTL_TR_IN_TYPE, obj->descriptor_config.dmac.triggerInType);
742 Cy_DMAC_Channel_Enable(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num);
743
744 cyhal_dest_t dest = _cyhal_dma_dmac_get_dest(obj->resource.block_num, obj->resource.channel_num);
745
746 return _cyhal_connect_signal(source, dest);
747 }
748
_cyhal_dma_dmac_enable_output(cyhal_dma_t * obj,cyhal_dma_output_t output,cyhal_source_t * source)749 cy_rslt_t _cyhal_dma_dmac_enable_output(cyhal_dma_t *obj, cyhal_dma_output_t output, cyhal_source_t *source)
750 {
751 if(output != CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_ELEMENT &&
752 output != CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_BURST &&
753 output != CYHAL_DMA_OUTPUT_TRIGGER_ALL_ELEMENTS)
754 return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
755
756 Cy_DMAC_Channel_Disable(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num);
757 obj->descriptor.dmac.ctl &= ~DMAC_CH_V2_DESCR_CTL_TR_OUT_TYPE_Msk;
758 obj->descriptor.dmac.ctl |= _VAL2FLD(DMAC_CH_V2_DESCR_CTL_TR_OUT_TYPE, _cyhal_convert_output_t(output));
759 Cy_DMAC_Channel_Enable(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num);
760
761 *source = _cyhal_dma_dmac_get_src(obj->resource.block_num, obj->resource.channel_num);
762
763 return CY_RSLT_SUCCESS;
764 }
765
_cyhal_dma_dmac_disconnect_digital(cyhal_dma_t * obj,cyhal_source_t source,cyhal_dma_input_t input)766 cy_rslt_t _cyhal_dma_dmac_disconnect_digital(cyhal_dma_t *obj, cyhal_source_t source, cyhal_dma_input_t input)
767 {
768 if(input != CYHAL_DMA_INPUT_TRIGGER_SINGLE_ELEMENT &&
769 input != CYHAL_DMA_INPUT_TRIGGER_SINGLE_BURST &&
770 input != CYHAL_DMA_INPUT_TRIGGER_ALL_ELEMENTS)
771 return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
772
773 Cy_DMAC_Channel_Disable(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num);
774
775 // There is no option to totally disable. Just reset to default.
776 // NOTE: Use .interruptType since it matches the desired .triggerInType from configure(), but
777 // is not modified by connect/disconnect functions
778 obj->descriptor.dmac.ctl &= ~DMAC_CH_V2_DESCR_CTL_TR_IN_TYPE_Msk;
779 obj->descriptor.dmac.ctl |= _VAL2FLD(DMAC_CH_V2_DESCR_CTL_TR_IN_TYPE, _cyhal_dma_dmac_default_descriptor_config.interruptType);
780
781 Cy_DMAC_Channel_Enable(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num);
782
783 cyhal_dest_t dest = _cyhal_dma_dmac_get_dest(obj->resource.block_num, obj->resource.channel_num);
784
785 return _cyhal_disconnect_signal(source, dest);
786 }
787
_cyhal_dma_dmac_disable_output(cyhal_dma_t * obj,cyhal_dma_output_t output)788 cy_rslt_t _cyhal_dma_dmac_disable_output(cyhal_dma_t *obj, cyhal_dma_output_t output)
789 {
790 if(output != CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_ELEMENT &&
791 output != CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_BURST &&
792 output != CYHAL_DMA_OUTPUT_TRIGGER_ALL_ELEMENTS)
793 return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
794
795 Cy_DMAC_Channel_Disable(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num);
796
797 // There is no option to totally disable. Just reset to default.
798 obj->descriptor.dmac.ctl &= ~DMAC_CH_V2_DESCR_CTL_TR_OUT_TYPE_Msk;
799 obj->descriptor.dmac.ctl |= _VAL2FLD(DMAC_CH_V2_DESCR_CTL_TR_OUT_TYPE, _cyhal_dma_dmac_default_descriptor_config.triggerOutType);
800
801 Cy_DMAC_Channel_Enable(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num);
802
803 return CY_RSLT_SUCCESS;
804
805 }
806 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
807
_cyhal_dma_dmac_connect_digital(cyhal_dma_t * obj,cyhal_source_t source,cyhal_dma_input_t input)808 cy_rslt_t _cyhal_dma_dmac_connect_digital(cyhal_dma_t *obj, cyhal_source_t source, cyhal_dma_input_t input)
809 {
810 if((input != CYHAL_DMA_INPUT_TRIGGER_SINGLE_ELEMENT) &&
811 (input != CYHAL_DMA_INPUT_TRIGGER_ALL_ELEMENTS))
812 return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
813
814 Cy_DMAC_Channel_SetCurrentDescriptor(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num, obj->descriptor);
815
816 cyhal_dest_t dest = (cyhal_dest_t)(CYHAL_TRIGGER_CPUSS_DMAC0_TR_IN0 + obj->resource.channel_num);
817
818 return _cyhal_connect_signal(source, dest);
819 }
820
821 // M0S8 output triggers are always active. This is a noop except to return the source.
_cyhal_dma_dmac_enable_output(cyhal_dma_t * obj,cyhal_dma_output_t output,cyhal_source_t * source)822 cy_rslt_t _cyhal_dma_dmac_enable_output(cyhal_dma_t *obj, cyhal_dma_output_t output, cyhal_source_t *source)
823 {
824 if((output != CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_ELEMENT) &&
825 (output != CYHAL_DMA_OUTPUT_TRIGGER_ALL_ELEMENTS))
826 return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
827
828 *source = _cyhal_dma_dmac_get_src(obj->resource.block_num, obj->resource.channel_num);
829
830 return CY_RSLT_SUCCESS;
831 }
832
_cyhal_dma_dmac_disconnect_digital(cyhal_dma_t * obj,cyhal_source_t source,cyhal_dma_input_t input)833 cy_rslt_t _cyhal_dma_dmac_disconnect_digital(cyhal_dma_t *obj, cyhal_source_t source, cyhal_dma_input_t input)
834 {
835 if((input != CYHAL_DMA_INPUT_TRIGGER_SINGLE_ELEMENT) &&
836 (input != CYHAL_DMA_INPUT_TRIGGER_ALL_ELEMENTS))
837 return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
838
839 // Reset to default
840 Cy_DMAC_Channel_SetCurrentDescriptor(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num, obj->descriptor);
841
842 cyhal_dest_t dest = (cyhal_dest_t)(CYHAL_TRIGGER_CPUSS_DMAC0_TR_IN0 + obj->resource.channel_num);
843
844 return _cyhal_disconnect_signal(source, dest);
845 }
846
847 // M0S8 output triggers are always active. This is a noop.
_cyhal_dma_dmac_disable_output(cyhal_dma_t * obj,cyhal_dma_output_t output)848 cy_rslt_t _cyhal_dma_dmac_disable_output(cyhal_dma_t *obj, cyhal_dma_output_t output)
849 {
850 CY_UNUSED_PARAMETER(obj);
851
852 if((output != CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_ELEMENT) &&
853 (output != CYHAL_DMA_OUTPUT_TRIGGER_ALL_ELEMENTS))
854 return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
855
856 return CY_RSLT_SUCCESS;
857 }
858
859 #endif /* defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC) */
860
861 #endif /* (_CYHAL_DRIVER_AVAILABLE_DMA_DMAC) */
862
863 #if defined(__cplusplus)
864 }
865 #endif
866