25 #if defined( EMDRV_DMADRV_UDMA )
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
38 dmaDirectionMemToPeripheral,
39 dmaDirectionPeripheralToMem
48 #if defined( EMDRV_DMADRV_USE_NATIVE_API ) && defined( EMDRV_DMADRV_UDMA )
54 #elif defined( EMDRV_DMADRV_USE_NATIVE_API ) && defined( EMDRV_DMADRV_LDMA )
59 unsigned int callbackCount;
68 unsigned int callbackCount;
69 #if defined( EMDRV_DMADRV_UDMA )
73 #if defined( EMDRV_DMADRV_LDMA )
80 static ChTable_t chTable[ EMDRV_DMADRV_DMA_CH_COUNT ];
82 #if defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
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 );
93 LDMA_Descriptor_t desc[2];
96 static DmaXfer_t dmaXfer[ EMDRV_DMADRV_DMA_CH_COUNT ];
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
110 DMADRV_DataSize_t size,
141 if ( channelId == NULL )
147 for ( i=0; i < EMDRV_DMADRV_DMA_CH_COUNT; i++ )
149 if ( !chTable[ i ].allocated )
152 chTable[ i ].allocated =
true;
153 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( EMDRV_DMADRV_LDMA )
154 chTable[ i ].callback = NULL;
184 for ( i=0; i < EMDRV_DMADRV_DMA_CH_COUNT; i++ )
186 if ( chTable[ i ].allocated )
195 #if defined( EMDRV_DMADRV_UDMA )
200 #elif defined( EMDRV_DMADRV_LDMA )
230 if ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
236 if ( chTable[ channelId ].allocated )
238 chTable[ channelId ].allocated =
false;
261 #if defined( EMDRV_DMADRV_UDMA )
263 #elif defined( EMDRV_DMADRV_LDMA )
264 LDMA_Init_t dmaInit = LDMA_INIT_DEFAULT;
265 dmaInit.ldmaInitCtrlNumFixed = EMDRV_DMADRV_DMA_CH_PRIORITY;
278 if ( EMDRV_DMADRV_DMA_IRQ_PRIORITY > 7 )
283 for ( i=0; i < EMDRV_DMADRV_DMA_CH_COUNT; i++ )
285 chTable[ i ].allocated =
false;
288 #if defined( EMDRV_DMADRV_UDMA )
289 NVIC_SetPriority(
DMA_IRQn, EMDRV_DMADRV_DMA_IRQ_PRIORITY );
293 #elif defined( EMDRV_DMADRV_LDMA )
294 dmaInit.ldmaInitIrqPriority = EMDRV_DMADRV_DMA_IRQ_PRIORITY;
295 LDMA_Init( &dmaInit );
301 #if defined( EMDRV_DMADRV_LDMA ) && defined( EMDRV_DMADRV_USE_NATIVE_API )
331 Ecode_t DMADRV_LdmaStartTransfer(
int channelId,
332 LDMA_TransferCfg_t *transfer,
333 LDMA_Descriptor_t *descriptor,
344 if ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
349 ch = &chTable[ channelId ];
350 if ( ch->allocated ==
false )
355 ch->callback = callback;
356 ch->userParam = cbUserParam;
357 ch->callbackCount = 0;
358 LDMA_StartTransfer( channelId, transfer, descriptor );
364 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
403 DMADRV_PeripheralSignal_t
409 DMADRV_DataSize_t size,
413 return StartTransfer( dmaModeBasic,
414 dmaDirectionMemToPeripheral,
428 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
470 unsigned int channelId,
471 DMADRV_PeripheralSignal_t
478 DMADRV_DataSize_t size,
482 return StartTransfer( dmaModePingPong,
483 dmaDirectionMemToPeripheral,
497 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
536 DMADRV_PeripheralSignal_t
542 DMADRV_DataSize_t size,
546 return StartTransfer( dmaModeBasic,
547 dmaDirectionPeripheralToMem,
561 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
603 unsigned int channelId,
604 DMADRV_PeripheralSignal_t
611 DMADRV_DataSize_t size,
615 return StartTransfer( dmaModePingPong,
616 dmaDirectionPeripheralToMem,
648 if ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
653 if ( chTable[ channelId ].allocated ==
false )
658 #if defined( EMDRV_DMADRV_UDMA )
660 #elif defined( EMDRV_DMADRV_LDMA )
661 LDMA_StopTransfer( channelId );
688 if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
689 || ( active == NULL ) )
694 if ( chTable[ channelId ].allocated ==
false )
699 #if defined( EMDRV_DMADRV_UDMA )
701 #elif defined( EMDRV_DMADRV_LDMA )
702 if ( LDMA->CHEN & ( 1 << channelId ) )
740 if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
741 || ( pending == NULL ) )
746 if ( chTable[ channelId ].allocated ==
false )
751 #if defined( EMDRV_DMADRV_UDMA )
752 if (
DMA->IF & ( 1 << channelId ) )
753 #elif defined( EMDRV_DMADRV_LDMA )
754 if ( LDMA->IF & ( 1 << channelId ) )
788 #if defined( EMDRV_DMADRV_UDMA )
789 uint32_t remaining, iflag;
797 if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
798 || ( done == NULL ) )
803 if ( chTable[ channelId ].allocated ==
false )
808 #if defined( EMDRV_DMADRV_UDMA )
817 if ( ( remaining == 0 ) && ( iflag & ( 1 << channelId ) ) )
825 #elif defined( EMDRV_DMADRV_LDMA )
826 *done = LDMA_TransferDone( channelId );
855 #if defined( EMDRV_DMADRV_UDMA )
856 uint32_t remain, iflag;
864 if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
865 || ( remaining == NULL ) )
870 if ( chTable[ channelId ].allocated ==
false )
875 #if defined( EMDRV_DMADRV_UDMA )
884 if ( ( remain == 0 ) && ( iflag & ( 1 << channelId ) ) )
890 *remaining = 1 + remain;
892 #elif defined( EMDRV_DMADRV_LDMA )
893 *remaining = LDMA_TransferRemainingCount( channelId );
901 #if defined( EMDRV_DMADRV_LDMA )
906 void LDMA_IRQHandler(
void )
908 #if !defined( EMDRV_DMADRV_USE_NATIVE_API )
912 uint32_t pending, chnum, chmask;
916 pending &= LDMA->IEN;
919 if ( pending & LDMA_IF_ERROR )
929 for ( chnum = 0, chmask = 1;
930 chnum < EMDRV_DMADRV_DMA_CH_COUNT;
931 chnum++, chmask <<= 1 )
933 if ( pending & chmask )
938 ch = &chTable[ chnum ];
939 if ( ch->callback != NULL )
942 #if defined( EMDRV_DMADRV_USE_NATIVE_API )
943 ch->callback( chnum, ch->callbackCount, ch->userParam );
945 stop = !ch->callback( chnum, ch->callbackCount, ch->userParam );
947 if ( ( ch->mode == dmaModePingPong ) && stop )
949 dmaXfer[ chnum ].desc[0].xfer.link = 0;
950 dmaXfer[ chnum ].desc[1].xfer.link = 0;
959 #if defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
964 static void DmaBasicCallback(
unsigned int channel,
bool primary,
void *user )
966 ChTable_t *ch = &chTable[ channel ];
970 if ( ch->callback != NULL )
973 ch->callback( channel, ch->callbackCount, ch->userParam );
978 #if defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
983 static void DmaPingPongCallback(
unsigned int channel,
bool primary,
void *user )
986 ChTable_t *ch = &chTable[ channel ];
990 if ( ch->callback != NULL )
993 stop = !ch->callback( channel, ch->callbackCount, ch->userParam );
1006 #if defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
1011 static Ecode_t StartTransfer( DmaMode_t mode,
1012 DmaDirection_t direction,
1013 unsigned int channelId,
1014 DMADRV_PeripheralSignal_t
1021 DMADRV_DataSize_t size,
1034 if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
1038 || ( ( mode == dmaModePingPong ) && ( buf2 == NULL ) ) )
1043 ch = &chTable[ channelId ];
1044 if ( ch->allocated ==
false )
1050 if ( mode == dmaModeBasic )
1052 dmaCallBack[ channelId ].
cbFunc = DmaBasicCallback;
1056 dmaCallBack[ channelId ].
cbFunc = DmaPingPongCallback;
1058 dmaCallBack[ channelId ].
userPtr = NULL;
1064 if ( ( callback != NULL ) || ( mode == dmaModePingPong ) )
1072 chCfg.
select = peripheralSignal;
1073 chCfg.
cb = &dmaCallBack[ channelId ];
1077 if ( direction == dmaDirectionMemToPeripheral )
1127 if ( mode == dmaModePingPong )
1132 ch->callback = callback;
1133 ch->userParam = cbUserParam;
1134 ch->callbackCount = 0;
1137 DMA->IFC = 1 << channelId;
1140 if ( mode == dmaModeBasic )
1146 if ( direction == dmaDirectionMemToPeripheral )
1174 #if defined( EMDRV_DMADRV_LDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
1179 static Ecode_t StartTransfer( DmaMode_t mode,
1180 DmaDirection_t direction,
1181 unsigned int channelId,
1182 DMADRV_PeripheralSignal_t
1189 DMADRV_DataSize_t size,
1194 LDMA_TransferCfg_t xfer;
1195 LDMA_Descriptor_t *desc;
1202 if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
1206 || ( ( mode == dmaModePingPong ) && ( buf2 == NULL ) ) )
1211 ch = &chTable[ channelId ];
1212 if ( ch->allocated ==
false )
1218 desc = &dmaXfer[ channelId ].desc[0];
1220 if ( direction == dmaDirectionMemToPeripheral )
1225 desc->xfer.srcInc = ldmaCtrlSrcIncNone;
1233 desc->xfer.dstInc = ldmaCtrlDstIncNone;
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;
1242 if ( mode == dmaModePingPong )
1244 desc->xfer.linkMode = ldmaLinkModeRel;
1245 desc->xfer.link = 1;
1246 desc->xfer.linkAddr = 4;
1249 dmaXfer[ channelId ].desc[1] = *desc;
1251 dmaXfer[ channelId ].desc[1].xfer.linkAddr = -4;
1252 dmaXfer[ channelId ].desc[1].xfer.srcAddr = (uint32_t)buf2;
1254 if ( direction == dmaDirectionPeripheralToMem )
1256 dmaXfer[ channelId ].desc[1].xfer.dstAddr = (uint32_t)buf1;
1257 desc->xfer.srcAddr = (uint32_t)buf2;
1262 if ( ( callback == NULL ) && ( mode == dmaModeBasic ) )
1264 desc->xfer.doneIfs = 0;
1267 ch->callback = callback;
1268 ch->userParam = cbUserParam;
1269 ch->callbackCount = 0;
1272 LDMA_StartTransfer( channelId, &xfer, desc );
Clock management unit (CMU) API.
DMA_ArbiterConfig_TypeDef arbRate
#define _DMA_IEN_RESETVALUE
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.
DMA_DataInc_TypeDef dstInc
Callback structure that can be used to define DMA complete actions.
Ecode_t DMADRV_TransferActive(unsigned int channelId, bool *active)
Check if a transfer is running.
bool(* DMADRV_Callback_t)(unsigned int channel, unsigned int sequenceNo, void *userParam)
DMADRV transfer completion callback function.
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.
__STATIC_INLINE uint32_t INT_Enable(void)
Enable interrupts.
Ecode_t DMADRV_StopTransfer(unsigned int channelId)
Stop an ongoing DMA transfer.
DMA_CB_TypeDef * cb
User definable callback handling configuration.
#define ECODE_EMDRV_DMADRV_NOT_INITIALIZED
DMA is not initialized.
CMSIS Cortex-M Peripheral Access Layer for Silicon Laboratories microcontroller devices.
bool DMA_ChannelEnabled(unsigned int channel)
Check if DMA channel is enabled.
#define ECODE_EMDRV_DMADRV_ALREADY_FREED
DMA channel was free.
Ecode_t DMADRV_TransferDone(unsigned int channelId, bool *done)
Check if a transfer has completed.
Ecode_t DMADRV_TransferRemainingCount(unsigned int channelId, int *remaining)
Get number of items remaining in a transfer.
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).
#define _DMA_CONFIG_RESETVALUE
#define ECODE_EMDRV_DMADRV_CH_NOT_ALLOCATED
The channel is not reserved.
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).
#define ECODE_EMDRV_DMADRV_CHANNELS_EXHAUSTED
No DMA channels available.
void DMA_Init(DMA_Init_TypeDef *init)
Initializes DMA controller.
void DMA_CfgChannel(unsigned int channel, DMA_CfgChannel_TypeDef *cfg)
Configure a DMA channel.
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.
DMA_DESCRIPTOR_TypeDef dmaControlBlock[DMACTRL_CH_CNT *2]
#define DMADRV_MAX_XFER_COUNT
Maximum length of one DMA transfer.
DMA_DataSize_TypeDef size
void CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)
Enable/disable a clock.
Ecode_t DMADRV_Init(void)
Initialize DMADRV.
DMA_DataInc_TypeDef srcInc
#define ECODE_EMDRV_DMADRV_OK
Success return value.
Ecode_t DMADRV_DeInit(void)
Deinitialize DMADRV.
#define ECODE_EMDRV_DMADRV_IN_USE
DMA is in use.
Ecode_t DMADRV_AllocateChannel(unsigned int *channelId, void *capabilities)
Allocate (reserve) a DMA channel.
#define ECODE_EMDRV_DMADRV_ALREADY_INITIALIZED
DMA has already been initialized.
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.
#define ECODE_EMDRV_DMADRV_PARAM_ERROR
Illegal input parameter.
DMA_FuncPtr_TypeDef cbFunc
uint32_t Ecode_t
Typedef for API function errorcode return values.
Ecode_t DMADRV_TransferCompletePending(unsigned int channelId, bool *pending)
Check if a transfer complete is pending.
__STATIC_INLINE uint32_t INT_Disable(void)
Disable interrupts.
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.
#define _DMA_CTRL_N_MINUS_1_SHIFT
Ecode_t DMADRV_FreeChannel(unsigned int channelId)
Free an allocate (reserved) DMA channel.
#define _DMA_CTRL_N_MINUS_1_MASK
void DMA_ChannelEnable(unsigned int channel, bool enable)
Enable or disable a DMA channel.
void DMA_CfgDescr(unsigned int channel, bool primary, DMA_CfgDescr_TypeDef *cfg)
Configure DMA descriptor for auto-request, basic or ping-pong DMA cycles.