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 )
83 static DMA_CB_TypeDef dmaCallBack[ EMDRV_DMADRV_DMA_CH_COUNT ];
86 #if defined( EMDRV_DMADRV_LDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
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,
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 )
198 NVIC_DisableIRQ( DMA_IRQn );
199 DMA->IEN = _DMA_IEN_RESETVALUE;
200 DMA->CONFIG = _DMA_CONFIG_RESETVALUE;
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 )
267 DMA_Init_TypeDef dmaInit;
268 #elif defined( EMDRV_DMADRV_LDMA )
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;
296 DMA_Init( &dmaInit );
297 #elif defined( EMDRV_DMADRV_LDMA )
305 #if defined( EMDRV_DMADRV_LDMA ) && defined( EMDRV_DMADRV_USE_NATIVE_API )
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;
368 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
417 return StartTransfer( dmaModeBasic,
418 dmaDirectionMemToPeripheral,
432 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
474 unsigned int channelId,
486 return StartTransfer( dmaModePingPong,
487 dmaDirectionMemToPeripheral,
501 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
550 return StartTransfer( dmaModeBasic,
551 dmaDirectionPeripheralToMem,
565 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
607 unsigned int channelId,
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 )
663 DMA_ChannelRequestEnable( channelId,
false );
664 #elif defined( EMDRV_DMADRV_LDMA )
689 if ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
694 if ( chTable[ channelId ].allocated ==
false )
699 #if defined( EMDRV_DMADRV_UDMA )
700 DMA_ChannelRequestEnable( channelId,
true );
701 #elif defined( EMDRV_DMADRV_LDMA )
726 if ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
731 if ( chTable[ channelId ].allocated ==
false )
736 #if defined( EMDRV_DMADRV_UDMA )
737 DMA_ChannelEnable( channelId,
false );
738 #elif defined( EMDRV_DMADRV_LDMA )
766 if ( ( channelId >= EMDRV_DMADRV_DMA_CH_COUNT )
767 || ( active == NULL ) )
772 if ( chTable[ channelId ].allocated ==
false )
777 #if defined( EMDRV_DMADRV_UDMA )
778 if ( DMA_ChannelEnabled( channelId ) )
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
890 & _DMA_CTRL_N_MINUS_1_MASK )
891 >> _DMA_CTRL_N_MINUS_1_SHIFT;
895 if ( ( remaining == 0 ) && ( iflag & ( 1 << channelId ) ) )
903 #elif defined( EMDRV_DMADRV_LDMA )
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
957 & _DMA_CTRL_N_MINUS_1_MASK )
958 >> _DMA_CTRL_N_MINUS_1_SHIFT;
962 if ( ( remain == 0 ) && ( iflag & ( 1 << channelId ) ) )
968 *remaining = 1 + remain;
970 #elif defined( EMDRV_DMADRV_LDMA )
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;
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 );
1074 DMA_RefreshPingPong( 0,
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,
1104 DMA_CfgChannel_TypeDef chCfg;
1105 DMA_CfgDescr_TypeDef descrCfg;
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;
1139 chCfg.highPri =
false;
1142 if ( ( callback != NULL ) || ( mode == dmaModePingPong ) )
1144 chCfg.enableInt =
true;
1148 chCfg.enableInt =
false;
1150 chCfg.select = peripheralSignal;
1151 chCfg.cb = &dmaCallBack[ channelId ];
1152 DMA_CfgChannel( channelId, &chCfg );
1155 if ( direction == dmaDirectionMemToPeripheral )
1161 descrCfg.srcInc = dmaDataInc1;
1165 descrCfg.srcInc = dmaDataInc2;
1169 descrCfg.srcInc = dmaDataInc4;
1174 descrCfg.srcInc = dmaDataIncNone;
1176 descrCfg.dstInc = dmaDataIncNone;
1184 descrCfg.dstInc = dmaDataInc1;
1188 descrCfg.dstInc = dmaDataInc2;
1192 descrCfg.dstInc = dmaDataInc4;
1197 descrCfg.dstInc = dmaDataIncNone;
1199 descrCfg.srcInc = dmaDataIncNone;
1201 descrCfg.size = (DMA_DataSize_TypeDef)size;
1202 descrCfg.arbRate = dmaArbitrate1;
1204 DMA_CfgDescr( channelId,
true, &descrCfg );
1205 if ( mode == dmaModePingPong )
1207 DMA_CfgDescr( channelId,
false, &descrCfg );
1210 ch->callback = callback;
1211 ch->userParam = cbUserParam;
1212 ch->callbackCount = 0;
1215 DMA->IFC = 1 << channelId;
1218 if ( mode == dmaModeBasic )
1220 DMA_ActivateBasic( channelId,
true,
false, buf0, buf1, len - 1 );
1224 if ( direction == dmaDirectionMemToPeripheral )
1226 DMA_ActivatePingPong( channelId,
1237 DMA_ActivatePingPong( channelId,
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,
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 )
1320 if ( mode == dmaModePingPong )
1327 dmaXfer[ channelId ].desc[1] = *desc;
1330 dmaXfer[ channelId ].desc[1].xfer.srcAddr = (uint32_t)buf2;
1332 if ( direction == dmaDirectionPeripheralToMem )
1334 dmaXfer[ channelId ].desc[1].xfer.dstAddr = (uint32_t)buf1;
1340 if ( ( callback == NULL ) && ( mode == dmaModeBasic ) )
1345 ch->callback = callback;
1346 ch->userParam = cbUserParam;
1347 ch->callbackCount = 0;
Clock management unit (CMU) API.
DMA transfer configuration structure.
#define CORE_DECLARE_IRQ_STATE
uint32_t LDMA_TransferRemainingCount(int ch)
Get number of items remaining in a transfer.
void LDMA_Init(const LDMA_Init_t *init)
Initialize the LDMA controller.
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.
#define LDMA_INIT_DEFAULT
Default DMA initialization structure.
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.
#define ECODE_EMDRV_DMADRV_NOT_INITIALIZED
DMA is not initialized.
CMSIS Cortex-M Peripheral Access Layer for Silicon Laboratories microcontroller devices.
DMADRV_DataSize_t
Data size of one LDMA transfer item.
#define ECODE_EMDRV_DMADRV_ALREADY_FREED
DMA channel was free.
void LDMA_StartTransfer(int ch, const LDMA_TransferCfg_t *transfer, const LDMA_Descriptor_t *descriptor)
Start a DMA transfer.
Ecode_t DMADRV_TransferDone(unsigned int channelId, bool *done)
Check if a transfer has completed.
void LDMA_StopTransfer(int ch)
Stop a DMA transfer.
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.
struct LDMA_Descriptor_t::@1 xfer
#define CORE_ENTER_ATOMIC()
Ecode_t DMADRV_LdmaStartTransfer(int channelId, LDMA_TransferCfg_t *transfer, LDMA_Descriptor_t *descriptor, DMADRV_Callback_t callback, void *cbUserParam)
Start a LDMA transfer.
#define ECODE_EMDRV_DMADRV_CH_NOT_ALLOCATED
The channel is not reserved.
#define CORE_ATOMIC_SECTION(yourcode)
void LDMA_DeInit(void)
De-initialize the LDMA controller.
#define ECODE_EMDRV_DMADRV_CHANNELS_EXHAUSTED
No DMA channels available.
#define LDMA_DESCRIPTOR_SINGLE_P2M_BYTE(src, dest, count)
DMA descriptor initializer for byte transfers from a peripheral to memory.
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.
Core interrupt handling API.
void CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)
Enable/disable a clock.
Ecode_t DMADRV_Init(void)
Initialize DMADRV.
bool LDMA_TransferDone(int ch)
Check if a DMA transfer has completed.
#define CORE_EXIT_ATOMIC()
#define ECODE_EMDRV_DMADRV_OK
Success return value.
#define LDMA_TRANSFER_CFG_PERIPHERAL(signal)
Generic DMA transfer configuration for memory to/from peripheral transfers.
Ecode_t DMADRV_DeInit(void)
Deinitialize DMADRV.
LDMA initialization configuration structure.
#define ECODE_EMDRV_DMADRV_IN_USE
DMA is in use.
Ecode_t DMADRV_AllocateChannel(unsigned int *channelId, void *capabilities)
Allocate (reserve) a DMA channel.
uint8_t ldmaInitCtrlNumFixed
#define ECODE_EMDRV_DMADRV_ALREADY_INITIALIZED
DMA has already been initialized.
#define LDMA_DESCRIPTOR_SINGLE_M2P_BYTE(src, dest, count)
DMA descriptor initializer for byte transfers from memory to a peripheral.
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.
uint8_t ldmaInitIrqPriority
#define ECODE_EMDRV_DMADRV_PARAM_ERROR
Illegal input parameter.
DMADRV_PeripheralSignal_t
Peripherals that can trigger LDMA transfers.
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.
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 LDMA_EnableChannelRequest(int ch, bool enable)
Enable or disable a LDMA channel request.