Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
Diff: targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/dma_api.c
- Revision:
- 50:a417edff4437
- Parent:
- 0:9b334a45a8ff
- Child:
- 144:ef7eb2e8f9f7
--- a/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/dma_api.c Wed Jan 13 12:45:11 2016 +0000 +++ b/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/dma_api.c Fri Jan 15 07:45:16 2016 +0000 @@ -30,10 +30,20 @@ #include <stdint.h> #include "dma_api_HAL.h" +#include "em_device.h" +#include "em_cmu.h" +#include "em_int.h" + +#ifdef DMA_PRESENT #include "em_dma.h" -#include "em_cmu.h" +#endif + +#ifdef LDMA_PRESENT +#include "em_ldma.h" +#endif /** DMA control block array, requires proper alignment. */ +#ifdef DMA_PRESENT #if defined (__ICCARM__) #pragma data_alignment=DMACTRL_ALIGNMENT DMA_DESCRIPTOR_TypeDef dmaControlBlock[DMACTRL_CH_CNT * 2]; @@ -47,6 +57,7 @@ #else #error Undefined toolkit, need to define alignment #endif +#endif /* DMA_PRESENT */ uint32_t channels = 0; // Bit vector of taken channels bool enabled = false; @@ -54,15 +65,32 @@ void dma_init(void) { if (enabled) return; + +#if defined DMA_PRESENT + CMU_ClockEnable(cmuClock_DMA, true); + CMU_ClockEnable(cmuClock_HFPER, true); // FIXME: DMA is clocked via HFCORECLK, why HFPERCLK? + DMA_Init_TypeDef dmaInit; - CMU_ClockEnable(cmuClock_DMA, true); - CMU_ClockEnable(cmuClock_HFPER, true); - - /* Configure general DMA issues */ dmaInit.hprot = 0; dmaInit.controlBlock = dmaControlBlock; DMA_Init(&dmaInit); + +#elif defined LDMA_PRESENT + CMU_ClockEnable(cmuClock_LDMA, true); + + LDMA_Init_t ldmaInit; + + ldmaInit.ldmaInitCtrlNumFixed = 0; /* All channels round-robin */ + ldmaInit.ldmaInitCtrlSyncPrsClrEn = 0; /* Do not allow PRS to clear SYNCTRIG */ + ldmaInit.ldmaInitCtrlSyncPrsSetEn = 0; /* Do not allow PRS to set SYNCTRIG */ + ldmaInit.ldmaInitIrqPriority = 2; /* IRQ Priority */ + + LDMA_Init(&ldmaInit); +#else +#error "Unrecognized DMA peripheral" +#endif + enabled = true; } @@ -97,7 +125,87 @@ int dma_channel_free(int channelid) { - channels &= ~(1 << channelid); + if( channelid >= 0 ) { + channels &= ~(1 << channelid); + } + return 0; } +#ifdef LDMA_PRESENT + +/* LDMA emlib API extensions */ + +typedef struct { + LDMAx_CBFunc_t callback; + void *userdata; +} LDMA_InternCallback_t; + +static LDMA_InternCallback_t ldmaCallback[DMA_CHAN_COUNT]; + +void LDMAx_StartTransfer( int ch, + LDMA_TransferCfg_t *transfer, + LDMA_Descriptor_t *descriptor, + LDMAx_CBFunc_t cbFunc, + void *userData ) +{ + ldmaCallback[ch].callback = cbFunc; + ldmaCallback[ch].userdata = userData; + + LDMA_StartTransfer(ch, transfer, descriptor); +} + +void LDMA_IRQHandler( void ) +{ + uint32_t pending, chnum, chmask; + + /* Get all pending and enabled interrupts */ + pending = LDMA->IF; + pending &= LDMA->IEN; + + /* Check for LDMA error */ + if ( pending & LDMA_IF_ERROR ) + { + /* Loop here to enable the debugger to see what has happened */ + while (1) + ; + } + + /* Iterate over all LDMA channels. */ + for ( chnum = 0, chmask = 1; + chnum < DMA_CHAN_COUNT; + chnum++, chmask <<= 1 ) + { + if ( pending & chmask ) + { + /* Clear interrupt flag. */ + LDMA->IFC = chmask; + + /* Do more stuff here, execute callbacks etc. */ + if ( ldmaCallback[chnum].callback ) + { + ldmaCallback[chnum].callback(chnum, false, ldmaCallback[chnum].userdata); + } + } + } +} + +/***************************************************************************//** + * @brief + * Check if LDMA channel is enabled. + * + * @param[in] ch + * LDMA channel to check. + * + * @return + * true if channel is enabled, false if not. + ******************************************************************************/ +bool LDMAx_ChannelEnabled( int ch ) +{ + EFM_ASSERT(ch < DMA_CHAN_COUNT); + uint32_t chMask = 1 << ch; + return (bool)(LDMA->CHEN & chMask); + INT_Disable(); +} + +#endif /* LDMA_PRESENT */