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, 1UL );
89 const LDMA_Descriptor_t p2m = LDMA_DESCRIPTOR_SINGLE_P2M_BYTE( NULL, NULL, 1UL );
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,
142 if ( channelId == NULL )
148 for ( i=0; i < EMDRV_DMADRV_DMA_CH_COUNT; i++ )
150 if ( !chTable[ i ].allocated )
153 chTable[ i ].allocated =
true;
154 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( EMDRV_DMADRV_LDMA )
155 chTable[ i ].callback = NULL;
186 for ( i=0; i < EMDRV_DMADRV_DMA_CH_COUNT; i++ )
188 if ( chTable[ i ].allocated )
197 #if defined( EMDRV_DMADRV_UDMA )
202 #elif defined( EMDRV_DMADRV_LDMA )
234 if ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
240 if ( chTable[ channelId ].allocated )
242 chTable[ channelId ].allocated =
false;
266 #if defined( EMDRV_DMADRV_UDMA )
268 #elif defined( EMDRV_DMADRV_LDMA )
269 LDMA_Init_t dmaInit = LDMA_INIT_DEFAULT;
270 dmaInit.ldmaInitCtrlNumFixed = EMDRV_DMADRV_DMA_CH_PRIORITY;
282 if ( EMDRV_DMADRV_DMA_IRQ_PRIORITY > 7 )
287 for ( i=0; i < EMDRV_DMADRV_DMA_CH_COUNT; i++ )
289 chTable[ i ].allocated =
false;
292 #if defined( EMDRV_DMADRV_UDMA )
293 NVIC_SetPriority(
DMA_IRQn, EMDRV_DMADRV_DMA_IRQ_PRIORITY );
295 dmaInit.controlBlock = dmaControlBlock;
297 #elif defined( EMDRV_DMADRV_LDMA )
298 dmaInit.ldmaInitIrqPriority = EMDRV_DMADRV_DMA_IRQ_PRIORITY;
299 LDMA_Init( &dmaInit );
305 #if defined( EMDRV_DMADRV_LDMA ) && defined( EMDRV_DMADRV_USE_NATIVE_API )
335 Ecode_t DMADRV_LdmaStartTransfer(
int channelId,
336 LDMA_TransferCfg_t *transfer,
337 LDMA_Descriptor_t *descriptor,
348 if ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
353 ch = &chTable[ channelId ];
354 if ( ch->allocated ==
false )
359 ch->callback = callback;
360 ch->userParam = cbUserParam;
361 ch->callbackCount = 0;
362 LDMA_StartTransfer( channelId, transfer, descriptor );
368 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
407 DMADRV_PeripheralSignal_t
413 DMADRV_DataSize_t size,
417 return StartTransfer( dmaModeBasic,
418 dmaDirectionMemToPeripheral,
432 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
474 unsigned int channelId,
475 DMADRV_PeripheralSignal_t
482 DMADRV_DataSize_t size,
486 return StartTransfer( dmaModePingPong,
487 dmaDirectionMemToPeripheral,
501 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
540 DMADRV_PeripheralSignal_t
546 DMADRV_DataSize_t size,
550 return StartTransfer( dmaModeBasic,
551 dmaDirectionPeripheralToMem,
565 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
607 unsigned int channelId,
608 DMADRV_PeripheralSignal_t
615 DMADRV_DataSize_t size,
619 return StartTransfer( dmaModePingPong,
620 dmaDirectionPeripheralToMem,
652 if ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
657 if ( chTable[ channelId ].allocated ==
false )
662 #if defined( EMDRV_DMADRV_UDMA )
664 #elif defined( EMDRV_DMADRV_LDMA )
665 LDMA_EnableChannelRequest( channelId,
false );
689 if ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
694 if ( chTable[ channelId ].allocated ==
false )
699 #if defined( EMDRV_DMADRV_UDMA )
701 #elif defined( EMDRV_DMADRV_LDMA )
702 LDMA_EnableChannelRequest( channelId,
true );
726 if ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
731 if ( chTable[ channelId ].allocated ==
false )
736 #if defined( EMDRV_DMADRV_UDMA )
738 #elif defined( EMDRV_DMADRV_LDMA )
739 LDMA_StopTransfer( channelId );
766 if ( ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
767 || ( active == NULL ) )
772 if ( chTable[ channelId ].allocated ==
false )
777 #if defined( EMDRV_DMADRV_UDMA )
779 #elif defined( EMDRV_DMADRV_LDMA )
780 if ( LDMA->CHEN & ( 1 << channelId ) )
818 if ( ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
819 || ( pending == NULL ) )
824 if ( chTable[ channelId ].allocated ==
false )
829 #if defined( EMDRV_DMADRV_UDMA )
830 if (
DMA->IF & ( 1 << channelId ) )
831 #elif defined( EMDRV_DMADRV_LDMA )
832 if ( LDMA->IF & ( 1 << channelId ) )
866 #if defined( EMDRV_DMADRV_UDMA )
867 uint32_t remaining, iflag;
875 if ( ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
876 || ( done == NULL ) )
881 if ( chTable[ channelId ].allocated ==
false )
886 #if defined( EMDRV_DMADRV_UDMA )
889 remaining = ( dmaControlBlock[ channelId ].CTRL
895 if ( ( remaining == 0 ) && ( iflag & ( 1 << channelId ) ) )
903 #elif defined( EMDRV_DMADRV_LDMA )
904 *done = LDMA_TransferDone( channelId );
933 #if defined( EMDRV_DMADRV_UDMA )
934 uint32_t remain, iflag;
942 if ( ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
943 || ( remaining == NULL ) )
948 if ( chTable[ channelId ].allocated ==
false )
953 #if defined( EMDRV_DMADRV_UDMA )
956 remain = ( dmaControlBlock[ channelId ].CTRL
962 if ( ( remain == 0 ) && ( iflag & ( 1 << channelId ) ) )
968 *remaining = 1 + remain;
970 #elif defined( EMDRV_DMADRV_LDMA )
971 *remaining = LDMA_TransferRemainingCount( channelId );
979 #if defined( EMDRV_DMADRV_LDMA )
984 void LDMA_IRQHandler(
void )
986 #if !defined( EMDRV_DMADRV_USE_NATIVE_API )
990 uint32_t pending, chnum, chmask;
994 pending &= LDMA->IEN;
997 if ( pending & LDMA_IF_ERROR )
1007 for ( chnum = 0, chmask = 1;
1008 chnum < EMDRV_DMADRV_DMA_CH_COUNT;
1009 chnum++, chmask <<= 1 )
1011 if ( pending & chmask )
1016 ch = &chTable[ chnum ];
1017 if ( ch->callback != NULL )
1019 ch->callbackCount++;
1020 #if defined( EMDRV_DMADRV_USE_NATIVE_API )
1021 ch->callback( chnum, ch->callbackCount, ch->userParam );
1023 stop = !ch->callback( chnum, ch->callbackCount, ch->userParam );
1025 if ( ( ch->mode == dmaModePingPong ) && stop )
1027 dmaXfer[ chnum ].desc[0].xfer.link = 0;
1028 dmaXfer[ chnum ].desc[1].xfer.link = 0;
1037 #if defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
1042 static void DmaBasicCallback(
unsigned int channel,
bool primary,
void *user )
1044 ChTable_t *ch = &chTable[ channel ];
1048 if ( ch->callback != NULL )
1050 ch->callbackCount++;
1051 ch->callback( channel, ch->callbackCount, ch->userParam );
1056 #if defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
1061 static void DmaPingPongCallback(
unsigned int channel,
bool primary,
void *user )
1064 ChTable_t *ch = &chTable[ channel ];
1068 if ( ch->callback != NULL )
1070 ch->callbackCount++;
1071 stop = !ch->callback( channel, ch->callbackCount, ch->userParam );
1084 #if defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
1089 static Ecode_t StartTransfer( DmaMode_t mode,
1090 DmaDirection_t direction,
1091 unsigned int channelId,
1092 DMADRV_PeripheralSignal_t
1099 DMADRV_DataSize_t size,
1112 if ( ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
1116 || ( ( mode == dmaModePingPong ) && ( buf2 == NULL ) ) )
1121 ch = &chTable[ channelId ];
1122 if ( ch->allocated ==
false )
1128 if ( mode == dmaModeBasic )
1130 dmaCallBack[ channelId ].
cbFunc = DmaBasicCallback;
1134 dmaCallBack[ channelId ].
cbFunc = DmaPingPongCallback;
1136 dmaCallBack[ channelId ].
userPtr = NULL;
1142 if ( ( callback != NULL ) || ( mode == dmaModePingPong ) )
1150 chCfg.
select = peripheralSignal;
1151 chCfg.
cb = &dmaCallBack[ channelId ];
1155 if ( direction == dmaDirectionMemToPeripheral )
1205 if ( mode == dmaModePingPong )
1210 ch->callback = callback;
1211 ch->userParam = cbUserParam;
1212 ch->callbackCount = 0;
1215 DMA->IFC = 1 << channelId;
1218 if ( mode == dmaModeBasic )
1224 if ( direction == dmaDirectionMemToPeripheral )
1252 #if defined( EMDRV_DMADRV_LDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
1257 static Ecode_t StartTransfer( DmaMode_t mode,
1258 DmaDirection_t direction,
1259 unsigned int channelId,
1260 DMADRV_PeripheralSignal_t
1267 DMADRV_DataSize_t size,
1272 LDMA_TransferCfg_t xfer;
1273 LDMA_Descriptor_t *desc;
1280 if ( ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
1284 || ( ( mode == dmaModePingPong ) && ( buf2 == NULL ) ) )
1289 ch = &chTable[ channelId ];
1290 if ( ch->allocated ==
false )
1296 desc = &dmaXfer[ channelId ].desc[0];
1298 if ( direction == dmaDirectionMemToPeripheral )
1303 desc->xfer.srcInc = ldmaCtrlSrcIncNone;
1311 desc->xfer.dstInc = ldmaCtrlDstIncNone;
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;
1320 if ( mode == dmaModePingPong )
1322 desc->xfer.linkMode = ldmaLinkModeRel;
1323 desc->xfer.link = 1;
1324 desc->xfer.linkAddr = 4;
1327 dmaXfer[ channelId ].desc[1] = *desc;
1329 dmaXfer[ channelId ].desc[1].xfer.linkAddr = -4;
1330 dmaXfer[ channelId ].desc[1].xfer.srcAddr = (uint32_t)buf2;
1332 if ( direction == dmaDirectionPeripheralToMem )
1334 dmaXfer[ channelId ].desc[1].xfer.dstAddr = (uint32_t)buf1;
1335 desc->xfer.srcAddr = (uint32_t)buf2;
1340 if ( ( callback == NULL ) && ( mode == dmaModeBasic ) )
1342 desc->xfer.doneIfs = 0;
1345 ch->callback = callback;
1346 ch->userParam = cbUserParam;
1347 ch->callbackCount = 0;
1350 LDMA_StartTransfer( channelId, &xfer, desc );
Clock management unit (CMU) API.
#define CORE_DECLARE_IRQ_STATE
DMA_ArbiterConfig_TypeDef arbRate
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.
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.
void DMA_RefreshPingPong(unsigned int channel, bool primary, bool useBurst, void *dst, const void *src, unsigned int nMinus1, bool last)
Refresh a descriptor used in a DMA ping-pong cycle.
Ecode_t DMADRV_TransferDone(unsigned int channelId, bool *done)
Check if a transfer has completed.
void DMA_ChannelRequestEnable(unsigned int channel, bool enable)
Enable or disable a DMA channel request.
void DMA_ActivateBasic(unsigned int channel, bool primary, bool useBurst, void *dst, const void *src, unsigned int nMinus1)
Activate DMA basic cycle (used for memory-peripheral transfers).
Ecode_t DMADRV_TransferRemainingCount(unsigned int channelId, int *remaining)
Get number of items remaining in a transfer.
Ecode_t DMADRV_ResumeTransfer(unsigned int channelId)
Resume an ongoing DMA transfer.
#define CORE_ENTER_ATOMIC()
#define ECODE_EMDRV_DMADRV_CH_NOT_ALLOCATED
The channel is not reserved.
#define CORE_ATOMIC_SECTION(yourcode)
void DMA_ActivatePingPong(unsigned int channel, bool useBurst, void *primDst, const void *primSrc, unsigned int primNMinus1, void *altDst, const void *altSrc, unsigned int altNMinus1)
Activate DMA ping-pong 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.
uint32_t Ecode_t
Typedef for API function error code return values.
#define DMADRV_MAX_XFER_COUNT
Maximum length of one DMA transfer.
#define _DMA_IEN_RESETVALUE
DMA_DataSize_TypeDef size
Core interrupt handling API.
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 CORE_EXIT_ATOMIC()
#define ECODE_EMDRV_DMADRV_OK
Success return value.
#define _DMA_CTRL_N_MINUS_1_MASK
Ecode_t DMADRV_DeInit(void)
Deinitialize DMADRV.
#define ECODE_EMDRV_DMADRV_IN_USE
DMA is in use.
#define _DMA_CONFIG_RESETVALUE
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
Ecode_t DMADRV_TransferCompletePending(unsigned int channelId, bool *pending)
Check if a transfer complete is pending.
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_PauseTransfer(unsigned int channelId)
Pause an ongoing DMA transfer.
Ecode_t DMADRV_FreeChannel(unsigned int channelId)
Free an allocate (reserved) DMA channel.
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.