EFM32 Leopard Gecko Software Documentation  efm32lg-doc-4.2.1
dmadrv.c
Go to the documentation of this file.
1 /***************************************************************************/
16 #include <stdbool.h>
17 #include <stddef.h>
18 
19 #include "em_device.h"
20 #include "em_cmu.h"
21 #include "em_int.h"
22 
23 #include "dmadrv.h"
24 
25 #if defined( EMDRV_DMADRV_UDMA )
26 #include "dmactrl.h"
27 #endif
28 
30 
31 #if !defined( EMDRV_DMADRV_DMA_CH_COUNT ) \
32  || ( EMDRV_DMADRV_DMA_CH_COUNT > DMA_CHAN_COUNT )
33 #define EMDRV_DMADRV_DMA_CH_COUNT DMA_CHAN_COUNT
34 #endif
35 
36 typedef enum
37 {
38  dmaDirectionMemToPeripheral,
39  dmaDirectionPeripheralToMem
40 } DmaDirection_t;
41 
42 typedef enum
43 {
44  dmaModeBasic,
45  dmaModePingPong
46 } DmaMode_t;
47 
48 #if defined( EMDRV_DMADRV_USE_NATIVE_API ) && defined( EMDRV_DMADRV_UDMA )
49 typedef struct
50 {
51  bool allocated;
52 } ChTable_t;
53 
54 #elif defined( EMDRV_DMADRV_USE_NATIVE_API ) && defined( EMDRV_DMADRV_LDMA )
55 typedef struct
56 {
57  DMADRV_Callback_t callback;
58  void *userParam;
59  unsigned int callbackCount;
60  bool allocated;
61 } ChTable_t;
62 
63 #else
64 typedef struct
65 {
66  DMADRV_Callback_t callback;
67  void *userParam;
68  unsigned int callbackCount;
69 #if defined( EMDRV_DMADRV_UDMA )
70  int length;
71 #endif
72  bool allocated;
73 #if defined( EMDRV_DMADRV_LDMA )
74  DmaMode_t mode;
75 #endif
76 } ChTable_t;
77 #endif
78 
79 static bool initialized = false;
80 static ChTable_t chTable[ EMDRV_DMADRV_DMA_CH_COUNT ];
81 
82 #if defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
83 static DMA_CB_TypeDef dmaCallBack[ EMDRV_DMADRV_DMA_CH_COUNT ];
84 #endif
85 
86 #if defined( EMDRV_DMADRV_LDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
87 const LDMA_TransferCfg_t xferCfg = LDMA_TRANSFER_CFG_PERIPHERAL( 0 );
88 const LDMA_Descriptor_t m2p = LDMA_DESCRIPTOR_SINGLE_M2P_BYTE( NULL, NULL, 0 );
89 const LDMA_Descriptor_t p2m = LDMA_DESCRIPTOR_SINGLE_P2M_BYTE( NULL, NULL, 0 );
90 
91 typedef struct
92 {
93  LDMA_Descriptor_t desc[2];
94 } DmaXfer_t;
95 
96 static DmaXfer_t dmaXfer[ EMDRV_DMADRV_DMA_CH_COUNT ];
97 #endif
98 
99 #if !defined( EMDRV_DMADRV_USE_NATIVE_API )
100 static Ecode_t StartTransfer( DmaMode_t mode,
101  DmaDirection_t direction,
102  unsigned int channelId,
103  DMADRV_PeripheralSignal_t
104  peripheralSignal,
105  void *buf0,
106  void *buf1,
107  void *buf2,
108  bool bufInc,
109  int len,
110  DMADRV_DataSize_t size,
111  DMADRV_Callback_t callback,
112  void *cbUserParam );
113 #endif
114 
116 
117 /***************************************************************************/
131 Ecode_t DMADRV_AllocateChannel( unsigned int *channelId, void *capabilities )
132 {
133  int i;
134  (void)capabilities;
135 
136  if ( !initialized )
137  {
139  }
140 
141  if ( channelId == NULL )
142  {
144  }
145 
146  INT_Disable();
147  for ( i=0; i < EMDRV_DMADRV_DMA_CH_COUNT; i++ )
148  {
149  if ( !chTable[ i ].allocated )
150  {
151  *channelId = i;
152  chTable[ i ].allocated = true;
153 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( EMDRV_DMADRV_LDMA )
154  chTable[ i ].callback = NULL;
155 #endif
156  INT_Enable();
157  return ECODE_EMDRV_DMADRV_OK;
158  }
159  }
160  INT_Enable();
162 }
163 
164 /***************************************************************************/
177 {
178  int i;
179  bool inUse;
180 
181  inUse = false;
182 
183  INT_Disable();
184  for ( i=0; i < EMDRV_DMADRV_DMA_CH_COUNT; i++ )
185  {
186  if ( chTable[ i ].allocated )
187  {
188  inUse = true;
189  break;
190  }
191  }
192 
193  if ( !inUse )
194  {
195 #if defined( EMDRV_DMADRV_UDMA )
196  NVIC_DisableIRQ( DMA_IRQn );
197  DMA->IEN = _DMA_IEN_RESETVALUE;
198  DMA->CONFIG = _DMA_CONFIG_RESETVALUE;
199  CMU_ClockEnable( cmuClock_DMA, false );
200 #elif defined( EMDRV_DMADRV_LDMA )
201  LDMA_DeInit();
202 #endif
203  initialized = false;
204  INT_Enable();
205  return ECODE_EMDRV_DMADRV_OK;
206  }
207  INT_Enable();
208 
210 }
211 
212 /***************************************************************************/
223 Ecode_t DMADRV_FreeChannel( unsigned int channelId )
224 {
225  if ( !initialized )
226  {
228  }
229 
230  if ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
231  {
233  }
234 
235  INT_Disable();
236  if ( chTable[ channelId ].allocated )
237  {
238  chTable[ channelId ].allocated = false;
239  INT_Enable();
240  return ECODE_EMDRV_DMADRV_OK;
241  }
242  INT_Enable();
243 
245 }
246 
247 /***************************************************************************/
259 {
260  int i;
261 #if defined( EMDRV_DMADRV_UDMA )
262  DMA_Init_TypeDef dmaInit;
263 #elif defined( EMDRV_DMADRV_LDMA )
264  LDMA_Init_t dmaInit = LDMA_INIT_DEFAULT;
265  dmaInit.ldmaInitCtrlNumFixed = EMDRV_DMADRV_DMA_CH_PRIORITY;
266 #endif
267 
268 
269  INT_Disable();
270  if ( initialized )
271  {
272  INT_Enable();
274  }
275  initialized = true;
276  INT_Enable();
277 
278  if ( EMDRV_DMADRV_DMA_IRQ_PRIORITY > 7 )
279  {
281  }
282 
283  for ( i=0; i < EMDRV_DMADRV_DMA_CH_COUNT; i++ )
284  {
285  chTable[ i ].allocated = false;
286  }
287 
288 #if defined( EMDRV_DMADRV_UDMA )
289  NVIC_SetPriority( DMA_IRQn, EMDRV_DMADRV_DMA_IRQ_PRIORITY );
290  dmaInit.hprot = 0;
291  dmaInit.controlBlock = dmaControlBlock;
292  DMA_Init( &dmaInit );
293 #elif defined( EMDRV_DMADRV_LDMA )
294  dmaInit.ldmaInitIrqPriority = EMDRV_DMADRV_DMA_IRQ_PRIORITY;
295  LDMA_Init( &dmaInit );
296 #endif
297 
298  return ECODE_EMDRV_DMADRV_OK;
299 }
300 
301 #if defined( EMDRV_DMADRV_LDMA ) && defined( EMDRV_DMADRV_USE_NATIVE_API )
302 /***************************************************************************/
331 Ecode_t DMADRV_LdmaStartTransfer( int channelId,
332  LDMA_TransferCfg_t *transfer,
333  LDMA_Descriptor_t *descriptor,
334  DMADRV_Callback_t callback,
335  void *cbUserParam )
336 {
337  ChTable_t *ch;
338 
339  if ( !initialized )
340  {
342  }
343 
344  if ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
345  {
347  }
348 
349  ch = &chTable[ channelId ];
350  if ( ch->allocated == false )
351  {
353  }
354 
355  ch->callback = callback;
356  ch->userParam = cbUserParam;
357  ch->callbackCount = 0;
358  LDMA_StartTransfer( channelId, transfer, descriptor );
359 
360  return ECODE_EMDRV_DMADRV_OK;
361 }
362 #endif
363 
364 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
365 /***************************************************************************/
402 Ecode_t DMADRV_MemoryPeripheral( unsigned int channelId,
403  DMADRV_PeripheralSignal_t
404  peripheralSignal,
405  void *dst,
406  void *src,
407  bool srcInc,
408  int len,
409  DMADRV_DataSize_t size,
410  DMADRV_Callback_t callback,
411  void *cbUserParam )
412 {
413  return StartTransfer( dmaModeBasic,
414  dmaDirectionMemToPeripheral,
415  channelId,
416  peripheralSignal,
417  dst,
418  src,
419  NULL,
420  srcInc,
421  len,
422  size,
423  callback,
424  cbUserParam );
425 }
426 #endif
427 
428 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
429 /***************************************************************************/
470  unsigned int channelId,
471  DMADRV_PeripheralSignal_t
472  peripheralSignal,
473  void *dst,
474  void *src0,
475  void *src1,
476  bool srcInc,
477  int len,
478  DMADRV_DataSize_t size,
479  DMADRV_Callback_t callback,
480  void *cbUserParam )
481 {
482  return StartTransfer( dmaModePingPong,
483  dmaDirectionMemToPeripheral,
484  channelId,
485  peripheralSignal,
486  dst,
487  src0,
488  src1,
489  srcInc,
490  len,
491  size,
492  callback,
493  cbUserParam );
494 }
495 #endif
496 
497 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
498 /***************************************************************************/
535 Ecode_t DMADRV_PeripheralMemory( unsigned int channelId,
536  DMADRV_PeripheralSignal_t
537  peripheralSignal,
538  void *dst,
539  void *src,
540  bool dstInc,
541  int len,
542  DMADRV_DataSize_t size,
543  DMADRV_Callback_t callback,
544  void *cbUserParam )
545 {
546  return StartTransfer( dmaModeBasic,
547  dmaDirectionPeripheralToMem,
548  channelId,
549  peripheralSignal,
550  dst,
551  src,
552  NULL,
553  dstInc,
554  len,
555  size,
556  callback,
557  cbUserParam );
558 }
559 #endif
560 
561 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
562 /***************************************************************************/
603  unsigned int channelId,
604  DMADRV_PeripheralSignal_t
605  peripheralSignal,
606  void *dst0,
607  void *dst1,
608  void *src,
609  bool dstInc,
610  int len,
611  DMADRV_DataSize_t size,
612  DMADRV_Callback_t callback,
613  void *cbUserParam )
614 {
615  return StartTransfer( dmaModePingPong,
616  dmaDirectionPeripheralToMem,
617  channelId,
618  peripheralSignal,
619  dst0,
620  dst1,
621  src,
622  dstInc,
623  len,
624  size,
625  callback,
626  cbUserParam );
627 }
628 #endif /* !defined( EMDRV_DMADRV_USE_NATIVE_API ) */
629 
630 /***************************************************************************/
641 Ecode_t DMADRV_StopTransfer( unsigned int channelId )
642 {
643  if ( !initialized )
644  {
646  }
647 
648  if ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
649  {
651  }
652 
653  if ( chTable[ channelId ].allocated == false )
654  {
656  }
657 
658 #if defined( EMDRV_DMADRV_UDMA )
659  DMA_ChannelEnable( channelId, false );
660 #elif defined( EMDRV_DMADRV_LDMA )
661  LDMA_StopTransfer( channelId );
662 #endif
663 
664  return ECODE_EMDRV_DMADRV_OK;
665 }
666 
667 /***************************************************************************/
681 Ecode_t DMADRV_TransferActive( unsigned int channelId, bool *active )
682 {
683  if ( !initialized )
684  {
686  }
687 
688  if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
689  || ( active == NULL ) )
690  {
692  }
693 
694  if ( chTable[ channelId ].allocated == false )
695  {
697  }
698 
699 #if defined( EMDRV_DMADRV_UDMA )
700  if ( DMA_ChannelEnabled( channelId ) )
701 #elif defined( EMDRV_DMADRV_LDMA )
702  if ( LDMA->CHEN & ( 1 << channelId ) )
703 #endif
704  {
705  *active = true;
706  }
707  else
708  {
709  *active = false;
710  }
711 
712  return ECODE_EMDRV_DMADRV_OK;
713 }
714 
715 /***************************************************************************/
733 Ecode_t DMADRV_TransferCompletePending( unsigned int channelId, bool *pending )
734 {
735  if ( !initialized )
736  {
738  }
739 
740  if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
741  || ( pending == NULL ) )
742  {
744  }
745 
746  if ( chTable[ channelId ].allocated == false )
747  {
749  }
750 
751 #if defined( EMDRV_DMADRV_UDMA )
752  if ( DMA->IF & ( 1 << channelId ) )
753 #elif defined( EMDRV_DMADRV_LDMA )
754  if ( LDMA->IF & ( 1 << channelId ) )
755 #endif
756  {
757  *pending = true;
758  }
759  else
760  {
761  *pending = false;
762  }
763 
764  return ECODE_EMDRV_DMADRV_OK;
765 }
766 
767 /***************************************************************************/
786 Ecode_t DMADRV_TransferDone( unsigned int channelId, bool *done )
787 {
788 #if defined( EMDRV_DMADRV_UDMA )
789  uint32_t remaining, iflag;
790 #endif
791 
792  if ( !initialized )
793  {
795  }
796 
797  if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
798  || ( done == NULL ) )
799  {
801  }
802 
803  if ( chTable[ channelId ].allocated == false )
804  {
806  }
807 
808 #if defined( EMDRV_DMADRV_UDMA )
809  INT_Disable();
810  /* This works for primary channel only ! */
811  remaining = ( dmaControlBlock[ channelId ].CTRL
814  iflag = DMA->IF;
815  INT_Enable();
816 
817  if ( ( remaining == 0 ) && ( iflag & ( 1 << channelId ) ) )
818  {
819  *done = true;
820  }
821  else
822  {
823  *done = false;
824  }
825 #elif defined( EMDRV_DMADRV_LDMA )
826  *done = LDMA_TransferDone( channelId );
827 #endif
828 
829  return ECODE_EMDRV_DMADRV_OK;
830 }
831 
832 /***************************************************************************/
852 Ecode_t DMADRV_TransferRemainingCount( unsigned int channelId,
853  int *remaining )
854 {
855 #if defined( EMDRV_DMADRV_UDMA )
856  uint32_t remain, iflag;
857 #endif
858 
859  if ( !initialized )
860  {
862  }
863 
864  if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
865  || ( remaining == NULL ) )
866  {
868  }
869 
870  if ( chTable[ channelId ].allocated == false )
871  {
873  }
874 
875 #if defined( EMDRV_DMADRV_UDMA )
876  INT_Disable();
877  /* This works for primary channel only ! */
878  remain = ( dmaControlBlock[ channelId ].CTRL
881  iflag = DMA->IF;
882  INT_Enable();
883 
884  if ( ( remain == 0 ) && ( iflag & ( 1 << channelId ) ) )
885  {
886  *remaining = 0;
887  }
888  else
889  {
890  *remaining = 1 + remain;
891  }
892 #elif defined( EMDRV_DMADRV_LDMA )
893  *remaining = LDMA_TransferRemainingCount( channelId );
894 #endif
895 
896  return ECODE_EMDRV_DMADRV_OK;
897 }
898 
900 
901 #if defined( EMDRV_DMADRV_LDMA )
902 /***************************************************************************/
906 void LDMA_IRQHandler( void )
907 {
908 #if !defined( EMDRV_DMADRV_USE_NATIVE_API )
909  bool stop;
910 #endif
911  ChTable_t *ch;
912  uint32_t pending, chnum, chmask;
913 
914  /* Get all pending and enabled interrupts */
915  pending = LDMA->IF;
916  pending &= LDMA->IEN;
917 
918  /* Check for LDMA error */
919  if ( pending & LDMA_IF_ERROR )
920  {
921  /* Loop here to enable the debugger to see what has happened */
922  while (1)
923  {
924  /* Wait forever. */
925  }
926  }
927 
928  /* Iterate over all LDMA channels. */
929  for ( chnum = 0, chmask = 1;
930  chnum < EMDRV_DMADRV_DMA_CH_COUNT;
931  chnum++, chmask <<= 1 )
932  {
933  if ( pending & chmask )
934  {
935  /* Clear interrupt flag. */
936  LDMA->IFC = chmask;
937 
938  ch = &chTable[ chnum ];
939  if ( ch->callback != NULL )
940  {
941  ch->callbackCount++;
942 #if defined( EMDRV_DMADRV_USE_NATIVE_API )
943  ch->callback( chnum, ch->callbackCount, ch->userParam );
944 #else
945  stop = !ch->callback( chnum, ch->callbackCount, ch->userParam );
946 
947  if ( ( ch->mode == dmaModePingPong ) && stop )
948  {
949  dmaXfer[ chnum ].desc[0].xfer.link = 0;
950  dmaXfer[ chnum ].desc[1].xfer.link = 0;
951  }
952 #endif
953  }
954  }
955  }
956 }
957 #endif /* defined( EMDRV_DMADRV_LDMA ) */
958 
959 #if defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
960 /***************************************************************************/
964 static void DmaBasicCallback( unsigned int channel, bool primary, void *user )
965 {
966  ChTable_t *ch = &chTable[ channel ];
967  (void)user;
968  (void)primary;
969 
970  if ( ch->callback != NULL )
971  {
972  ch->callbackCount++;
973  ch->callback( channel, ch->callbackCount, ch->userParam );
974  }
975 }
976 #endif
977 
978 #if defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
979 /***************************************************************************/
983 static void DmaPingPongCallback( unsigned int channel, bool primary, void *user )
984 {
985  bool stop = true;
986  ChTable_t *ch = &chTable[ channel ];
987 
988  (void)user;
989 
990  if ( ch->callback != NULL )
991  {
992  ch->callbackCount++;
993  stop = !ch->callback( channel, ch->callbackCount, ch->userParam );
994  }
995 
997  primary,
998  false,
999  NULL,
1000  NULL,
1001  ch->length - 1,
1002  stop );
1003 }
1004 #endif
1005 
1006 #if defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
1007 /***************************************************************************/
1011 static Ecode_t StartTransfer( DmaMode_t mode,
1012  DmaDirection_t direction,
1013  unsigned int channelId,
1014  DMADRV_PeripheralSignal_t
1015  peripheralSignal,
1016  void *buf0,
1017  void *buf1,
1018  void *buf2,
1019  bool bufInc,
1020  int len,
1021  DMADRV_DataSize_t size,
1022  DMADRV_Callback_t callback,
1023  void *cbUserParam )
1024 {
1025  ChTable_t *ch;
1026  DMA_CfgChannel_TypeDef chCfg;
1027  DMA_CfgDescr_TypeDef descrCfg;
1028 
1029  if ( !initialized )
1030  {
1032  }
1033 
1034  if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
1035  || ( buf0 == NULL )
1036  || ( buf1 == NULL )
1037  || ( len > DMADRV_MAX_XFER_COUNT )
1038  || ( ( mode == dmaModePingPong ) && ( buf2 == NULL ) ) )
1039  {
1041  }
1042 
1043  ch = &chTable[ channelId ];
1044  if ( ch->allocated == false )
1045  {
1047  }
1048 
1049  /* Setup the interrupt callback routine. */
1050  if ( mode == dmaModeBasic )
1051  {
1052  dmaCallBack[ channelId ].cbFunc = DmaBasicCallback;
1053  }
1054  else
1055  {
1056  dmaCallBack[ channelId ].cbFunc = DmaPingPongCallback;
1057  }
1058  dmaCallBack[ channelId ].userPtr = NULL;
1059 
1060  /* Setup the channel */
1061  chCfg.highPri = false; /* Can't use hi pri with peripherals. */
1062 
1063  /* Interrupt needed ? */
1064  if ( ( callback != NULL ) || ( mode == dmaModePingPong ) )
1065  {
1066  chCfg.enableInt = true;
1067  }
1068  else
1069  {
1070  chCfg.enableInt = false;
1071  }
1072  chCfg.select = peripheralSignal;
1073  chCfg.cb = &dmaCallBack[ channelId ];
1074  DMA_CfgChannel( channelId, &chCfg );
1075 
1076  /* Setup channel descriptor. */
1077  if ( direction == dmaDirectionMemToPeripheral )
1078  {
1079  if ( bufInc )
1080  {
1081  if ( size == dmadrvDataSize1 )
1082  {
1083  descrCfg.srcInc = dmaDataInc1;
1084  }
1085  else if ( size == dmadrvDataSize2 )
1086  {
1087  descrCfg.srcInc = dmaDataInc2;
1088  }
1089  else /* dmadrvDataSize4 */
1090  {
1091  descrCfg.srcInc = dmaDataInc4;
1092  }
1093  }
1094  else
1095  {
1096  descrCfg.srcInc = dmaDataIncNone;
1097  }
1098  descrCfg.dstInc = dmaDataIncNone;
1099  }
1100  else
1101  {
1102  if ( bufInc )
1103  {
1104  if ( size == dmadrvDataSize1 )
1105  {
1106  descrCfg.dstInc = dmaDataInc1;
1107  }
1108  else if ( size == dmadrvDataSize2 )
1109  {
1110  descrCfg.dstInc = dmaDataInc2;
1111  }
1112  else /* dmadrvDataSize4 */
1113  {
1114  descrCfg.dstInc = dmaDataInc4;
1115  }
1116  }
1117  else
1118  {
1119  descrCfg.dstInc = dmaDataIncNone;
1120  }
1121  descrCfg.srcInc = dmaDataIncNone;
1122  }
1123  descrCfg.size = (DMA_DataSize_TypeDef)size;
1124  descrCfg.arbRate = dmaArbitrate1;
1125  descrCfg.hprot = 0;
1126  DMA_CfgDescr( channelId, true, &descrCfg );
1127  if ( mode == dmaModePingPong )
1128  {
1129  DMA_CfgDescr( channelId, false, &descrCfg );
1130  }
1131 
1132  ch->callback = callback;
1133  ch->userParam = cbUserParam;
1134  ch->callbackCount = 0;
1135  ch->length = len;
1136 
1137  DMA->IFC = 1 << channelId;
1138 
1139  /* Start DMA cycle. */
1140  if ( mode == dmaModeBasic )
1141  {
1142  DMA_ActivateBasic( channelId, true, false, buf0, buf1, len - 1 );
1143  }
1144  else
1145  {
1146  if ( direction == dmaDirectionMemToPeripheral )
1147  {
1148  DMA_ActivatePingPong( channelId,
1149  false,
1150  buf0, /* dest */
1151  buf1, /* src */
1152  len - 1,
1153  buf0, /* dest */
1154  buf2, /* src */
1155  len - 1);
1156  }
1157  else
1158  {
1159  DMA_ActivatePingPong( channelId,
1160  false,
1161  buf0, /* dest */
1162  buf2, /* src */
1163  len - 1,
1164  buf1, /* dest */
1165  buf2, /* src */
1166  len - 1);
1167  }
1168  }
1169 
1170  return ECODE_EMDRV_DMADRV_OK;
1171 }
1172 #endif /* defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API ) */
1173 
1174 #if defined( EMDRV_DMADRV_LDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
1175 /***************************************************************************/
1179 static Ecode_t StartTransfer( DmaMode_t mode,
1180  DmaDirection_t direction,
1181  unsigned int channelId,
1182  DMADRV_PeripheralSignal_t
1183  peripheralSignal,
1184  void *buf0,
1185  void *buf1,
1186  void *buf2,
1187  bool bufInc,
1188  int len,
1189  DMADRV_DataSize_t size,
1190  DMADRV_Callback_t callback,
1191  void *cbUserParam )
1192 {
1193  ChTable_t *ch;
1194  LDMA_TransferCfg_t xfer;
1195  LDMA_Descriptor_t *desc;
1196 
1197  if ( !initialized )
1198  {
1200  }
1201 
1202  if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
1203  || ( buf0 == NULL )
1204  || ( buf1 == NULL )
1205  || ( len > DMADRV_MAX_XFER_COUNT )
1206  || ( ( mode == dmaModePingPong ) && ( buf2 == NULL ) ) )
1207  {
1209  }
1210 
1211  ch = &chTable[ channelId ];
1212  if ( ch->allocated == false )
1213  {
1215  }
1216 
1217  xfer = xferCfg;
1218  desc = &dmaXfer[ channelId ].desc[0];
1219 
1220  if ( direction == dmaDirectionMemToPeripheral )
1221  {
1222  *desc = m2p;
1223  if ( !bufInc )
1224  {
1225  desc->xfer.srcInc = ldmaCtrlSrcIncNone;
1226  }
1227  }
1228  else
1229  {
1230  *desc = p2m;
1231  if ( !bufInc )
1232  {
1233  desc->xfer.dstInc = ldmaCtrlDstIncNone;
1234  }
1235  }
1236  xfer.ldmaReqSel = peripheralSignal;
1237  desc->xfer.xferCnt = len - 1;
1238  desc->xfer.dstAddr = (uint32_t)buf0;
1239  desc->xfer.srcAddr = (uint32_t)buf1;
1240  desc->xfer.size = size;
1241 
1242  if ( mode == dmaModePingPong )
1243  {
1244  desc->xfer.linkMode = ldmaLinkModeRel;
1245  desc->xfer.link = 1;
1246  desc->xfer.linkAddr = 4; /* Refer to "pong" descriptor. */
1247 
1248  /* Set the "pong" descriptor equal to the "ping" descriptor. */
1249  dmaXfer[ channelId ].desc[1] = *desc;
1250  /* Refer to "ping" descriptor. */
1251  dmaXfer[ channelId ].desc[1].xfer.linkAddr = -4;
1252  dmaXfer[ channelId ].desc[1].xfer.srcAddr = (uint32_t)buf2;
1253 
1254  if ( direction == dmaDirectionPeripheralToMem )
1255  {
1256  dmaXfer[ channelId ].desc[1].xfer.dstAddr = (uint32_t)buf1;
1257  desc->xfer.srcAddr = (uint32_t)buf2;
1258  }
1259  }
1260 
1261  /* Interrupt needed ? */
1262  if ( ( callback == NULL ) && ( mode == dmaModeBasic ) )
1263  {
1264  desc->xfer.doneIfs = 0;
1265  }
1266 
1267  ch->callback = callback;
1268  ch->userParam = cbUserParam;
1269  ch->callbackCount = 0;
1270  ch->mode = mode;
1271 
1272  LDMA_StartTransfer( channelId, &xfer, desc );
1273 
1274  return ECODE_EMDRV_DMADRV_OK;
1275 }
1276 #endif /* defined( EMDRV_DMADRV_LDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API ) */
1277 
1279 
1280 
1281 /******** THE REST OF THE FILE IS DOCUMENTATION ONLY !**********************/
Clock management unit (CMU) API.
#define _DMA_CTRL_N_MINUS_1_MASK
DMADRV API definition.
DMA_ArbiterConfig_TypeDef arbRate
Definition: em_dma.h:231
Ecode_t DMADRV_PeripheralMemory(unsigned int channelId, DMADRV_PeripheralSignal_t peripheralSignal, void *dst, void *src, bool dstInc, int len, DMADRV_DataSize_t size, DMADRV_Callback_t callback, void *cbUserParam)
Start a peripheral to memory DMA transfer.
Definition: dmadrv.c:535
DMA_DataInc_TypeDef dstInc
Definition: em_dma.h:219
Callback structure that can be used to define DMA complete actions.
Definition: em_dma.h:148
Ecode_t DMADRV_TransferActive(unsigned int channelId, bool *active)
Check if a transfer is running.
Definition: dmadrv.c:681
static bool initialized
bool(* DMADRV_Callback_t)(unsigned int channel, unsigned int sequenceNo, void *userParam)
DMADRV transfer completion callback function.
Definition: dmadrv.h:81
void DMA_RefreshPingPong(unsigned int channel, bool primary, bool useBurst, void *dst, void *src, unsigned int nMinus1, bool last)
Refresh a descriptor used in a DMA ping-pong cycle.
Definition: em_dma.c:1111
__STATIC_INLINE uint32_t INT_Enable(void)
Enable interrupts.
Definition: em_int.h:94
Ecode_t DMADRV_StopTransfer(unsigned int channelId)
Stop an ongoing DMA transfer.
Definition: dmadrv.c:641
DMA_CB_TypeDef * cb
User definable callback handling configuration.
Definition: em_dma.h:208
Halfword.
Definition: dmadrv.h:299
#define ECODE_EMDRV_DMADRV_NOT_INITIALIZED
DMA is not initialized.
Definition: dmadrv.h:53
CMSIS Cortex-M Peripheral Access Layer for Silicon Laboratories microcontroller devices.
#define _DMA_IEN_RESETVALUE
Definition: efm32lg_dma.h:1276
#define DMA
bool DMA_ChannelEnabled(unsigned int channel)
Check if DMA channel is enabled.
Definition: em_dma.c:1008
#define ECODE_EMDRV_DMADRV_ALREADY_FREED
DMA channel was free.
Definition: dmadrv.h:57
Ecode_t DMADRV_TransferDone(unsigned int channelId, bool *done)
Check if a transfer has completed.
Definition: dmadrv.c:786
Byte.
Definition: dmadrv.h:298
#define _DMA_CTRL_N_MINUS_1_SHIFT
Ecode_t DMADRV_TransferRemainingCount(unsigned int channelId, int *remaining)
Get number of items remaining in a transfer.
Definition: dmadrv.c:852
Interrupt enable/disable unit API.
void DMA_ActivatePingPong(unsigned int channel, bool useBurst, void *primDst, void *primSrc, unsigned int primNMinus1, void *altDst, void *altSrc, unsigned int altNMinus1)
Activate DMA ping-pong cycle (used for memory-peripheral transfers).
Definition: em_dma.c:526
#define ECODE_EMDRV_DMADRV_CH_NOT_ALLOCATED
The channel is not reserved.
Definition: dmadrv.h:58
void DMA_ActivateBasic(unsigned int channel, bool primary, bool useBurst, void *dst, void *src, unsigned int nMinus1)
Activate DMA basic cycle (used for memory-peripheral transfers).
Definition: em_dma.c:454
#define ECODE_EMDRV_DMADRV_CHANNELS_EXHAUSTED
No DMA channels available.
Definition: dmadrv.h:55
void DMA_Init(DMA_Init_TypeDef *init)
Initializes DMA controller.
Definition: em_dma.c:1033
void DMA_CfgChannel(unsigned int channel, DMA_CfgChannel_TypeDef *cfg)
Configure a DMA channel.
Definition: em_dma.c:706
Ecode_t DMADRV_MemoryPeripheralPingPong(unsigned int channelId, DMADRV_PeripheralSignal_t peripheralSignal, void *dst, void *src0, void *src1, bool srcInc, int len, DMADRV_DataSize_t size, DMADRV_Callback_t callback, void *cbUserParam)
Start a memory to peripheral ping-pong DMA transfer.
Definition: dmadrv.c:469
DMA_DESCRIPTOR_TypeDef dmaControlBlock[DMACTRL_CH_CNT *2]
Definition: dmactrl.c:48
#define DMADRV_MAX_XFER_COUNT
Maximum length of one DMA transfer.
Definition: dmadrv.h:88
DMA_DataSize_TypeDef size
Definition: em_dma.h:225
void CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)
Enable/disable a clock.
Definition: em_cmu.c:1369
Ecode_t DMADRV_Init(void)
Initialize DMADRV.
Definition: dmadrv.c:258
DMA_DataInc_TypeDef srcInc
Definition: em_dma.h:222
#define ECODE_EMDRV_DMADRV_OK
Success return value.
Definition: dmadrv.h:51
Ecode_t DMADRV_DeInit(void)
Deinitialize DMADRV.
Definition: dmadrv.c:176
#define _DMA_CONFIG_RESETVALUE
Definition: efm32lg_dma.h:130
#define ECODE_EMDRV_DMADRV_IN_USE
DMA is in use.
Definition: dmadrv.h:56
DMA_DataSize_TypeDef
Definition: em_dma.h:74
Ecode_t DMADRV_AllocateChannel(unsigned int *channelId, void *capabilities)
Allocate (reserve) a DMA channel.
Definition: dmadrv.c:131
void * userPtr
Definition: em_dma.h:158
#define ECODE_EMDRV_DMADRV_ALREADY_INITIALIZED
DMA has already been initialized.
Definition: dmadrv.h:54
Ecode_t DMADRV_MemoryPeripheral(unsigned int channelId, DMADRV_PeripheralSignal_t peripheralSignal, void *dst, void *src, bool srcInc, int len, DMADRV_DataSize_t size, DMADRV_Callback_t callback, void *cbUserParam)
Start a memory to peripheral DMA transfer.
Definition: dmadrv.c:402
#define ECODE_EMDRV_DMADRV_PARAM_ERROR
Illegal input parameter.
Definition: dmadrv.h:52
DMA_FuncPtr_TypeDef cbFunc
Definition: em_dma.h:155
uint32_t Ecode_t
Typedef for API function errorcode return values.
Definition: ecode.h:31
Ecode_t DMADRV_TransferCompletePending(unsigned int channelId, bool *pending)
Check if a transfer complete is pending.
Definition: dmadrv.c:733
__STATIC_INLINE uint32_t INT_Disable(void)
Disable interrupts.
Definition: em_int.h:71
Ecode_t DMADRV_PeripheralMemoryPingPong(unsigned int channelId, DMADRV_PeripheralSignal_t peripheralSignal, void *dst0, void *dst1, void *src, bool dstInc, int len, DMADRV_DataSize_t size, DMADRV_Callback_t callback, void *cbUserParam)
Start a peripheral to memory ping-pong DMA transfer.
Definition: dmadrv.c:602
DMA control data block.
Ecode_t DMADRV_FreeChannel(unsigned int channelId)
Free an allocate (reserved) DMA channel.
Definition: dmadrv.c:223
void DMA_ChannelEnable(unsigned int channel, bool enable)
Enable or disable a DMA channel.
Definition: em_dma.c:979
void DMA_CfgDescr(unsigned int channel, bool primary, DMA_CfgDescr_TypeDef *cfg)
Configure DMA descriptor for auto-request, basic or ping-pong DMA cycles.
Definition: em_dma.c:781