EFR32 Mighty Gecko 1 Software Documentation  efr32mg1-doc-5.1.2
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_core.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 )
88 const LDMA_Descriptor_t m2p = LDMA_DESCRIPTOR_SINGLE_M2P_BYTE( NULL, NULL, 1UL );
89 const LDMA_Descriptor_t p2m = LDMA_DESCRIPTOR_SINGLE_P2M_BYTE( NULL, NULL, 1UL );
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,
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;
136 
137  if ( !initialized )
138  {
140  }
141 
142  if ( channelId == NULL )
143  {
145  }
146 
148  for ( i=0; i < EMDRV_DMADRV_DMA_CH_COUNT; i++ )
149  {
150  if ( !chTable[ i ].allocated )
151  {
152  *channelId = i;
153  chTable[ i ].allocated = true;
154 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( EMDRV_DMADRV_LDMA )
155  chTable[ i ].callback = NULL;
156 #endif
158  return ECODE_EMDRV_DMADRV_OK;
159  }
160  }
163 }
164 
165 /***************************************************************************/
178 {
179  int i;
180  bool inUse;
182 
183  inUse = false;
184 
186  for ( i=0; i < EMDRV_DMADRV_DMA_CH_COUNT; i++ )
187  {
188  if ( chTable[ i ].allocated )
189  {
190  inUse = true;
191  break;
192  }
193  }
194 
195  if ( !inUse )
196  {
197 #if defined( EMDRV_DMADRV_UDMA )
198  NVIC_DisableIRQ( DMA_IRQn );
199  DMA->IEN = _DMA_IEN_RESETVALUE;
200  DMA->CONFIG = _DMA_CONFIG_RESETVALUE;
201  CMU_ClockEnable( cmuClock_DMA, false );
202 #elif defined( EMDRV_DMADRV_LDMA )
203  LDMA_DeInit();
204 #endif
205  initialized = false;
207  return ECODE_EMDRV_DMADRV_OK;
208  }
210 
212 }
213 
214 /***************************************************************************/
225 Ecode_t DMADRV_FreeChannel( unsigned int channelId )
226 {
228 
229  if ( !initialized )
230  {
232  }
233 
234  if ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
235  {
237  }
238 
240  if ( chTable[ channelId ].allocated )
241  {
242  chTable[ channelId ].allocated = false;
244  return ECODE_EMDRV_DMADRV_OK;
245  }
247 
249 }
250 
251 /***************************************************************************/
263 {
264  int i;
266 #if defined( EMDRV_DMADRV_UDMA )
267  DMA_Init_TypeDef dmaInit;
268 #elif defined( EMDRV_DMADRV_LDMA )
269  LDMA_Init_t dmaInit = LDMA_INIT_DEFAULT;
270  dmaInit.ldmaInitCtrlNumFixed = EMDRV_DMADRV_DMA_CH_PRIORITY;
271 #endif
272 
274  if ( initialized )
275  {
278  }
279  initialized = true;
281 
282  if ( EMDRV_DMADRV_DMA_IRQ_PRIORITY > 7 )
283  {
285  }
286 
287  for ( i=0; i < EMDRV_DMADRV_DMA_CH_COUNT; i++ )
288  {
289  chTable[ i ].allocated = false;
290  }
291 
292 #if defined( EMDRV_DMADRV_UDMA )
293  NVIC_SetPriority( DMA_IRQn, EMDRV_DMADRV_DMA_IRQ_PRIORITY );
294  dmaInit.hprot = 0;
295  dmaInit.controlBlock = dmaControlBlock;
296  DMA_Init( &dmaInit );
297 #elif defined( EMDRV_DMADRV_LDMA )
298  dmaInit.ldmaInitIrqPriority = EMDRV_DMADRV_DMA_IRQ_PRIORITY;
299  LDMA_Init( &dmaInit );
300 #endif
301 
302  return ECODE_EMDRV_DMADRV_OK;
303 }
304 
305 #if defined( EMDRV_DMADRV_LDMA ) && defined( EMDRV_DMADRV_USE_NATIVE_API )
306 /***************************************************************************/
336  LDMA_TransferCfg_t *transfer,
337  LDMA_Descriptor_t *descriptor,
338  DMADRV_Callback_t callback,
339  void *cbUserParam )
340 {
341  ChTable_t *ch;
342 
343  if ( !initialized )
344  {
346  }
347 
348  if ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
349  {
351  }
352 
353  ch = &chTable[ channelId ];
354  if ( ch->allocated == false )
355  {
357  }
358 
359  ch->callback = callback;
360  ch->userParam = cbUserParam;
361  ch->callbackCount = 0;
362  LDMA_StartTransfer( channelId, transfer, descriptor );
363 
364  return ECODE_EMDRV_DMADRV_OK;
365 }
366 #endif
367 
368 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
369 /***************************************************************************/
406 Ecode_t DMADRV_MemoryPeripheral( unsigned int channelId,
408  peripheralSignal,
409  void *dst,
410  void *src,
411  bool srcInc,
412  int len,
413  DMADRV_DataSize_t size,
414  DMADRV_Callback_t callback,
415  void *cbUserParam )
416 {
417  return StartTransfer( dmaModeBasic,
418  dmaDirectionMemToPeripheral,
419  channelId,
420  peripheralSignal,
421  dst,
422  src,
423  NULL,
424  srcInc,
425  len,
426  size,
427  callback,
428  cbUserParam );
429 }
430 #endif
431 
432 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
433 /***************************************************************************/
474  unsigned int channelId,
476  peripheralSignal,
477  void *dst,
478  void *src0,
479  void *src1,
480  bool srcInc,
481  int len,
482  DMADRV_DataSize_t size,
483  DMADRV_Callback_t callback,
484  void *cbUserParam )
485 {
486  return StartTransfer( dmaModePingPong,
487  dmaDirectionMemToPeripheral,
488  channelId,
489  peripheralSignal,
490  dst,
491  src0,
492  src1,
493  srcInc,
494  len,
495  size,
496  callback,
497  cbUserParam );
498 }
499 #endif
500 
501 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
502 /***************************************************************************/
539 Ecode_t DMADRV_PeripheralMemory( unsigned int channelId,
541  peripheralSignal,
542  void *dst,
543  void *src,
544  bool dstInc,
545  int len,
546  DMADRV_DataSize_t size,
547  DMADRV_Callback_t callback,
548  void *cbUserParam )
549 {
550  return StartTransfer( dmaModeBasic,
551  dmaDirectionPeripheralToMem,
552  channelId,
553  peripheralSignal,
554  dst,
555  src,
556  NULL,
557  dstInc,
558  len,
559  size,
560  callback,
561  cbUserParam );
562 }
563 #endif
564 
565 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
566 /***************************************************************************/
607  unsigned int channelId,
609  peripheralSignal,
610  void *dst0,
611  void *dst1,
612  void *src,
613  bool dstInc,
614  int len,
615  DMADRV_DataSize_t size,
616  DMADRV_Callback_t callback,
617  void *cbUserParam )
618 {
619  return StartTransfer( dmaModePingPong,
620  dmaDirectionPeripheralToMem,
621  channelId,
622  peripheralSignal,
623  dst0,
624  dst1,
625  src,
626  dstInc,
627  len,
628  size,
629  callback,
630  cbUserParam );
631 }
632 #endif /* !defined( EMDRV_DMADRV_USE_NATIVE_API ) */
633 
634 /***************************************************************************/
645 Ecode_t DMADRV_PauseTransfer( unsigned int channelId )
646 {
647  if ( !initialized )
648  {
650  }
651 
652  if ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
653  {
655  }
656 
657  if ( chTable[ channelId ].allocated == false )
658  {
660  }
661 
662 #if defined( EMDRV_DMADRV_UDMA )
663  DMA_ChannelRequestEnable( channelId, false );
664 #elif defined( EMDRV_DMADRV_LDMA )
665  LDMA_EnableChannelRequest( channelId, false );
666 #endif
667 
668  return ECODE_EMDRV_DMADRV_OK;
669 }
670 
671 /***************************************************************************/
682 Ecode_t DMADRV_ResumeTransfer( unsigned int channelId )
683 {
684  if ( !initialized )
685  {
687  }
688 
689  if ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
690  {
692  }
693 
694  if ( chTable[ channelId ].allocated == false )
695  {
697  }
698 
699 #if defined( EMDRV_DMADRV_UDMA )
700  DMA_ChannelRequestEnable( channelId, true );
701 #elif defined( EMDRV_DMADRV_LDMA )
702  LDMA_EnableChannelRequest( channelId, true );
703 #endif
704 
705  return ECODE_EMDRV_DMADRV_OK;
706 }
707 
708 /***************************************************************************/
719 Ecode_t DMADRV_StopTransfer( unsigned int channelId )
720 {
721  if ( !initialized )
722  {
724  }
725 
726  if ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
727  {
729  }
730 
731  if ( chTable[ channelId ].allocated == false )
732  {
734  }
735 
736 #if defined( EMDRV_DMADRV_UDMA )
737  DMA_ChannelEnable( channelId, false );
738 #elif defined( EMDRV_DMADRV_LDMA )
739  LDMA_StopTransfer( channelId );
740 #endif
741 
742  return ECODE_EMDRV_DMADRV_OK;
743 }
744 
745 /***************************************************************************/
759 Ecode_t DMADRV_TransferActive( unsigned int channelId, bool *active )
760 {
761  if ( !initialized )
762  {
764  }
765 
766  if ( ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
767  || ( active == NULL ) )
768  {
770  }
771 
772  if ( chTable[ channelId ].allocated == false )
773  {
775  }
776 
777 #if defined( EMDRV_DMADRV_UDMA )
778  if ( DMA_ChannelEnabled( channelId ) )
779 #elif defined( EMDRV_DMADRV_LDMA )
780  if ( LDMA->CHEN & ( 1 << channelId ) )
781 #endif
782  {
783  *active = true;
784  }
785  else
786  {
787  *active = false;
788  }
789 
790  return ECODE_EMDRV_DMADRV_OK;
791 }
792 
793 /***************************************************************************/
811 Ecode_t DMADRV_TransferCompletePending( unsigned int channelId, bool *pending )
812 {
813  if ( !initialized )
814  {
816  }
817 
818  if ( ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
819  || ( pending == NULL ) )
820  {
822  }
823 
824  if ( chTable[ channelId ].allocated == false )
825  {
827  }
828 
829 #if defined( EMDRV_DMADRV_UDMA )
830  if ( DMA->IF & ( 1 << channelId ) )
831 #elif defined( EMDRV_DMADRV_LDMA )
832  if ( LDMA->IF & ( 1 << channelId ) )
833 #endif
834  {
835  *pending = true;
836  }
837  else
838  {
839  *pending = false;
840  }
841 
842  return ECODE_EMDRV_DMADRV_OK;
843 }
844 
845 /***************************************************************************/
864 Ecode_t DMADRV_TransferDone( unsigned int channelId, bool *done )
865 {
866 #if defined( EMDRV_DMADRV_UDMA )
867  uint32_t remaining, iflag;
868 #endif
869 
870  if ( !initialized )
871  {
873  }
874 
875  if ( ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
876  || ( done == NULL ) )
877  {
879  }
880 
881  if ( chTable[ channelId ].allocated == false )
882  {
884  }
885 
886 #if defined( EMDRV_DMADRV_UDMA )
888  /* This works for primary channel only ! */
889  remaining = ( dmaControlBlock[ channelId ].CTRL
890  & _DMA_CTRL_N_MINUS_1_MASK )
891  >> _DMA_CTRL_N_MINUS_1_SHIFT;
892  iflag = DMA->IF;
893  )
894 
895  if ( ( remaining == 0 ) && ( iflag & ( 1 << channelId ) ) )
896  {
897  *done = true;
898  }
899  else
900  {
901  *done = false;
902  }
903 #elif defined( EMDRV_DMADRV_LDMA )
904  *done = LDMA_TransferDone( channelId );
905 #endif
906 
907  return ECODE_EMDRV_DMADRV_OK;
908 }
909 
910 /***************************************************************************/
930 Ecode_t DMADRV_TransferRemainingCount( unsigned int channelId,
931  int *remaining )
932 {
933 #if defined( EMDRV_DMADRV_UDMA )
934  uint32_t remain, iflag;
935 #endif
936 
937  if ( !initialized )
938  {
940  }
941 
942  if ( ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
943  || ( remaining == NULL ) )
944  {
946  }
947 
948  if ( chTable[ channelId ].allocated == false )
949  {
951  }
952 
953 #if defined( EMDRV_DMADRV_UDMA )
955  /* This works for primary channel only ! */
956  remain = ( dmaControlBlock[ channelId ].CTRL
957  & _DMA_CTRL_N_MINUS_1_MASK )
958  >> _DMA_CTRL_N_MINUS_1_SHIFT;
959  iflag = DMA->IF;
960  )
961 
962  if ( ( remain == 0 ) && ( iflag & ( 1 << channelId ) ) )
963  {
964  *remaining = 0;
965  }
966  else
967  {
968  *remaining = 1 + remain;
969  }
970 #elif defined( EMDRV_DMADRV_LDMA )
971  *remaining = LDMA_TransferRemainingCount( channelId );
972 #endif
973 
974  return ECODE_EMDRV_DMADRV_OK;
975 }
976 
978 
979 #if defined( EMDRV_DMADRV_LDMA )
980 /***************************************************************************/
984 void LDMA_IRQHandler( void )
985 {
986 #if !defined( EMDRV_DMADRV_USE_NATIVE_API )
987  bool stop;
988 #endif
989  ChTable_t *ch;
990  uint32_t pending, chnum, chmask;
991 
992  /* Get all pending and enabled interrupts */
993  pending = LDMA->IF;
994  pending &= LDMA->IEN;
995 
996  /* Check for LDMA error */
997  if ( pending & LDMA_IF_ERROR )
998  {
999  /* Loop here to enable the debugger to see what has happened */
1000  while (1)
1001  {
1002  /* Wait forever. */
1003  }
1004  }
1005 
1006  /* Iterate over all LDMA channels. */
1007  for ( chnum = 0, chmask = 1;
1008  chnum < EMDRV_DMADRV_DMA_CH_COUNT;
1009  chnum++, chmask <<= 1 )
1010  {
1011  if ( pending & chmask )
1012  {
1013  /* Clear interrupt flag. */
1014  LDMA->IFC = chmask;
1015 
1016  ch = &chTable[ chnum ];
1017  if ( ch->callback != NULL )
1018  {
1019  ch->callbackCount++;
1020 #if defined( EMDRV_DMADRV_USE_NATIVE_API )
1021  ch->callback( chnum, ch->callbackCount, ch->userParam );
1022 #else
1023  stop = !ch->callback( chnum, ch->callbackCount, ch->userParam );
1024 
1025  if ( ( ch->mode == dmaModePingPong ) && stop )
1026  {
1027  dmaXfer[ chnum ].desc[0].xfer.link = 0;
1028  dmaXfer[ chnum ].desc[1].xfer.link = 0;
1029  }
1030 #endif
1031  }
1032  }
1033  }
1034 }
1035 #endif /* defined( EMDRV_DMADRV_LDMA ) */
1036 
1037 #if defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
1038 /***************************************************************************/
1042 static void DmaBasicCallback( unsigned int channel, bool primary, void *user )
1043 {
1044  ChTable_t *ch = &chTable[ channel ];
1045  (void)user;
1046  (void)primary;
1047 
1048  if ( ch->callback != NULL )
1049  {
1050  ch->callbackCount++;
1051  ch->callback( channel, ch->callbackCount, ch->userParam );
1052  }
1053 }
1054 #endif
1055 
1056 #if defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
1057 /***************************************************************************/
1061 static void DmaPingPongCallback( unsigned int channel, bool primary, void *user )
1062 {
1063  bool stop = true;
1064  ChTable_t *ch = &chTable[ channel ];
1065 
1066  (void)user;
1067 
1068  if ( ch->callback != NULL )
1069  {
1070  ch->callbackCount++;
1071  stop = !ch->callback( channel, ch->callbackCount, ch->userParam );
1072  }
1073 
1074  DMA_RefreshPingPong( 0,
1075  primary,
1076  false,
1077  NULL,
1078  NULL,
1079  ch->length - 1,
1080  stop );
1081 }
1082 #endif
1083 
1084 #if defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
1085 /***************************************************************************/
1089 static Ecode_t StartTransfer( DmaMode_t mode,
1090  DmaDirection_t direction,
1091  unsigned int channelId,
1093  peripheralSignal,
1094  void *buf0,
1095  void *buf1,
1096  void *buf2,
1097  bool bufInc,
1098  int len,
1099  DMADRV_DataSize_t size,
1100  DMADRV_Callback_t callback,
1101  void *cbUserParam )
1102 {
1103  ChTable_t *ch;
1104  DMA_CfgChannel_TypeDef chCfg;
1105  DMA_CfgDescr_TypeDef descrCfg;
1106 
1107  if ( !initialized )
1108  {
1110  }
1111 
1112  if ( ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
1113  || ( buf0 == NULL )
1114  || ( buf1 == NULL )
1115  || ( len > DMADRV_MAX_XFER_COUNT )
1116  || ( ( mode == dmaModePingPong ) && ( buf2 == NULL ) ) )
1117  {
1119  }
1120 
1121  ch = &chTable[ channelId ];
1122  if ( ch->allocated == false )
1123  {
1125  }
1126 
1127  /* Setup the interrupt callback routine. */
1128  if ( mode == dmaModeBasic )
1129  {
1130  dmaCallBack[ channelId ].cbFunc = DmaBasicCallback;
1131  }
1132  else
1133  {
1134  dmaCallBack[ channelId ].cbFunc = DmaPingPongCallback;
1135  }
1136  dmaCallBack[ channelId ].userPtr = NULL;
1137 
1138  /* Setup the channel */
1139  chCfg.highPri = false; /* Can't use hi pri with peripherals. */
1140 
1141  /* Interrupt needed ? */
1142  if ( ( callback != NULL ) || ( mode == dmaModePingPong ) )
1143  {
1144  chCfg.enableInt = true;
1145  }
1146  else
1147  {
1148  chCfg.enableInt = false;
1149  }
1150  chCfg.select = peripheralSignal;
1151  chCfg.cb = &dmaCallBack[ channelId ];
1152  DMA_CfgChannel( channelId, &chCfg );
1153 
1154  /* Setup channel descriptor. */
1155  if ( direction == dmaDirectionMemToPeripheral )
1156  {
1157  if ( bufInc )
1158  {
1159  if ( size == dmadrvDataSize1 )
1160  {
1161  descrCfg.srcInc = dmaDataInc1;
1162  }
1163  else if ( size == dmadrvDataSize2 )
1164  {
1165  descrCfg.srcInc = dmaDataInc2;
1166  }
1167  else /* dmadrvDataSize4 */
1168  {
1169  descrCfg.srcInc = dmaDataInc4;
1170  }
1171  }
1172  else
1173  {
1174  descrCfg.srcInc = dmaDataIncNone;
1175  }
1176  descrCfg.dstInc = dmaDataIncNone;
1177  }
1178  else
1179  {
1180  if ( bufInc )
1181  {
1182  if ( size == dmadrvDataSize1 )
1183  {
1184  descrCfg.dstInc = dmaDataInc1;
1185  }
1186  else if ( size == dmadrvDataSize2 )
1187  {
1188  descrCfg.dstInc = dmaDataInc2;
1189  }
1190  else /* dmadrvDataSize4 */
1191  {
1192  descrCfg.dstInc = dmaDataInc4;
1193  }
1194  }
1195  else
1196  {
1197  descrCfg.dstInc = dmaDataIncNone;
1198  }
1199  descrCfg.srcInc = dmaDataIncNone;
1200  }
1201  descrCfg.size = (DMA_DataSize_TypeDef)size;
1202  descrCfg.arbRate = dmaArbitrate1;
1203  descrCfg.hprot = 0;
1204  DMA_CfgDescr( channelId, true, &descrCfg );
1205  if ( mode == dmaModePingPong )
1206  {
1207  DMA_CfgDescr( channelId, false, &descrCfg );
1208  }
1209 
1210  ch->callback = callback;
1211  ch->userParam = cbUserParam;
1212  ch->callbackCount = 0;
1213  ch->length = len;
1214 
1215  DMA->IFC = 1 << channelId;
1216 
1217  /* Start DMA cycle. */
1218  if ( mode == dmaModeBasic )
1219  {
1220  DMA_ActivateBasic( channelId, true, false, buf0, buf1, len - 1 );
1221  }
1222  else
1223  {
1224  if ( direction == dmaDirectionMemToPeripheral )
1225  {
1226  DMA_ActivatePingPong( channelId,
1227  false,
1228  buf0, /* dest */
1229  buf1, /* src */
1230  len - 1,
1231  buf0, /* dest */
1232  buf2, /* src */
1233  len - 1);
1234  }
1235  else
1236  {
1237  DMA_ActivatePingPong( channelId,
1238  false,
1239  buf0, /* dest */
1240  buf2, /* src */
1241  len - 1,
1242  buf1, /* dest */
1243  buf2, /* src */
1244  len - 1);
1245  }
1246  }
1247 
1248  return ECODE_EMDRV_DMADRV_OK;
1249 }
1250 #endif /* defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API ) */
1251 
1252 #if defined( EMDRV_DMADRV_LDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
1253 /***************************************************************************/
1257 static Ecode_t StartTransfer( DmaMode_t mode,
1258  DmaDirection_t direction,
1259  unsigned int channelId,
1261  peripheralSignal,
1262  void *buf0,
1263  void *buf1,
1264  void *buf2,
1265  bool bufInc,
1266  int len,
1267  DMADRV_DataSize_t size,
1268  DMADRV_Callback_t callback,
1269  void *cbUserParam )
1270 {
1271  ChTable_t *ch;
1272  LDMA_TransferCfg_t xfer;
1273  LDMA_Descriptor_t *desc;
1274 
1275  if ( !initialized )
1276  {
1278  }
1279 
1280  if ( ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
1281  || ( buf0 == NULL )
1282  || ( buf1 == NULL )
1283  || ( len > DMADRV_MAX_XFER_COUNT )
1284  || ( ( mode == dmaModePingPong ) && ( buf2 == NULL ) ) )
1285  {
1287  }
1288 
1289  ch = &chTable[ channelId ];
1290  if ( ch->allocated == false )
1291  {
1293  }
1294 
1295  xfer = xferCfg;
1296  desc = &dmaXfer[ channelId ].desc[0];
1297 
1298  if ( direction == dmaDirectionMemToPeripheral )
1299  {
1300  *desc = m2p;
1301  if ( !bufInc )
1302  {
1303  desc->xfer.srcInc = ldmaCtrlSrcIncNone;
1304  }
1305  }
1306  else
1307  {
1308  *desc = p2m;
1309  if ( !bufInc )
1310  {
1311  desc->xfer.dstInc = ldmaCtrlDstIncNone;
1312  }
1313  }
1314  xfer.ldmaReqSel = peripheralSignal;
1315  desc->xfer.xferCnt = len - 1;
1316  desc->xfer.dstAddr = (uint32_t)buf0;
1317  desc->xfer.srcAddr = (uint32_t)buf1;
1318  desc->xfer.size = size;
1319 
1320  if ( mode == dmaModePingPong )
1321  {
1322  desc->xfer.linkMode = ldmaLinkModeRel;
1323  desc->xfer.link = 1;
1324  desc->xfer.linkAddr = 4; /* Refer to "pong" descriptor. */
1325 
1326  /* Set the "pong" descriptor equal to the "ping" descriptor. */
1327  dmaXfer[ channelId ].desc[1] = *desc;
1328  /* Refer to "ping" descriptor. */
1329  dmaXfer[ channelId ].desc[1].xfer.linkAddr = -4;
1330  dmaXfer[ channelId ].desc[1].xfer.srcAddr = (uint32_t)buf2;
1331 
1332  if ( direction == dmaDirectionPeripheralToMem )
1333  {
1334  dmaXfer[ channelId ].desc[1].xfer.dstAddr = (uint32_t)buf1;
1335  desc->xfer.srcAddr = (uint32_t)buf2;
1336  }
1337  }
1338 
1339  /* Interrupt needed ? */
1340  if ( ( callback == NULL ) && ( mode == dmaModeBasic ) )
1341  {
1342  desc->xfer.doneIfs = 0;
1343  }
1344 
1345  ch->callback = callback;
1346  ch->userParam = cbUserParam;
1347  ch->callbackCount = 0;
1348  ch->mode = mode;
1349 
1350  LDMA_StartTransfer( channelId, &xfer, desc );
1351 
1352  return ECODE_EMDRV_DMADRV_OK;
1353 }
1354 #endif /* defined( EMDRV_DMADRV_LDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API ) */
1355 
1357 
1358 
1359 /******** THE REST OF THE FILE IS DOCUMENTATION ONLY !**********************/
Byte.
Definition: dmadrv.h:510
Clock management unit (CMU) API.
DMA transfer configuration structure.
Definition: em_ldma.h:564
uint32_t dstInc
Definition: em_ldma.h:476
DMADRV API definition.
#define CORE_DECLARE_IRQ_STATE
Definition: em_core.h:85
uint32_t LDMA_TransferRemainingCount(int ch)
Get number of items remaining in a transfer.
Definition: em_ldma.c:338
uint32_t ldmaReqSel
Definition: em_ldma.h:566
void LDMA_Init(const LDMA_Init_t *init)
Initialize the LDMA controller.
Definition: em_ldma.c:137
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:539
#define LDMA_INIT_DEFAULT
Default DMA initialization structure.
Definition: em_ldma.h:586
int32_t linkAddr
Definition: em_ldma.h:485
Ecode_t DMADRV_TransferActive(unsigned int channelId, bool *active)
Check if a transfer is running.
Definition: dmadrv.c:759
static bool initialized
bool(* DMADRV_Callback_t)(unsigned int channel, unsigned int sequenceNo, void *userParam)
DMADRV transfer completion callback function.
Definition: dmadrv.h:80
uint32_t doneIfs
Definition: em_ldma.h:470
Ecode_t DMADRV_StopTransfer(unsigned int channelId)
Stop an ongoing DMA transfer.
Definition: dmadrv.c:719
#define ECODE_EMDRV_DMADRV_NOT_INITIALIZED
DMA is not initialized.
Definition: dmadrv.h:52
CMSIS Cortex-M Peripheral Access Layer for Silicon Laboratories microcontroller devices.
uint32_t linkMode
Definition: em_ldma.h:483
DMADRV_DataSize_t
Data size of one LDMA transfer item.
Definition: dmadrv.h:508
#define ECODE_EMDRV_DMADRV_ALREADY_FREED
DMA channel was free.
Definition: dmadrv.h:56
void LDMA_StartTransfer(int ch, const LDMA_TransferCfg_t *transfer, const LDMA_Descriptor_t *descriptor)
Start a DMA transfer.
Definition: em_ldma.c:183
Ecode_t DMADRV_TransferDone(unsigned int channelId, bool *done)
Check if a transfer has completed.
Definition: dmadrv.c:864
void LDMA_StopTransfer(int ch)
Stop a DMA transfer.
Definition: em_ldma.c:284
Ecode_t DMADRV_TransferRemainingCount(unsigned int channelId, int *remaining)
Get number of items remaining in a transfer.
Definition: dmadrv.c:930
Ecode_t DMADRV_ResumeTransfer(unsigned int channelId)
Resume an ongoing DMA transfer.
Definition: dmadrv.c:682
struct LDMA_Descriptor_t::@1 xfer
Halfword.
Definition: dmadrv.h:511
#define CORE_ENTER_ATOMIC()
Definition: em_core.h:138
uint32_t dstAddr
Definition: em_ldma.h:481
Ecode_t DMADRV_LdmaStartTransfer(int channelId, LDMA_TransferCfg_t *transfer, LDMA_Descriptor_t *descriptor, DMADRV_Callback_t callback, void *cbUserParam)
Start a LDMA transfer.
Definition: dmadrv.c:335
#define ECODE_EMDRV_DMADRV_CH_NOT_ALLOCATED
The channel is not reserved.
Definition: dmadrv.h:57
#define CORE_ATOMIC_SECTION(yourcode)
Definition: em_core.h:126
void LDMA_DeInit(void)
De-initialize the LDMA controller.
Definition: em_ldma.c:90
uint32_t link
Definition: em_ldma.h:484
uint32_t srcInc
Definition: em_ldma.h:474
#define ECODE_EMDRV_DMADRV_CHANNELS_EXHAUSTED
No DMA channels available.
Definition: dmadrv.h:54
#define LDMA_DESCRIPTOR_SINGLE_P2M_BYTE(src, dest, count)
DMA descriptor initializer for byte transfers from a peripheral to memory.
Definition: em_ldma.h:991
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:473
uint32_t Ecode_t
Typedef for API function error code return values.
Definition: ecode.h:51
#define DMADRV_MAX_XFER_COUNT
Maximum length of one DMA transfer.
Definition: dmadrv.h:311
Core interrupt handling API.
void CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)
Enable/disable a clock.
Definition: em_cmu.c:1453
Ecode_t DMADRV_Init(void)
Initialize DMADRV.
Definition: dmadrv.c:262
bool LDMA_TransferDone(int ch)
Check if a DMA transfer has completed.
Definition: em_ldma.c:306
#define CORE_EXIT_ATOMIC()
Definition: em_core.h:142
#define ECODE_EMDRV_DMADRV_OK
Success return value.
Definition: dmadrv.h:50
DMA descriptor.
Definition: em_ldma.h:456
#define LDMA_TRANSFER_CFG_PERIPHERAL(signal)
Generic DMA transfer configuration for memory to/from peripheral transfers.
Definition: em_ldma.h:621
#define LDMA
Ecode_t DMADRV_DeInit(void)
Deinitialize DMADRV.
Definition: dmadrv.c:177
LDMA initialization configuration structure.
Definition: em_ldma.h:550
#define ECODE_EMDRV_DMADRV_IN_USE
DMA is in use.
Definition: dmadrv.h:55
Ecode_t DMADRV_AllocateChannel(unsigned int *channelId, void *capabilities)
Allocate (reserve) a DMA channel.
Definition: dmadrv.c:131
uint8_t ldmaInitCtrlNumFixed
Definition: em_ldma.h:552
uint32_t xferCnt
Definition: em_ldma.h:467
#define ECODE_EMDRV_DMADRV_ALREADY_INITIALIZED
DMA has already been initialized.
Definition: dmadrv.h:53
#define LDMA_DESCRIPTOR_SINGLE_M2P_BYTE(src, dest, count)
DMA descriptor initializer for byte transfers from memory to a peripheral.
Definition: em_ldma.h:1057
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:406
uint8_t ldmaInitIrqPriority
Definition: em_ldma.h:555
#define ECODE_EMDRV_DMADRV_PARAM_ERROR
Illegal input parameter.
Definition: dmadrv.h:51
DMADRV_PeripheralSignal_t
Peripherals that can trigger LDMA transfers.
Definition: dmadrv.h:314
Ecode_t DMADRV_TransferCompletePending(unsigned int channelId, bool *pending)
Check if a transfer complete is pending.
Definition: dmadrv.c:811
uint32_t srcAddr
Definition: em_ldma.h:480
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:606
#define LDMA_IF_ERROR
DMA control data block.
Ecode_t DMADRV_PauseTransfer(unsigned int channelId)
Pause an ongoing DMA transfer.
Definition: dmadrv.c:645
Ecode_t DMADRV_FreeChannel(unsigned int channelId)
Free an allocate (reserved) DMA channel.
Definition: dmadrv.c:225
void LDMA_EnableChannelRequest(int ch, bool enable)
Enable or disable a LDMA channel request.
Definition: em_ldma.c:112
uint32_t size
Definition: em_ldma.h:475