S32 SDK
edma_driver.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * THIS SOFTWARE IS PROVIDED BY NXP "AS IS" AND ANY EXPRESSED OR
7  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
8  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
9  * IN NO EVENT SHALL NXP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
10  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
12  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
14  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
15  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
16  * THE POSSIBILITY OF SUCH DAMAGE.
17  */
18 
49 #include "edma_irq.h"
50 #include "clock_manager.h"
51 #include "interrupt_manager.h"
52 
53 /*******************************************************************************
54  * Variables
55  ******************************************************************************/
56 
59 
62 
65 
67 #if defined FEATURE_EDMA_HAS_ERROR_IRQ
68 static const IRQn_Type s_edmaErrIrqId[FEATURE_ERROR_INTERRUPT_LINES] = DMA_ERROR_IRQS;
69 #endif
70 
74 
76 static edma_state_t *s_edma = NULL;
77 
78 /*******************************************************************************
79  * PROTOTYPES
80  ******************************************************************************/
81 static status_t EDMA_DRV_RequestChannel(uint8_t requestedChannel, dma_request_source_t source,
82  edma_chn_state_t *chn);
83 static void EDMA_DRV_ClearIntStatus(uint8_t channel);
84 static void EDMA_DRV_ClearSoftwareTCD(edma_software_tcd_t * stcd);
85 #ifdef DEV_ERROR_DETECT
86 static bool EDMA_DRV_ValidTransferSize(edma_transfer_size_t size);
87 #endif
88 
89 /*******************************************************************************
90  * Code
91  ******************************************************************************/
92 /*FUNCTION**********************************************************************
93  *
94  * Function Name : EDMA_DRV_Init
95  * Description : Initializes the eDMA module.
96  *
97  * Implements : EDMA_DRV_Init_Activity
98  *END**************************************************************************/
99 status_t EDMA_DRV_Init(edma_state_t *edmaState, const edma_user_config_t *userConfig,
100  edma_chn_state_t * const chnStateArray[],
101  const edma_channel_config_t * const chnConfigArray[],
102  uint8_t chnCount)
103 {
104  uint32_t i;
105  DMA_Type * edmaRegBase;
106  IRQn_Type irqNumber;
107  status_t edmaStatus = STATUS_SUCCESS;
108  status_t chnInitStatus;
109 #ifdef DEV_ERROR_DETECT
110  uint32_t freq;
111  status_t clockManagerStatus;
112 #endif
113 
114  /* Check the state and configuration structure pointers are valid */
115  DEV_ASSERT((edmaState != NULL) && (userConfig != NULL));
116 
117  /* Check the module has not already been initialized */
118  DEV_ASSERT(s_edma == NULL);
119 
120 #ifdef DEV_ERROR_DETECT
121  /* Check that eDMA and DMAMUX modules are clock gated on */
122  clockManagerStatus = CLOCK_SYS_GetFreq(s_edmaClockNames[0U], &freq);
123  DEV_ASSERT(clockManagerStatus == STATUS_SUCCESS);
124 
125  for (i = 0U; i < DMAMUX_INSTANCE_COUNT; i++)
126  {
127  clockManagerStatus = CLOCK_SYS_GetFreq(s_dmamuxClockNames[i], &freq);
128  DEV_ASSERT(clockManagerStatus == STATUS_SUCCESS);
129  }
130 #endif
131 
132  /* Save the runtime state structure for the driver */
133  s_edma = edmaState;
134 
135  /* Clear the state structure. */
136  volatile uint8_t *clearStructPtr = (volatile uint8_t *)s_edma;
137  size_t clearSize = sizeof(edma_state_t);
138  while (clearSize > 0U)
139  {
140  *clearStructPtr = 0;
141  clearStructPtr ++;
142  clearSize --;
143  }
144 
145  edmaRegBase = s_edmaBase[0U];
146 
147  /* Init eDMA module on hardware level. */
148  EDMA_Init(edmaRegBase);
149 
150  /* Set arbitration mode */
151  EDMA_SetChannelArbitrationMode(edmaRegBase, userConfig->chnArbitration);
152 #if (FEATURE_EDMA_CHANNEL_GROUP_COUNT > 0x1U)
153  EDMA_SetGroupArbitrationMode(edmaRegBase, userConfig->groupArbitration);
154  EDMA_SetGroupPriority(edmaRegBase, userConfig->groupPriority);
155 #endif
156 
157  /* Set 'Halt on error' configuration */
158  EDMA_SetHaltOnErrorCmd(edmaRegBase, !userConfig->notHaltOnError);
159 
160 #if defined FEATURE_EDMA_HAS_ERROR_IRQ
161  /* Enable the error interrupts for eDMA module. */
162  for (i = 0U; i < FEATURE_ERROR_INTERRUPT_LINES; i++)
163  {
164  /* Enable channel interrupt ID. */
165  irqNumber = s_edmaErrIrqId[i];
166  INT_SYS_EnableIRQ(irqNumber);
167  }
168 #endif
169 
170  /* Register all edma channel interrupt handler into vector table. */
171  for (i = 0U; i < FEATURE_CHANNEL_INTERRUPT_LINES; i++)
172  {
173  /* Enable channel interrupt ID. */
174  irqNumber = s_edmaIrqId[i];
175  INT_SYS_EnableIRQ(irqNumber);
176  }
177 
178  /* Initialize all DMAMUX instances */
179  for (i = 0U; i < DMAMUX_INSTANCE_COUNT; i++)
180  {
181  DMAMUX_Init(s_dmamuxBase[i]);
182  }
183 
184  /* Initialize the channels based on configuration list */
185  if ((chnStateArray != NULL) && (chnConfigArray != NULL))
186  {
187  for (i = 0U; i < chnCount; i++)
188  {
189  chnInitStatus = EDMA_DRV_ChannelInit(chnStateArray[i], chnConfigArray[i]);
190  if (chnInitStatus != STATUS_SUCCESS)
191  {
192  edmaStatus = chnInitStatus;
193  }
194  }
195  }
196 
197  return edmaStatus;
198 }
199 
200 /*FUNCTION**********************************************************************
201  *
202  * Function Name : EDMA_DRV_Deinit
203  * Description : Deinitialize EDMA.
204  *
205  * Implements : EDMA_DRV_Deinit_Activity
206  *END**************************************************************************/
208 {
209  uint32_t i;
210  IRQn_Type irqNumber;
211  const edma_chn_state_t *chn;
212 
213  /* Release all edma channel. */
214 #if defined FEATURE_EDMA_HAS_ERROR_IRQ
215  /* Disable the error interrupts for eDMA module. */
216  for (i = 0U; i < FEATURE_ERROR_INTERRUPT_LINES; i++)
217  {
218  /* Enable channel interrupt ID. */
219  irqNumber = s_edmaErrIrqId[i];
220  INT_SYS_DisableIRQ(irqNumber);
221  }
222 #endif
223  if (s_edma != NULL)
224  {
225  for (i = 0U; i < FEATURE_EDMA_MODULE_CHANNELS; i++)
226  {
227  /* Release all channels. */
228  chn = s_edma->chn[i];
229  if (chn != NULL)
230  {
231  (void) EDMA_DRV_ReleaseChannel(chn->channel);
232  }
233  }
234  for (i = 0U; i < FEATURE_CHANNEL_INTERRUPT_LINES; i++)
235  {
236  /* Disable channel interrupts. */
237  irqNumber = s_edmaIrqId[i];
238  INT_SYS_DisableIRQ(irqNumber);
239  }
240 
241  s_edma = NULL;
242  }
243 
244  return STATUS_SUCCESS;
245 }
246 
247 /*FUNCTION**********************************************************************
248  *
249  * Function Name : EDMA_DRV_ChannelInit
250  * Description : Initialize EDMA channel.
251  *
252  * Implements : EDMA_DRV_ChannelInit_Activity
253  *END**************************************************************************/
254 status_t EDMA_DRV_ChannelInit(edma_chn_state_t *edmaChannelState, const edma_channel_config_t *edmaChannelConfig)
255 {
256  DMA_Type * edmaRegBase = s_edmaBase[0U];
257  status_t status;
258 
259  /* Check the state and configuration structure pointers are valid */
260  DEV_ASSERT((edmaChannelState != NULL) && (edmaChannelConfig != NULL));
261  /* Check if the module is initialized */
262  DEV_ASSERT(s_edma != NULL);
263  /* Check if the channel defined by user in the channel configuration structure is valid */
264  DEV_ASSERT(edmaChannelConfig->channel < FEATURE_EDMA_MODULE_CHANNELS);
265 
266  /* Request the channel */
267  status = EDMA_DRV_RequestChannel(edmaChannelConfig->channel, edmaChannelConfig->source, edmaChannelState);
268 
269  if (status == STATUS_SUCCESS)
270  {
271  /* Set the channel priority, as defined in the configuration, only if fixed arbitration mode is selected */
272  if ((EDMA_GetChannelArbitrationMode(edmaRegBase) == EDMA_ARBITRATION_FIXED_PRIORITY) &&
273  (edmaChannelConfig->priority != EDMA_CHN_DEFAULT_PRIORITY))
274  {
275  EDMA_SetChannelPriority(edmaRegBase, edmaChannelConfig->channel, edmaChannelConfig->priority);
276  }
277 
278  /* Install the user callback */
279  status = EDMA_DRV_InstallCallback(edmaChannelConfig->channel, edmaChannelConfig->callback,
280  edmaChannelConfig->callbackParam);
281  }
282 
283  return status;
284 }
285 
286 /*FUNCTION**********************************************************************
287  *
288  * Function Name : EDMA_DRV_InstallCallback
289  * Description : Register callback function and parameter.
290  *
291  * Implements : EDMA_DRV_InstallCallback_Activity
292  *END**************************************************************************/
293 status_t EDMA_DRV_InstallCallback(uint8_t channel, edma_callback_t callback, void *parameter)
294 {
295  /* Check the channel number is valid */
297 
298  edma_chn_state_t * chnState = s_edma->chn[channel];
299  /* Check the channel is allocated */
300  DEV_ASSERT(chnState != NULL);
301 
302  chnState->callback = callback;
303  chnState->parameter = parameter;
304 
305  return STATUS_SUCCESS;
306 }
307 
308 /*FUNCTION**********************************************************************
309  *
310  * Function Name : EDMA_DRV_RequestChannel
311  * Description : Request an eDMA channel.
312  *
313  *END**************************************************************************/
314 static status_t EDMA_DRV_RequestChannel(uint8_t requestedChannel, dma_request_source_t source,
315  edma_chn_state_t *chn)
316 {
317  /* Retrieve the DMAMUX instance serving this channel */
318  uint8_t dmamuxInstance = (uint8_t)FEATURE_DMAMUX_REQ_SRC_TO_INSTANCE(source);
319  /* Retrieve the appropriate request source index for the corresponding DMAMUX instance */
320  uint8_t sourceDmamuxChannel = (uint8_t)FEATURE_DMAMUX_REQ_SRC_TO_CHN((uint8_t)source);
321  /* Retrieve the appropriate DMAMUX channel for the selected request source */
322  uint8_t dmamuxChannel = (uint8_t)FEATURE_DMAMUX_CHN_FOR_EDMA_CHN(requestedChannel);
323  /* Base addresses for eDMA and DMAMUX */
324  DMA_Type * edmaRegBase = s_edmaBase[0U];
325  DMAMUX_Type * dmamuxRegBase = s_dmamuxBase[dmamuxInstance];
326 
327  /* Check the channel has not already been allocated */
328  DEV_ASSERT(s_edma->chn[requestedChannel] == NULL);
329 
330  /* Channel allocation */
331  s_edma->chn[requestedChannel] = chn;
332 
333  /* Reset the channel state structure to default value. */
334  uint8_t *clearStructPtr = (uint8_t *)chn;
335  size_t clearSize = sizeof(edma_chn_state_t);
336  while (clearSize > 0U)
337  {
338  *clearStructPtr = 0;
339  clearStructPtr ++;
340  clearSize --;
341  }
342 
343  /* Init the channel state structure to the allocated channel number. */
344  chn->channel = requestedChannel;
345 
346  /* Enable error interrupt for this channel */
347  EDMA_SetErrorIntCmd(edmaRegBase, requestedChannel, true);
348 
349  /* Configure the DMAMUX for edma channel */
350  DMAMUX_SetChannelCmd(dmamuxRegBase, dmamuxChannel, false);
351  DMAMUX_SetChannelSource(dmamuxRegBase, dmamuxChannel, sourceDmamuxChannel);
352  DMAMUX_SetChannelCmd(dmamuxRegBase, dmamuxChannel, true);
353 
354  /* Clear the TCD registers for this channel */
355  EDMA_TCDClearReg(edmaRegBase, requestedChannel);
356 
357  return STATUS_SUCCESS;
358 }
359 
360 /*FUNCTION**********************************************************************
361  *
362  * Function Name : EDMA_DRV_ReleaseChannel
363  * Description : Free eDMA channel's hardware and software resource.
364  *
365  * Implements : EDMA_DRV_ReleaseChannel_Activity
366  *END**************************************************************************/
368 {
369  /* Check the channel number is valid */
371 
372  /* Check the DMA module is initialized */
373  DEV_ASSERT(s_edma != NULL);
374 
375  edma_chn_state_t * chnState = s_edma->chn[channel];
376 
377  /* Check the channel is initialized */
378  DEV_ASSERT(chnState != NULL);
379 
380  DMA_Type * edmaRegBase = s_edmaBase[0U];
381 
382  /* Stop edma channel. */
383  EDMA_SetDmaRequestCmd(edmaRegBase, channel, false);
384 
385  /* Reset the channel state structure to default value. */
386  uint8_t *clearStructPtr = (uint8_t *)chnState;
387  size_t clearSize = sizeof(edma_chn_state_t);
388  while (clearSize > 0U)
389  {
390  *clearStructPtr = 0;
391  clearStructPtr ++;
392  clearSize --;
393  }
394 
395  s_edma->chn[channel] = NULL;
396 
397  return STATUS_SUCCESS;
398 }
399 
400 /*FUNCTION**********************************************************************
401  *
402  * Function Name : EDMA_DRV_ClearIntStatus
403  * Description : Clear done and interrupt status.
404  *
405  *END**************************************************************************/
406 static void EDMA_DRV_ClearIntStatus(uint8_t channel)
407 {
408  DMA_Type * edmaRegBase = s_edmaBase[0U];
409  EDMA_ClearDoneStatusFlag(edmaRegBase, channel);
410  EDMA_ClearIntStatusFlag(edmaRegBase, channel);
411 }
412 
413 /*FUNCTION**********************************************************************
414  *
415  * Function Name : EDMA_DRV_ClearSoftwareTCD
416  * Description : Clear the software tcd structure.
417  *
418  *END**************************************************************************/
419 static void EDMA_DRV_ClearSoftwareTCD(edma_software_tcd_t * stcd)
420 {
421  uint8_t *byteAccess = (uint8_t *)stcd;
422  size_t clearSize = sizeof(edma_software_tcd_t);
423  while (clearSize > 0U)
424  {
425  *byteAccess = 0;
426  byteAccess ++;
427  clearSize --;
428  }
429 }
430 
431 /*FUNCTION**********************************************************************
432  *
433  * Function Name : EDMA_DRV_IRQHandler
434  * Description : EDMA IRQ handler.
435  *END**************************************************************************/
436 void EDMA_DRV_IRQHandler(uint8_t channel)
437 {
438  const edma_chn_state_t *chn = s_edma->chn[channel];
439 
440  EDMA_DRV_ClearIntStatus(channel);
441 
442  if (chn != NULL)
443  {
444  if (chn->callback != NULL)
445  {
446  chn->callback(chn->parameter, chn->status);
447  }
448  }
449 }
450 
451 /*FUNCTION**********************************************************************
452  *
453  * Function Name : EDMA_DRV_ErrorIRQHandler
454  * Description : EDMA error IRQ handler
455  *END**************************************************************************/
457 {
458  uint8_t channel = 0U;
459  uint32_t error;
460  DMA_Type * edmaRegBase = s_edmaBase[0U];
461  edma_chn_state_t *chn;
462 
463  error = EDMA_GetErrorIntStatusFlag(edmaRegBase);
464 
465  while ((error != 0UL) && (channel < (uint8_t) FEATURE_EDMA_MODULE_CHANNELS))
466  {
467  if ((error & EDMA_ERR_LSB_MASK) != 0UL)
468  {
469  EDMA_SetDmaRequestCmd(edmaRegBase, channel, false);
470  chn = s_edma->chn[channel];
471  if (chn != NULL)
472  {
473  EDMA_DRV_ClearIntStatus(channel);
474  EDMA_ClearErrorIntStatusFlag(edmaRegBase, channel);
475  chn->status = EDMA_CHN_ERROR;
476  if (chn->callback != NULL)
477  {
478  chn->callback(chn->parameter, chn->status);
479  }
480  }
481  }
482  error = error >> 1U;
483  channel++;
484  }
485  EDMA_SetHaltCmd(edmaRegBase, false);
486 }
487 
488 /*FUNCTION**********************************************************************
489  *
490  * Function Name : EDMA_DRV_ConfigSingleBlockTransfer
491  * Description : Configures a DMA single block transfer.
492  *
493  * Implements : EDMA_DRV_ConfigSingleBlockTransfer_Activity
494  *END**************************************************************************/
496  uint32_t srcAddr, uint32_t destAddr,
497  edma_transfer_size_t transferSize, uint32_t dataBufferSize)
498 {
499  /* Check the channel number is valid */
501 
502  /* Check the eDMA module is initialized */
503  DEV_ASSERT(s_edma != NULL);
504 
505  /* Check the channel is initialized */
506  DEV_ASSERT(s_edma->chn[channel] != NULL);
507 
508 #ifdef DEV_ERROR_DETECT
509  /* Check if the value passed for 'transferSize' is valid */
510  DEV_ASSERT(EDMA_DRV_ValidTransferSize(transferSize));
511 #endif
512 
513  DMA_Type * edmaRegBase = s_edmaBase[0U];
514  uint8_t transferOffset;
515  status_t status = STATUS_SUCCESS;
516 
517  /* Compute the transfer offset, based on transfer size.
518  * The number of bytes transferred in each source read/destination write
519  * is obtained with the following formula:
520  * source_read_size = 2^SSIZE
521  * destination_write_size = 2^DSIZE
522  */
523  transferOffset = (uint8_t) (1U << ((uint8_t)transferSize));
524 
525  /* The number of bytes to be transferred (buffer size) must
526  * be a multiple of the source read/destination write size
527  */
528  if ((dataBufferSize % transferOffset) != 0U)
529  {
530  status = STATUS_ERROR;
531  }
532 
533  if (status == STATUS_SUCCESS)
534  {
535  /* Clear transfer control descriptor for the current channel */
536  EDMA_TCDClearReg(edmaRegBase, channel);
537 
538  /* Configure source and destination addresses */
539  EDMA_TCDSetSrcAddr(edmaRegBase, channel, srcAddr);
540  EDMA_TCDSetDestAddr(edmaRegBase, channel, destAddr);
541 
542  /* Set transfer size (1B/2B/4B/16B/32B) */
543  EDMA_TCDSetAttribute(edmaRegBase, channel, EDMA_MODULO_OFF, EDMA_MODULO_OFF, transferSize, transferSize);
544 
545  /* Configure source/destination offset. */
546  switch (type)
547  {
549  EDMA_TCDSetSrcOffset(edmaRegBase, channel, 0);
550  EDMA_TCDSetDestOffset(edmaRegBase, channel, (int8_t) transferOffset);
551  break;
553  EDMA_TCDSetSrcOffset(edmaRegBase, channel, (int8_t) transferOffset);
554  EDMA_TCDSetDestOffset(edmaRegBase, channel, 0);
555  break;
557  EDMA_TCDSetSrcOffset(edmaRegBase, channel, (int8_t) transferOffset);
558  EDMA_TCDSetDestOffset(edmaRegBase, channel, (int8_t) transferOffset);
559  break;
561  EDMA_TCDSetSrcOffset(edmaRegBase, channel, 0);
562  EDMA_TCDSetDestOffset(edmaRegBase, channel, 0);
563  break;
564  default:
565  /* This should never be reached - all the possible values have been handled. */
566  break;
567  }
568 
569  /* Set the total number of bytes to be transfered */
570  EDMA_TCDSetNbytes(edmaRegBase, channel, dataBufferSize);
571 
572  /* Set major iteration count to 1 (single block mode) */
573  EDMA_TCDSetMajorCount(edmaRegBase, channel, 1U);
574 
575  /* Enable interrupt when the transfer completes */
576  EDMA_TCDSetMajorCompleteIntCmd(edmaRegBase, channel, true);
577  }
578 
579  return status;
580 }
581 
582 /*FUNCTION**********************************************************************
583  *
584  * Function Name : EDMA_DRV_ConfigSingleBlockTransfer
585  * Description : Configures a DMA single block transfer.
586  *
587  * Implements : EDMA_DRV_ConfigSingleBlockTransfer_Activity
588  *END**************************************************************************/
590  uint32_t srcAddr, uint32_t destAddr,
591  edma_transfer_size_t transferSize, uint32_t blockSize,
592  uint32_t blockCount, bool disableReqOnCompletion)
593 {
594  status_t status = STATUS_SUCCESS;
595 
596  /* Configure the transfer for one data block */
597  status = EDMA_DRV_ConfigSingleBlockTransfer(channel, type, srcAddr, destAddr, transferSize, blockSize);
598 
599  if (status == STATUS_SUCCESS)
600  {
601  DMA_Type * edmaRegBase = s_edmaBase[0U];
602 
603  /* Set the number of data blocks */
604  EDMA_TCDSetMajorCount(edmaRegBase, channel, blockCount);
605 
606  /* Enable/disable requests upon completion */
607  EDMA_TCDSetDisableDmaRequestAfterTCDDoneCmd(edmaRegBase, channel, disableReqOnCompletion);
608  }
609 
610  return status;
611 }
612 /*FUNCTION**********************************************************************
613  *
614  * Function Name : EDMA_DRV_ConfigLoopTransfer
615  * Description : Configures the DMA transfer in a loop.
616  *
617  * Implements : EDMA_DRV_ConfigLoopTransfer_Activity
618  *END**************************************************************************/
619 status_t EDMA_DRV_ConfigLoopTransfer(uint8_t channel, const edma_transfer_config_t *transferConfig)
620 {
621  /* Check the channel number is valid */
623 
624  /* Check the eDMA module is initialized */
625  DEV_ASSERT(s_edma != NULL);
626 
627  /* Check the channel is initialized */
628  DEV_ASSERT(s_edma->chn[channel] != NULL);
629 
630  /* Check the transfer configuration structure is valid */
631  DEV_ASSERT(transferConfig != NULL);
632 
633  /* Check the minor/major loop properties are defined */
634  DEV_ASSERT(transferConfig->loopTransferConfig != NULL);
635 
636  /* Enable minor loop mapping */
637  DMA_Type * edmaRegBase = s_edmaBase[0U];
638  EDMA_SetMinorLoopMappingCmd(edmaRegBase, true);
639 
640  /* Write the configuration in the transfer control descriptor registers */
641  EDMA_DRV_PushConfigToReg(channel, transferConfig);
642 
643  /* Enable interrupt when major loop iteration completes */
644  EDMA_TCDSetMajorCompleteIntCmd(edmaRegBase, channel, true);
645 
646  return STATUS_SUCCESS;
647 }
648 
649 /*FUNCTION**********************************************************************
650  *
651  * Function Name : EDMA_DRV_ConfigScatterGatherTransfer
652  * Description : Configure eDMA for scatter/gather operation
653  *
654  * Implements : EDMA_DRV_ConfigScatterGatherTransfer_Activity
655  *END**************************************************************************/
656 status_t EDMA_DRV_ConfigScatterGatherTransfer(uint8_t channel, edma_software_tcd_t *stcd,
657  edma_transfer_size_t transferSize, uint32_t bytesOnEachRequest,
658  const edma_scatter_gather_list_t *srcList,
659  const edma_scatter_gather_list_t *destList, uint8_t tcdCount)
660 {
661  /* Check the channel number is valid */
663 
664  /* Check the eDMA module is initialized */
665  DEV_ASSERT(s_edma != NULL);
666 
667  /* Check the channel is initialized */
668  DEV_ASSERT(s_edma->chn[channel] != NULL);
669 
670  /* Check the input arrays for scatter/gather operation are valid */
671  DEV_ASSERT((stcd != NULL) && (srcList != NULL) && (destList != NULL));
672 
673 #ifdef DEV_ERROR_DETECT
674  /* Check if the value passed for 'transferSize' is valid */
675  DEV_ASSERT(EDMA_DRV_ValidTransferSize(transferSize));
676 #endif
677 
678  uint8_t i;
679  uint16_t transferOffset;
680  uint32_t stcdAlignedAddr = STCD_ADDR(stcd);
681  edma_software_tcd_t *stcdAddr = (edma_software_tcd_t *)stcdAlignedAddr;
682  edma_loop_transfer_config_t loopConfig;
683  edma_transfer_config_t config;
684  status_t status = STATUS_SUCCESS;
685 
686  /* Compute the transfer offset, based on transfer size.
687  * The number of bytes transferred in each source read/destination write
688  * is obtained with the following formula:
689  * source_read_size = 2^SSIZE
690  * destination_write_size = 2^DSIZE
691  */
692  transferOffset = (uint16_t) (1UL << ((uint16_t)transferSize));
693 
694  /* The number of bytes to be transferred on each request must
695  * be a multiple of the source read/destination write size
696  */
697  if ((bytesOnEachRequest % transferOffset) != 0U)
698  {
699  status = STATUS_ERROR;
700  }
701 
702  /* Clear the configuration structures before initializing them. */
703  uint8_t *clearStructPtr = (uint8_t *)(&config);
704  size_t clearSize = sizeof(edma_transfer_config_t);
705  while (clearSize > 0U)
706  {
707  *clearStructPtr = 0;
708  clearStructPtr ++;
709  clearSize --;
710  }
711 
712  clearStructPtr = (uint8_t *)(&loopConfig);
713  clearSize = sizeof(edma_loop_transfer_config_t);
714  while (clearSize > 0U)
715  {
716  *clearStructPtr = 0;
717  clearStructPtr ++;
718  clearSize --;
719  }
720 
721  /* Configure the transfer for scatter/gather mode. */
722  config.srcLastAddrAdjust = 0;
723  config.destLastAddrAdjust = 0;
724  config.srcModulo = EDMA_MODULO_OFF;
725  config.destModulo = EDMA_MODULO_OFF;
726  config.srcTransferSize = transferSize;
727  config.destTransferSize = transferSize;
728  config.minorByteTransferCount = bytesOnEachRequest;
729  config.interruptEnable = true;
730  config.scatterGatherEnable = true;
731  config.loopTransferConfig = &loopConfig;
732  config.loopTransferConfig->srcOffsetEnable = false;
733  config.loopTransferConfig->dstOffsetEnable = false;
736 
737  /* Copy scatter/gather lists to transfer configuration*/
738  for (i = 0U; (i < tcdCount) && (status == STATUS_SUCCESS); i++)
739  {
740  config.srcAddr = srcList[i].address;
741  config.destAddr = destList[i].address;
742  if ((srcList[i].length != destList[i].length) || (srcList[i].type != destList[i].type))
743  {
744  status = STATUS_ERROR;
745  break;
746  }
747  config.loopTransferConfig->majorLoopIterationCount = srcList[i].length/bytesOnEachRequest;
748 
749  switch (srcList[i].type)
750  {
752  /* Configure Source Read. */
753  config.srcOffset = 0;
754  /* Configure Dest Write. */
755  config.destOffset = (int16_t) transferOffset;
756  break;
758  /* Configure Source Read. */
759  config.srcOffset = (int16_t) transferOffset;
760  /* Configure Dest Write. */
761  config.destOffset = 0;
762  break;
764  /* Configure Source Read. */
765  config.srcOffset = (int16_t) transferOffset;
766  /* Configure Dest Write. */
767  config.destOffset = (int16_t) transferOffset;
768  break;
770  /* Configure Source Read. */
771  config.srcOffset = 0;
772  /* Configure Dest Write. */
773  config.destOffset = 0;
774  break;
775  default:
776  /* This should never be reached - all the possible values have been handled. */
777  break;
778  }
779 
780  /* Configure the pointer to next software TCD structure; for the last one, this address should be 0 */
781  if (i == ((uint8_t)(tcdCount - 1U)))
782  {
783  config.scatterGatherNextDescAddr = 0U;
784  }
785  else
786  {
787  edma_software_tcd_t *nextAddr = &stcdAddr[i];
788  config.scatterGatherNextDescAddr = ((uint32_t) nextAddr);
789  }
790 
791  if (i == 0U)
792  {
793  /* Push the configuration for the first descriptor to registers */
794  EDMA_DRV_PushConfigToReg(channel, &config);
795  }
796  else
797  {
798  /* Copy configuration to software TCD structure */
799  EDMA_DRV_PushConfigToSTCD(&config, &stcdAddr[i - 1U]);
800  }
801  }
802 
803  return status;
804 }
805 
806 /*FUNCTION**********************************************************************
807  *
808  * Function Name : EDMA_DRV_StartChannel
809  * Description : Starts an eDMA channel.
810  *
811  * Implements : EDMA_DRV_StartChannel_Activity
812  *END**************************************************************************/
814 {
815  /* Check the channel number is valid */
817 
818  /* Check the eDMA module is initialized */
819  DEV_ASSERT(s_edma != NULL);
820 
821  /* Check the channel is initialized */
822  DEV_ASSERT(s_edma->chn[channel] != NULL);
823 
824  /* Enable requests for current channel */
825  DMA_Type * edmaRegBase = s_edmaBase[0U];
826  EDMA_SetDmaRequestCmd(edmaRegBase, channel, true);
827 
828  return STATUS_SUCCESS;
829 }
830 
831 /*FUNCTION**********************************************************************
832  *
833  * Function Name : EDMA_DRV_StopChannel
834  * Description : Stops an eDMA channel.
835  *
836  * Implements : EDMA_DRV_StopChannel_Activity
837  *END**************************************************************************/
839 {
840  /* Check the channel number is valid */
842 
843  /* Check the eDMA module is initialized */
844  DEV_ASSERT(s_edma != NULL);
845 
846  /* Check the channel is initialized */
847  DEV_ASSERT(s_edma->chn[channel] != NULL);
848 
849  /* Disable requests for current channel */
850  DMA_Type * edmaRegBase = s_edmaBase[0U];
851  EDMA_SetDmaRequestCmd(edmaRegBase, channel, false);
852 
853  return STATUS_SUCCESS;
854 }
855 
856 /*FUNCTION**********************************************************************
857  *
858  * Function Name : EDMA_DRV_SetChannelRequest
859  * Description : Configures the DMA request for the eDMA channel.
860  *
861  * Implements : EDMA_DRV_SetChannelRequest_Activity
862  *END**************************************************************************/
863 status_t EDMA_DRV_SetChannelRequest(uint8_t channel, uint8_t req)
864 {
865  /* Check the channel number is valid */
867 
868  /* Check the eDMA module is initialized */
869  DEV_ASSERT(s_edma != NULL);
870 
871  /* Check the channel is initialized */
872  DEV_ASSERT(s_edma->chn[channel] != NULL);
873 
874  /* Select the request for current channel */
875  DMAMUX_Type * dmamuxRegBase = s_dmamuxBase[0U];
876  DMAMUX_SetChannelSource(dmamuxRegBase, channel, req);
877 
878  return STATUS_SUCCESS;
879 }
880 
881 /*FUNCTION**********************************************************************
882  *
883  * Function Name : EDMA_DRV_ClearTCD
884  * Description : Clears all registers to 0 for the hardware TCD.
885  *
886  * Implements : EDMA_DRV_ClearTCD_Activity
887  *END**************************************************************************/
888 void EDMA_DRV_ClearTCD(uint8_t channel)
889 {
890  /* Check the channel number is valid */
892 
893  /* Check the eDMA module is initialized */
894  DEV_ASSERT(s_edma != NULL);
895 
896  /* Check the channel is initialized */
897  DEV_ASSERT(s_edma->chn[channel] != NULL);
898 
899  /* Clear the TCD memory */
900  DMA_Type * edmaRegBase = s_edmaBase[0U];
901  EDMA_TCDClearReg(edmaRegBase, channel);
902 }
903 
904 /*FUNCTION**********************************************************************
905  *
906  * Function Name : EDMA_DRV_SetSrcAddr
907  * Description : Configures the source address for the eDMA channel.
908  *
909  * Implements : EDMA_DRV_SetSrcAddr_Activity
910  *END**************************************************************************/
911 void EDMA_DRV_SetSrcAddr(uint8_t channel, uint32_t address)
912 {
913  /* Check the channel number is valid */
915 
916  /* Check the eDMA module is initialized */
917  DEV_ASSERT(s_edma != NULL);
918 
919  /* Check the channel is initialized */
920  DEV_ASSERT(s_edma->chn[channel] != NULL);
921 
922  /* Set channel TCD source address */
923  DMA_Type * edmaRegBase = s_edmaBase[0U];
924  EDMA_TCDSetSrcAddr(edmaRegBase, channel, address);
925 }
926 
927 /*FUNCTION**********************************************************************
928  *
929  * Function Name : EDMA_DRV_SetSrcOffset
930  * Description : Configures the source address signed offset for the eDMA channel.
931  *
932  * Implements : EDMA_DRV_SetSrcOffset_Activity
933  *END**************************************************************************/
934 void EDMA_DRV_SetSrcOffset(uint8_t channel, int16_t offset)
935 {
936  /* Check the channel number is valid */
938 
939  /* Check the eDMA module is initialized */
940  DEV_ASSERT(s_edma != NULL);
941 
942  /* Check the channel is initialized */
943  DEV_ASSERT(s_edma->chn[channel] != NULL);
944 
945  /* Set channel TCD source offset */
946  DMA_Type * edmaRegBase = s_edmaBase[0U];
947  EDMA_TCDSetSrcOffset(edmaRegBase, channel, offset);
948 }
949 
950 /*FUNCTION**********************************************************************
951  *
952  * Function Name : EDMA_DRV_SetSrcReadChunkSize
953  * Description : Configures the source read data chunk size (transferred in a read sequence).
954  *
955  * Implements : EDMA_DRV_SetSrcReadChunkSize_Activity
956  *END**************************************************************************/
958 {
959  /* Check the channel number is valid */
961 
962  /* Check the eDMA module is initialized */
963  DEV_ASSERT(s_edma != NULL);
964 
965  /* Check the channel is initialized */
966  DEV_ASSERT(s_edma->chn[channel] != NULL);
967 
968  /* Set channel TCD source transfer size */
969  DMA_Type * edmaRegBase = s_edmaBase[0U];
970  EDMA_TCDSetSrcTransferSize(edmaRegBase, channel, size);
971 }
972 
973 /*FUNCTION**********************************************************************
974  *
975  * Function Name : EDMA_DRV_SetSrcLastAddrAdjustment
976  * Description : Configures the source address last adjustment.
977  *
978  * Implements : EDMA_DRV_SetSrcLastAddrAdjustment_Activity
979  *END**************************************************************************/
980 void EDMA_DRV_SetSrcLastAddrAdjustment(uint8_t channel, int32_t adjust)
981 {
982  /* Check the channel number is valid */
984 
985  /* Check the eDMA module is initialized */
986  DEV_ASSERT(s_edma != NULL);
987 
988  /* Check the channel is initialized */
989  DEV_ASSERT(s_edma->chn[channel] != NULL);
990 
991  /* Set channel TCD source last adjustment */
992  DMA_Type * edmaRegBase = s_edmaBase[0U];
993  EDMA_TCDSetSrcLastAdjust(edmaRegBase, channel, adjust);
994 }
995 
996 /*FUNCTION**********************************************************************
997  *
998  * Function Name : EDMA_DRV_SetDestLastAddrAdjustment
999  * Description : Configures the source address last adjustment.
1000  *
1001  * Implements : EDMA_DRV_SetDestLastAddrAdjustment_Activity
1002  *END**************************************************************************/
1003 void EDMA_DRV_SetDestLastAddrAdjustment(uint8_t channel, int32_t adjust)
1004 {
1005  /* Check the channel number is valid */
1007 
1008  /* Check the eDMA module is initialized */
1009  DEV_ASSERT(s_edma != NULL);
1010 
1011  /* Check the channel is initialized */
1012  DEV_ASSERT(s_edma->chn[channel] != NULL);
1013 
1014  /* Set channel TCD source last adjustment */
1015  DMA_Type * edmaRegBase = s_edmaBase[0U];
1016  EDMA_TCDSetDestLastAdjust(edmaRegBase, channel, adjust);
1017 }
1018 
1019 /*FUNCTION**********************************************************************
1020  *
1021  * Function Name : EDMA_DRV_SetDestAddr
1022  * Description : Configures the destination address for the eDMA channel.
1023  *
1024  * Implements : EDMA_DRV_SetDestAddr_Activity
1025  *END**************************************************************************/
1026 void EDMA_DRV_SetDestAddr(uint8_t channel, uint32_t address)
1027 {
1028  /* Check the channel number is valid */
1030 
1031  /* Check the eDMA module is initialized */
1032  DEV_ASSERT(s_edma != NULL);
1033 
1034  /* Check the channel is initialized */
1035  DEV_ASSERT(s_edma->chn[channel] != NULL);
1036 
1037  /* Set channel TCD destination address */
1038  DMA_Type * edmaRegBase = s_edmaBase[0U];
1039  EDMA_TCDSetDestAddr(edmaRegBase, channel, address);
1040 }
1041 
1042 /*FUNCTION**********************************************************************
1043  *
1044  * Function Name : EDMA_DRV_SetDestOffset
1045  * Description : Configures the destination address signed offset for the eDMA channel.
1046  *
1047  * Implements : EDMA_DRV_SetDestOffset_Activity
1048  *END**************************************************************************/
1049 void EDMA_DRV_SetDestOffset(uint8_t channel, int16_t offset)
1050 {
1051  /* Check the channel number is valid */
1053 
1054  /* Check the eDMA module is initialized */
1055  DEV_ASSERT(s_edma != NULL);
1056 
1057  /* Check the channel is initialized */
1058  DEV_ASSERT(s_edma->chn[channel] != NULL);
1059 
1060  /* Set channel TCD destination offset */
1061  DMA_Type * edmaRegBase = s_edmaBase[0U];
1062  EDMA_TCDSetDestOffset(edmaRegBase, channel, offset);
1063 }
1064 
1065 /*FUNCTION**********************************************************************
1066  *
1067  * Function Name : EDMA_DRV_SetDestWriteChunkSize
1068  * Description : Configures the destination data chunk size (transferred in a write sequence).
1069  *
1070  * Implements : EDMA_DRV_SetDestWriteChunkSize_Activity
1071  *END**************************************************************************/
1073 {
1074  /* Check the channel number is valid */
1076 
1077  /* Check the eDMA module is initialized */
1078  DEV_ASSERT(s_edma != NULL);
1079 
1080  /* Check the channel is initialized */
1081  DEV_ASSERT(s_edma->chn[channel] != NULL);
1082 
1083  /* Set channel TCD source transfer size */
1084  DMA_Type * edmaRegBase = s_edmaBase[0U];
1085  EDMA_TCDSetDestTransferSize(edmaRegBase, channel, size);
1086 }
1087 
1088 /*FUNCTION**********************************************************************
1089  *
1090  * Function Name : EDMA_DRV_SetMinorLoopBlockSize
1091  * Description : Configures the number of bytes to be transferred in each service request of the channel.
1092  *
1093  * Implements : EDMA_DRV_SetMinorLoopBlockSize_Activity
1094  *END**************************************************************************/
1095 void EDMA_DRV_SetMinorLoopBlockSize(uint8_t channel, uint32_t nbytes)
1096 {
1097  /* Check the channel number is valid */
1099 
1100  /* Check the eDMA module is initialized */
1101  DEV_ASSERT(s_edma != NULL);
1102 
1103  /* Check the channel is initialized */
1104  DEV_ASSERT(s_edma->chn[channel] != NULL);
1105 
1106  /* Set channel TCD minor loop block size */
1107  DMA_Type * edmaRegBase = s_edmaBase[0U];
1108  EDMA_TCDSetNbytes(edmaRegBase, channel, nbytes);
1109 }
1110 
1111 /*FUNCTION**********************************************************************
1112  *
1113  * Function Name : EDMA_DRV_SetMajorLoopIterationCount
1114  * Description : Configures the number of major loop iterations.
1115  *
1116  * Implements : EDMA_DRV_SetMajorLoopIterationCount_Activity
1117  *END**************************************************************************/
1118 void EDMA_DRV_SetMajorLoopIterationCount(uint8_t channel, uint32_t majorLoopCount)
1119 {
1120  /* Check the channel number is valid */
1122 
1123  /* Check the eDMA module is initialized */
1124  DEV_ASSERT(s_edma != NULL);
1125 
1126  /* Check the channel is initialized */
1127  DEV_ASSERT(s_edma->chn[channel] != NULL);
1128 
1129  /* Set the major loop iteration count */
1130  DMA_Type * edmaRegBase = s_edmaBase[0U];
1131  EDMA_TCDSetMajorCount(edmaRegBase, channel, majorLoopCount);
1132 }
1133 
1134 /*FUNCTION**********************************************************************
1135  *
1136  * Function Name : EDMA_DRV_GetRemainingMajorIterationsCount
1137  * Description : Returns the remaining major loop iteration count.
1138  *
1139  * Implements : EDMA_DRV_GetRemainingMajorIterationsCount_Activity
1140  *END**************************************************************************/
1142 {
1143  uint32_t count;
1144 
1145  /* Check the channel number is valid */
1147 
1148  /* Check the eDMA module is initialized */
1149  DEV_ASSERT(s_edma != NULL);
1150 
1151  /* Check the channel is initialized */
1152  DEV_ASSERT(s_edma->chn[channel] != NULL);
1153 
1154  /* Retrieve the number of minor loops yet to be triggered */
1155  const DMA_Type * edmaRegBase = s_edmaBase[0U];
1156  count = EDMA_TCDGetCurrentMajorCount(edmaRegBase, channel);
1157 
1158  return count;
1159 }
1160 
1161 /*FUNCTION**********************************************************************
1162  *
1163  * Function Name : EDMA_DRV_SetScatterGatherLink
1164  * Description : Configures the memory address of the next TCD, in scatter/gather mode.
1165  *
1166  * Implements : EDMA_DRV_SetScatterGatherLink_Activity
1167  *END**************************************************************************/
1168 void EDMA_DRV_SetScatterGatherLink(uint8_t channel, uint32_t nextTCDAddr)
1169 {
1170  /* Check the channel number is valid */
1172 
1173  /* Check the eDMA module is initialized */
1174  DEV_ASSERT(s_edma != NULL);
1175 
1176  /* Check the channel is initialized */
1177  DEV_ASSERT(s_edma->chn[channel] != NULL);
1178 
1179  /* Configures the memory address of the next TCD */
1180  DMA_Type * edmaRegBase = s_edmaBase[0U];
1181  EDMA_TCDSetScatterGatherLink(edmaRegBase, channel, nextTCDAddr);
1182 }
1183 
1184 /*FUNCTION**********************************************************************
1185  *
1186  * Function Name : EDMA_DRV_DisableRequestsOnTransferComplete
1187  * Description : Disables/Enables the DMA request after the major loop completes for the TCD.
1188  *
1189  * Implements : EDMA_DRV_DisableRequestsOnTransferComplete_Activity
1190  *END**************************************************************************/
1191 void EDMA_DRV_DisableRequestsOnTransferComplete(uint8_t channel, bool disable)
1192 {
1193  /* Check the channel number is valid */
1195 
1196  /* Check the eDMA module is initialized */
1197  DEV_ASSERT(s_edma != NULL);
1198 
1199  /* Check the channel is initialized */
1200  DEV_ASSERT(s_edma->chn[channel] != NULL);
1201 
1202  /* Disables/Enables the DMA request upon TCD completion */
1203  DMA_Type * edmaRegBase = s_edmaBase[0U];
1204  EDMA_TCDSetDisableDmaRequestAfterTCDDoneCmd(edmaRegBase, channel, disable);
1205 }
1206 
1207 /*FUNCTION**********************************************************************
1208  *
1209  * Function Name : EDMA_DRV_ConfigureInterrupt
1210  * Description : Disables/Enables the channel interrupt requests.
1211  *
1212  * Implements : EDMA_DRV_ConfigureInterrupt_Activity
1213  *END**************************************************************************/
1214 void EDMA_DRV_ConfigureInterrupt(uint8_t channel, edma_channel_interrupt_t intSrc, bool enable)
1215 {
1216  /* Check the channel number is valid */
1218 
1219  /* Check the eDMA module is initialized */
1220  DEV_ASSERT(s_edma != NULL);
1221 
1222  /* Check the channel is initialized */
1223  DEV_ASSERT(s_edma->chn[channel] != NULL);
1224 
1225  /* Disables/Enables the channel interrupt requests. */
1226  DMA_Type * edmaRegBase = s_edmaBase[0U];
1227  switch (intSrc)
1228  {
1229  case EDMA_CHN_ERR_INT:
1230  /* Enable channel interrupt request when error conditions occur */
1231  EDMA_SetErrorIntCmd(edmaRegBase, channel, enable);
1232  break;
1234  /* Enable channel interrupt request when major iteration count reaches halfway point */
1235  EDMA_TCDSetMajorHalfCompleteIntCmd(edmaRegBase, channel, enable);
1236  break;
1238  /* Enable channel interrupt request when major iteration count reaches zero */
1239  EDMA_TCDSetMajorCompleteIntCmd(edmaRegBase, channel, enable);
1240  break;
1241  default:
1242  /* This branch should never be reached if driver API is used properly */
1243  break;
1244  }
1245 }
1246 
1247 /*FUNCTION**********************************************************************
1248  *
1249  * Function Name : EDMA_DRV_CancelTransfer
1250  * Description : Cancels the running transfer for this channel.
1251  *
1252  * Implements : EDMA_DRV_CancelTransfer_Activity
1253  *END**************************************************************************/
1254 void EDMA_DRV_CancelTransfer(bool error)
1255 {
1256  /* Check the eDMA module is initialized */
1257  DEV_ASSERT(s_edma != NULL);
1258 
1259  /* Cancel the running transfer. */
1260  DMA_Type * edmaRegBase = s_edmaBase[0U];
1261 
1262  if (error)
1263  {
1264  EDMA_CancelTransferWithError(edmaRegBase);
1265  }
1266  else
1267  {
1268  EDMA_CancelTransfer(edmaRegBase);
1269  }
1270 }
1271 
1272 /*FUNCTION**********************************************************************
1273  *
1274  * Function Name : EDMA_DRV_TriggerSwRequest
1275  * Description : Triggers a sw request for the current channel.
1276  *
1277  * Implements : EDMA_DRV_TriggerSwRequest_Activity
1278  *END**************************************************************************/
1279 void EDMA_DRV_TriggerSwRequest(uint8_t channel)
1280 {
1281  /* Check the channel number is valid */
1283 
1284  /* Check the eDMA module is initialized */
1285  DEV_ASSERT(s_edma != NULL);
1286 
1287  /* Check the channel is initialized */
1288  DEV_ASSERT(s_edma->chn[channel] != NULL);
1289 
1290  /* Trigger the channel transfer. */
1291  DMA_Type * edmaRegBase = s_edmaBase[0U];
1292  EDMA_TriggerChannelStart(edmaRegBase, channel);
1293 }
1294 
1295 /*FUNCTION**********************************************************************
1296  *
1297  * Function Name : EDMA_DRV_PushConfigToSTCD
1298  * Description : Copy the configuration to the software TCD structure.
1299  *
1300  * Implements : EDMA_DRV_PushConfigToSTCD_Activity
1301  *END**************************************************************************/
1302 void EDMA_DRV_PushConfigToSTCD(const edma_transfer_config_t *config, edma_software_tcd_t *stcd)
1303 {
1304  if ((config != NULL) && (stcd != NULL))
1305  {
1306  /* Clear the array of software TCDs passed by the user */
1308 
1309  /* Set the software TCD fields */
1310  stcd->ATTR = (uint16_t)((((uint16_t)config->srcModulo) << DMA_TCD_ATTR_SMOD_SHIFT) | (((uint16_t)config->srcTransferSize) << DMA_TCD_ATTR_SSIZE_SHIFT) |
1311  (((uint16_t)config->destModulo) << DMA_TCD_ATTR_DMOD_SHIFT) | (((uint16_t)config->destTransferSize) << DMA_TCD_ATTR_DSIZE_SHIFT));
1312  stcd->SADDR = config->srcAddr;
1313  stcd->SOFF = config->srcOffset;
1314  stcd->NBYTES = config->minorByteTransferCount;
1315  stcd->SLAST = config->srcLastAddrAdjust;
1316  stcd->DADDR = config->destAddr;
1317  stcd->DOFF = config->destOffset;
1318  stcd->CITER = (uint16_t) config->loopTransferConfig->majorLoopIterationCount;
1319  if (config->scatterGatherEnable)
1320  {
1321  stcd->DLAST_SGA = (int32_t) config->scatterGatherNextDescAddr;
1322  }
1323  else
1324  {
1325  stcd->DLAST_SGA = config->destLastAddrAdjust;
1326  }
1327  stcd->CSR = (uint16_t) (((config->interruptEnable ? 1UL : 0UL) << DMA_TCD_CSR_INTMAJOR_SHIFT) |
1328  ((config->scatterGatherEnable ? 1UL : 0UL) << DMA_TCD_CSR_ESG_SHIFT));
1329  stcd->BITER = (uint16_t) config->loopTransferConfig->majorLoopIterationCount;
1330  }
1331 }
1332 
1333 /*FUNCTION**********************************************************************
1334  *
1335  * Function Name : EDMA_DRV_PushConfigToReg
1336  * Description : Copy the configuration to the TCD registers.
1337  *
1338  * Implements : EDMA_DRV_PushConfigToReg_Activity
1339  *END**************************************************************************/
1340 void EDMA_DRV_PushConfigToReg(uint8_t channel, const edma_transfer_config_t *tcd)
1341 {
1342  /* Check the channel number is valid */
1344 
1345  /* Check the eDMA module is initialized */
1346  DEV_ASSERT(s_edma != NULL);
1347 
1348  /* Check the channel is initialized */
1349  DEV_ASSERT(s_edma->chn[channel] != NULL);
1350 
1351  /* Check the transfer configuration structure is valid */
1352  DEV_ASSERT(tcd != NULL);
1353 
1354  DMA_Type * edmaRegBase = s_edmaBase[0U];
1355  /* Clear TCD registers */
1356  EDMA_TCDClearReg(edmaRegBase, channel);
1357 
1358  /* Set source and destination addresses */
1359  EDMA_TCDSetSrcAddr(edmaRegBase, channel, tcd->srcAddr);
1360  EDMA_TCDSetDestAddr(edmaRegBase, channel, tcd->destAddr);
1361 
1362  /* Set source/destination modulo feature and transfer size */
1363  EDMA_TCDSetAttribute(edmaRegBase, channel, tcd->srcModulo, tcd->destModulo,
1364  tcd->srcTransferSize, tcd->destTransferSize);
1365 
1366  /* Set source/destination offset and last adjustment; for scatter/gather operation, destination
1367  * last adjustment is the address of the next TCD structure to be loaded by the eDMA engine */
1368  EDMA_TCDSetSrcOffset(edmaRegBase, channel, tcd->srcOffset);
1369  EDMA_TCDSetDestOffset(edmaRegBase, channel, tcd->destOffset);
1370  EDMA_TCDSetSrcLastAdjust(edmaRegBase, channel, tcd->srcLastAddrAdjust);
1371  if (tcd->scatterGatherEnable)
1372  {
1373  EDMA_TCDSetScatterGatherCmd(edmaRegBase, channel, true);
1374  EDMA_TCDSetScatterGatherLink(edmaRegBase, channel, tcd->scatterGatherNextDescAddr);
1375  }
1376  else
1377  {
1378  EDMA_TCDSetScatterGatherCmd(edmaRegBase, channel, false);
1379  EDMA_TCDSetDestLastAdjust(edmaRegBase, channel, tcd->destLastAddrAdjust);
1380  }
1381 
1382  /* Configure channel interrupt */
1383  EDMA_TCDSetMajorCompleteIntCmd(edmaRegBase, channel, tcd->interruptEnable);
1384 
1385  /* If loop configuration is available, copy minor/major loop setup to registers */
1386  if (tcd->loopTransferConfig != NULL)
1387  {
1388  EDMA_TCDSetSrcMinorLoopOffsetCmd(edmaRegBase, channel, tcd->loopTransferConfig->srcOffsetEnable);
1389  EDMA_TCDSetDestMinorLoopOffsetCmd(edmaRegBase, channel, tcd->loopTransferConfig->dstOffsetEnable);
1390  EDMA_TCDSetMinorLoopOffset(edmaRegBase, channel, tcd->loopTransferConfig->minorLoopOffset);
1391  EDMA_TCDSetNbytes(edmaRegBase, channel, tcd->minorByteTransferCount);
1392 
1393  EDMA_TCDSetChannelMinorLink(edmaRegBase, channel, tcd->loopTransferConfig->minorLoopChnLinkNumber,
1395  EDMA_TCDSetChannelMajorLink(edmaRegBase, channel, tcd->loopTransferConfig->majorLoopChnLinkNumber,
1397 
1398  EDMA_TCDSetMajorCount(edmaRegBase, channel, tcd->loopTransferConfig->majorLoopIterationCount);
1399  }
1400  else
1401  {
1402  EDMA_TCDSetNbytes(edmaRegBase, channel, tcd->minorByteTransferCount);
1403  }
1404 }
1405 
1406 #ifdef DEV_ERROR_DETECT
1407 /*FUNCTION**********************************************************************
1408  *
1409  * Function Name : EDMA_DRV_ValidTransferSize
1410  * Description : Check if the transfer size value is legal (0/1/2/4/5).
1411  *
1412  *END**************************************************************************/
1413 static bool EDMA_DRV_ValidTransferSize(edma_transfer_size_t size)
1414 {
1415  bool isValid;
1416  switch (size)
1417  {
1418  case EDMA_TRANSFER_SIZE_1B:
1419  case EDMA_TRANSFER_SIZE_2B:
1420  case EDMA_TRANSFER_SIZE_4B:
1423  isValid = true;
1424  break;
1425  default:
1426  isValid = false;
1427  break;
1428  }
1429  return isValid;
1430 }
1431 #endif
1432 
1433 /*FUNCTION**********************************************************************
1434  *
1435  * Function Name : EDMA_DRV_GetChannelStatus
1436  * Description : Returns the eDMA channel status.
1437  *
1438  * Implements : EDMA_DRV_GetChannelStatus_Activity
1439  *END**************************************************************************/
1441 {
1442  /* Check the channel number is valid */
1444 
1445  /* Check the eDMA module is initialized */
1446  DEV_ASSERT(s_edma != NULL);
1447 
1448  /* Check the channel is initialized */
1449  DEV_ASSERT(s_edma->chn[channel] != NULL);
1450 
1451  return s_edma->chn[channel]->status;
1452 }
1453 
1454 /*******************************************************************************
1455  * EOF
1456  ******************************************************************************/
1457 
1458 
void EDMA_DRV_PushConfigToSTCD(const edma_transfer_config_t *config, edma_software_tcd_t *stcd)
Copies the channel configuration to the software TCD structure.
Definition: edma_driver.c:1302
edma_chn_state_t *volatile chn[FEATURE_EDMA_MODULE_CHANNELS]
Definition: edma_driver.h:263
void EDMA_DRV_SetDestLastAddrAdjustment(uint8_t channel, int32_t adjust)
Configures the destination address last adjustment.
Definition: edma_driver.c:1003
uint32_t minorByteTransferCount
Definition: edma_driver.h:310
#define DMAMUX_INSTANCE_COUNT
Definition: S32K142.h:3029
#define DMA_INSTANCE_COUNT
Definition: S32K142.h:2212
void EDMA_DRV_SetSrcReadChunkSize(uint8_t channel, edma_transfer_size_t size)
Configures the source data chunk size (transferred in a read sequence).
Definition: edma_driver.c:957
edma_modulo_t destModulo
Definition: edma_driver.h:309
static status_t EDMA_DRV_RequestChannel(uint8_t requestedChannel, dma_request_source_t source, edma_chn_state_t *chn)
Definition: edma_driver.c:314
uint32_t EDMA_DRV_GetRemainingMajorIterationsCount(uint8_t channel)
Returns the remaining major loop iteration count.
Definition: edma_driver.c:1141
edma_callback_t callback
Definition: edma_driver.h:230
The user configuration structure for the eDMA driver.
Definition: edma_driver.h:175
edma_transfer_type_t
A type for the DMA transfer. Implements : edma_transfer_type_t_Class.
Definition: edma_driver.h:237
The user configuration structure for the an eDMA driver channel.
Definition: edma_driver.h:225
status_t EDMA_DRV_ReleaseChannel(uint8_t channel)
Releases an eDMA channel.
Definition: edma_driver.c:367
status_t EDMA_DRV_StopChannel(uint8_t channel)
Stops the eDMA channel.
Definition: edma_driver.c:838
void EDMA_DRV_SetDestOffset(uint8_t channel, int16_t offset)
Configures the destination address signed offset for the eDMA channel.
Definition: edma_driver.c:1049
status_t EDMA_DRV_Deinit(void)
De-initializes the eDMA module.
Definition: edma_driver.c:207
status_t EDMA_DRV_Init(edma_state_t *edmaState, const edma_user_config_t *userConfig, edma_chn_state_t *const chnStateArray[], const edma_channel_config_t *const chnConfigArray[], uint8_t chnCount)
Initializes the eDMA module.
Definition: edma_driver.c:99
edma_channel_priority_t priority
Definition: edma_driver.h:226
void EDMA_DRV_IRQHandler(uint8_t channel)
eDMA channel interrupt handler, implemented in driver c file.
Definition: edma_driver.c:436
void EDMA_DRV_SetMinorLoopBlockSize(uint8_t channel, uint32_t nbytes)
Configures the number of bytes to be transferred in each service request of the channel.
Definition: edma_driver.c:1095
status_t EDMA_DRV_SetChannelRequest(uint8_t channel, uint8_t req)
Configures the DMA request for the eDMA channel.
Definition: edma_driver.c:863
#define DMA_BASE_PTRS
Definition: S32K142.h:2223
#define FEATURE_DMAMUX_REQ_SRC_TO_INSTANCE(x)
dma_request_source_t
Structure for the DMA hardware request.
void EDMA_DRV_DisableRequestsOnTransferComplete(uint8_t channel, bool disable)
Disables/Enables the DMA request after the major loop completes for the TCD.
Definition: edma_driver.c:1191
void INT_SYS_DisableIRQ(IRQn_Type irqNumber)
Disables an interrupt for a given IRQ number.
void EDMA_DRV_SetSrcLastAddrAdjustment(uint8_t channel, int32_t adjust)
Configures the source address last adjustment.
Definition: edma_driver.c:980
void EDMA_DRV_SetScatterGatherLink(uint8_t channel, uint32_t nextTCDAddr)
Configures the memory address of the next TCD, in scatter/gather mode.
Definition: edma_driver.c:1168
edma_channel_interrupt_t
eDMA channel interrupts. Implements : edma_channel_interrupt_t_Class
Definition: edma_driver.h:72
#define DEV_ASSERT(x)
Definition: devassert.h:77
uint32_t scatterGatherNextDescAddr
Definition: edma_driver.h:313
status_t EDMA_DRV_ConfigLoopTransfer(uint8_t channel, const edma_transfer_config_t *transferConfig)
Configures the DMA transfer in loop mode.
Definition: edma_driver.c:619
#define STCD_ADDR(address)
Definition: edma_driver.h:59
status_t EDMA_DRV_ChannelInit(edma_chn_state_t *edmaChannelState, const edma_channel_config_t *edmaChannelConfig)
Initializes an eDMA channel.
Definition: edma_driver.c:254
void EDMA_DRV_ErrorIRQHandler(void)
Definition: edma_driver.c:456
Runtime state structure for the eDMA driver.
Definition: edma_driver.h:262
edma_chn_status_t
Channel status for eDMA channel.
Definition: edma_driver.h:193
clock_names_t
Clock names.
edma_transfer_size_t destTransferSize
Definition: edma_driver.h:298
edma_callback_t callback
Definition: edma_driver.h:211
#define DMA_TCD_ATTR_DMOD_SHIFT
Definition: S32K142.h:2848
edma_transfer_size_t
eDMA transfer configuration Implements : edma_transfer_size_t_Class
Definition: edma_driver.h:160
#define DMA_TCD_CSR_ESG_SHIFT
Definition: S32K142.h:2954
void EDMA_DRV_PushConfigToReg(uint8_t channel, const edma_transfer_config_t *tcd)
Copies the channel configuration to the TCD registers.
Definition: edma_driver.c:1340
void EDMA_DRV_SetSrcAddr(uint8_t channel, uint32_t address)
Configures the source address for the eDMA channel.
Definition: edma_driver.c:911
status_t CLOCK_SYS_GetFreq(clock_names_t clockName, uint32_t *frequency)
Gets the clock frequency for a specific clock name.
static edma_state_t * s_edma
EDMA global structure to maintain eDMA state.
Definition: edma_driver.c:76
edma_arbitration_algorithm_t chnArbitration
Definition: edma_driver.h:176
#define FEATURE_ERROR_INTERRUPT_LINES
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:44
static void EDMA_DRV_ClearIntStatus(uint8_t channel)
Definition: edma_driver.c:406
#define EDMA_CLOCK_NAMES
edma_modulo_t srcModulo
Definition: edma_driver.h:308
status_t EDMA_DRV_ConfigScatterGatherTransfer(uint8_t channel, edma_software_tcd_t *stcd, edma_transfer_size_t transferSize, uint32_t bytesOnEachRequest, const edma_scatter_gather_list_t *srcList, const edma_scatter_gather_list_t *destList, uint8_t tcdCount)
Configures the DMA transfer in a scatter-gather mode.
Definition: edma_driver.c:656
#define FEATURE_CHANNEL_INTERRUPT_LINES
#define DMA_TCD_ATTR_SMOD_SHIFT
Definition: S32K142.h:2856
#define EDMA_ERR_LSB_MASK
Macro for accessing the least significant bit of the ERR register.
Definition: edma_driver.h:67
edma_transfer_size_t srcTransferSize
Definition: edma_driver.h:297
Data structure for configuring a discrete memory transfer. Implements : edma_scatter_gather_list_t_Cl...
Definition: edma_driver.h:247
void EDMA_DRV_SetMajorLoopIterationCount(uint8_t channel, uint32_t majorLoopCount)
Configures the number of major loop iterations.
Definition: edma_driver.c:1118
volatile edma_chn_status_t status
Definition: edma_driver.h:215
#define DMAMUX_BASE_PTRS
Definition: S32K142.h:3040
void EDMA_DRV_SetDestAddr(uint8_t channel, uint32_t address)
Configures the destination address for the eDMA channel.
Definition: edma_driver.c:1026
edma_chn_status_t EDMA_DRV_GetChannelStatus(uint8_t channel)
Gets the eDMA channel status.
Definition: edma_driver.c:1440
edma_transfer_type_t type
Definition: edma_driver.h:250
void EDMA_DRV_SetDestWriteChunkSize(uint8_t channel, edma_transfer_size_t size)
Configures the destination data chunk size (transferred in a write sequence).
Definition: edma_driver.c:1072
status_t EDMA_DRV_StartChannel(uint8_t channel)
Starts an eDMA channel.
Definition: edma_driver.c:813
static const IRQn_Type s_edmaIrqId[FEATURE_CHANNEL_INTERRUPT_LINES]
Array of default DMA channel interrupt handlers.
Definition: edma_driver.c:64
void EDMA_DRV_SetSrcOffset(uint8_t channel, int16_t offset)
Configures the source address signed offset for the eDMA channel.
Definition: edma_driver.c:934
void EDMA_DRV_TriggerSwRequest(uint8_t channel)
Triggers a sw request for the current channel.
Definition: edma_driver.c:1279
void EDMA_DRV_ClearTCD(uint8_t channel)
Clears all registers to 0 for the channel's TCD.
Definition: edma_driver.c:888
#define DMAMUX_CLOCK_NAMES
void INT_SYS_EnableIRQ(IRQn_Type irqNumber)
Enables an interrupt for a given IRQ number.
#define DMA_TCD_CSR_INTMAJOR_SHIFT
Definition: S32K142.h:2942
static DMAMUX_Type *const s_dmamuxBase[DMAMUX_INSTANCE_COUNT]
Array of base addresses for DMAMUX instances.
Definition: edma_driver.c:61
#define DMA_TCD_ATTR_SSIZE_SHIFT
Definition: S32K142.h:2852
void EDMA_DRV_CancelTransfer(bool error)
Cancel the running transfer.
Definition: edma_driver.c:1254
static const clock_names_t s_dmamuxClockNames[DMAMUX_INSTANCE_COUNT]
Definition: edma_driver.c:73
void(* edma_callback_t)(void *parameter, edma_chn_status_t status)
Definition for the eDMA channel callback function.
Definition: edma_driver.h:204
dma_request_source_t source
Definition: edma_driver.h:229
status_t EDMA_DRV_ConfigSingleBlockTransfer(uint8_t channel, edma_transfer_type_t type, uint32_t srcAddr, uint32_t destAddr, edma_transfer_size_t transferSize, uint32_t dataBufferSize)
Configures a simple single block data transfer with DMA.
Definition: edma_driver.c:495
static void EDMA_DRV_ClearSoftwareTCD(edma_software_tcd_t *stcd)
Definition: edma_driver.c:419
eDMA loop transfer configuration.
Definition: edma_driver.h:272
static const clock_names_t s_edmaClockNames[DMA_INSTANCE_COUNT]
Array of default DMA error interrupt handlers.
Definition: edma_driver.c:72
#define FEATURE_DMAMUX_CHN_FOR_EDMA_CHN(x)
void EDMA_DRV_ConfigureInterrupt(uint8_t channel, edma_channel_interrupt_t intSrc, bool enable)
Disables/Enables the channel interrupt requests.
Definition: edma_driver.c:1214
eDMA transfer size configuration.
Definition: edma_driver.h:294
edma_loop_transfer_config_t * loopTransferConfig
Definition: edma_driver.h:319
#define DMA_CHN_IRQS
Definition: S32K142.h:2231
status_t EDMA_DRV_ConfigMultiBlockTransfer(uint8_t channel, edma_transfer_type_t type, uint32_t srcAddr, uint32_t destAddr, edma_transfer_size_t transferSize, uint32_t blockSize, uint32_t blockCount, bool disableReqOnCompletion)
Configures a multiple block data transfer with DMA.
Definition: edma_driver.c:589
status_t EDMA_DRV_InstallCallback(uint8_t channel, edma_callback_t callback, void *parameter)
Registers the callback function and the parameter for eDMA channel.
Definition: edma_driver.c:293
static DMA_Type *const s_edmaBase[DMA_INSTANCE_COUNT]
Array of base addresses for DMA instances.
Definition: edma_driver.c:58
#define FEATURE_EDMA_MODULE_CHANNELS
#define DMA_ERROR_IRQS
Definition: S32K142.h:2232
#define DMA_TCD_ATTR_DSIZE_SHIFT
Definition: S32K142.h:2844
#define FEATURE_DMAMUX_REQ_SRC_TO_CHN(x)
IRQn_Type
Defines the Interrupt Numbers definitions.
Definition: S32K142.h:192
Data structure for the eDMA channel state. Implements : edma_chn_state_t_Class.
Definition: edma_driver.h:209