EFR32 Mighty Gecko 13 Software Documentation  efr32mg13-doc-5.1.2
em_ldma.c
Go to the documentation of this file.
1 /***************************************************************************/
33 #include "em_ldma.h"
34 
35 #if defined( LDMA_PRESENT ) && ( LDMA_COUNT == 1 )
36 
37 #include <stddef.h>
38 #include "em_assert.h"
39 #include "em_bus.h"
40 #include "em_cmu.h"
41 #include "em_core.h"
42 
43 /***************************************************************************/
48 /***************************************************************************/
53 #if defined( LDMA_IRQ_HANDLER_TEMPLATE )
54 /***************************************************************************/
58 void LDMA_IRQHandler(void)
59 {
60  uint32_t ch;
61  /* Get all pending and enabled interrupts. */
62  uint32_t pending = LDMA_IntGetEnabled();
63 
64  /* Loop here on an LDMA error to enable debugging. */
65  while (pending & LDMA_IF_ERROR)
66  {
67  }
68 
69  /* Iterate over all LDMA channels. */
70  for (ch = 0; ch < DMA_CHAN_COUNT; ch++)
71  {
72  uint32_t mask = 0x1 << ch;
73  if (pending & mask)
74  {
75  /* Clear interrupt flag. */
76  LDMA->IFC = mask;
77 
78  /* Do more stuff here, execute callbacks etc. */
79  }
80  }
81 }
82 #endif
83 
84 /***************************************************************************/
90 void LDMA_DeInit(void)
91 {
92  NVIC_DisableIRQ(LDMA_IRQn);
93  LDMA->IEN = 0;
94  LDMA->CHEN = 0;
96 }
97 
98 /***************************************************************************/
112 void LDMA_EnableChannelRequest(int ch, bool enable)
113 {
114  EFM_ASSERT(ch < DMA_CHAN_COUNT);
115 
116  BUS_RegBitWrite(&LDMA->REQDIS, ch, !enable);
117 }
118 
119 /***************************************************************************/
137 void LDMA_Init(const LDMA_Init_t *init)
138 {
139  EFM_ASSERT(init != NULL);
140  EFM_ASSERT(!((init->ldmaInitCtrlNumFixed << _LDMA_CTRL_NUMFIXED_SHIFT)
146  EFM_ASSERT(init->ldmaInitIrqPriority < (1 << __NVIC_PRIO_BITS));
147 
149 
153 
154  LDMA->CHEN = 0;
155  LDMA->DBGHALT = 0;
156  LDMA->REQDIS = 0;
157 
158  /* Enable LDMA error interrupt. */
159  LDMA->IEN = LDMA_IEN_ERROR;
160  LDMA->IFC = 0xFFFFFFFF;
161 
162  NVIC_ClearPendingIRQ(LDMA_IRQn);
163 
164  /* Range is 0..7, 0 is highest priority. */
165  NVIC_SetPriority(LDMA_IRQn, init->ldmaInitIrqPriority);
166 
167  NVIC_EnableIRQ(LDMA_IRQn);
168 }
169 
170 /***************************************************************************/
183 void LDMA_StartTransfer(int ch,
184  const LDMA_TransferCfg_t *transfer,
185  const LDMA_Descriptor_t *descriptor)
186 {
187  uint32_t tmp;
189  uint32_t chMask = 1 << ch;
190 
191  EFM_ASSERT(ch < DMA_CHAN_COUNT);
192  EFM_ASSERT(transfer != NULL);
193  EFM_ASSERT(!(transfer->ldmaReqSel & ~_LDMA_CH_REQSEL_MASK));
194 
195  EFM_ASSERT(!((transfer->ldmaCtrlSyncPrsClrOff << _LDMA_CTRL_SYNCPRSCLREN_SHIFT)
197  EFM_ASSERT(!((transfer->ldmaCtrlSyncPrsClrOn << _LDMA_CTRL_SYNCPRSCLREN_SHIFT)
199  EFM_ASSERT(!((transfer->ldmaCtrlSyncPrsSetOff << _LDMA_CTRL_SYNCPRSSETEN_SHIFT)
201  EFM_ASSERT(!((transfer->ldmaCtrlSyncPrsSetOn << _LDMA_CTRL_SYNCPRSSETEN_SHIFT)
203 
204  EFM_ASSERT(!((transfer->ldmaCfgArbSlots << _LDMA_CH_CFG_ARBSLOTS_SHIFT)
206  EFM_ASSERT(!((transfer->ldmaCfgSrcIncSign << _LDMA_CH_CFG_SRCINCSIGN_SHIFT)
208  EFM_ASSERT(!((transfer->ldmaCfgDstIncSign << _LDMA_CH_CFG_DSTINCSIGN_SHIFT)
210  EFM_ASSERT(!((transfer->ldmaLoopCnt << _LDMA_CH_LOOP_LOOPCNT_SHIFT)
212 
213  LDMA->CH[ch].REQSEL = transfer->ldmaReqSel;
214  LDMA->CH[ch].LOOP = (transfer->ldmaLoopCnt << _LDMA_CH_LOOP_LOOPCNT_SHIFT);
215  LDMA->CH[ch].CFG = (transfer->ldmaCfgArbSlots << _LDMA_CH_CFG_ARBSLOTS_SHIFT)
218 
219  /* Set descriptor address. */
220  LDMA->CH[ch].LINK = (uint32_t)descriptor & _LDMA_CH_LINK_LINKADDR_MASK;
221 
222  /* Clear pending channel interrupt. */
223  LDMA->IFC = chMask;
224 
225  /* Critical region. */
227 
228  /* Enable channel interrupt. */
229  LDMA->IEN |= chMask;
230 
231  if (transfer->ldmaReqDis)
232  {
233  LDMA->REQDIS |= chMask;
234  }
235 
236  if (transfer->ldmaDbgHalt)
237  {
238  LDMA->DBGHALT |= chMask;
239  }
240 
241  tmp = LDMA->CTRL;
242 
243  if (transfer->ldmaCtrlSyncPrsClrOff)
244  {
247  }
248 
249  if (transfer->ldmaCtrlSyncPrsClrOn)
250  {
252  }
253 
254  if (transfer->ldmaCtrlSyncPrsSetOff)
255  {
258  }
259 
260  if (transfer->ldmaCtrlSyncPrsSetOn)
261  {
263  }
264 
265  LDMA->CTRL = tmp;
266 
267  BUS_RegMaskedClear(&LDMA->CHDONE, chMask); /* Clear the done flag. */
268  LDMA->LINKLOAD = chMask; /* Start transfer by loading descriptor. */
269 
270  /* Critical region end. */
272 }
273 
274 /***************************************************************************/
284 void LDMA_StopTransfer(int ch)
285 {
286  uint32_t chMask = 1 << ch;
287 
288  EFM_ASSERT(ch < DMA_CHAN_COUNT);
289 
291  LDMA->IEN &= ~chMask;
292  BUS_RegMaskedClear(&LDMA->CHEN, chMask);
293  )
294 }
295 
296 /***************************************************************************/
306 bool LDMA_TransferDone(int ch)
307 {
308  bool retVal = false;
309  uint32_t chMask = 1 << ch;
310 
311  EFM_ASSERT(ch < DMA_CHAN_COUNT);
312 
314  if (((LDMA->CHEN & chMask) == 0)
315  && ((LDMA->CHDONE & chMask) == chMask))
316  {
317  retVal = true;
318  }
319  )
320  return retVal;
321 }
322 
323 /***************************************************************************/
339 {
340  uint32_t remaining, done, iflag;
341  uint32_t chMask = 1 << ch;
342 
343  EFM_ASSERT(ch < DMA_CHAN_COUNT);
344 
346  iflag = LDMA->IF;
347  done = LDMA->CHDONE;
348  remaining = LDMA->CH[ch].CTRL;
349  )
350 
351  iflag &= chMask;
352  done &= chMask;
353  remaining = (remaining & _LDMA_CH_CTRL_XFERCNT_MASK)
355 
356  if (done || ((remaining == 0) && iflag))
357  {
358  return 0;
359  }
360 
361  return remaining + 1;
362 }
363 
366 #endif /* defined( LDMA_PRESENT ) && ( LDMA_COUNT == 1 ) */
#define DMA_CHAN_COUNT
uint8_t ldmaCfgArbSlots
Definition: em_ldma.h:573
Clock management unit (CMU) API.
DMA transfer configuration structure.
Definition: em_ldma.h:564
uint8_t ldmaCtrlSyncPrsSetOn
Definition: em_ldma.h:570
uint8_t ldmaInitCtrlSyncPrsSetEn
Definition: em_ldma.h:554
#define _LDMA_CH_LOOP_LOOPCNT_MASK
#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
__STATIC_INLINE uint32_t LDMA_IntGetEnabled(void)
Get enabled and pending LDMA interrupt flags. Useful for handling more interrupt sources in the same ...
Definition: em_ldma.h:1480
Emlib peripheral API "assert" implementation.
#define _LDMA_CH_CFG_DSTINCSIGN_MASK
void LDMA_Init(const LDMA_Init_t *init)
Initialize the LDMA controller.
Definition: em_ldma.c:137
#define _LDMA_CH_LOOP_LOOPCNT_SHIFT
RAM and peripheral bit-field set and clear API.
uint8_t ldmaCtrlSyncPrsClrOn
Definition: em_ldma.h:568
#define _LDMA_CH_LINK_LINKADDR_MASK
void LDMA_StartTransfer(int ch, const LDMA_TransferCfg_t *transfer, const LDMA_Descriptor_t *descriptor)
Start a DMA transfer.
Definition: em_ldma.c:183
#define _LDMA_CH_CFG_SRCINCSIGN_SHIFT
#define _LDMA_CTRL_NUMFIXED_SHIFT
uint8_t ldmaCfgDstIncSign
Definition: em_ldma.h:575
void LDMA_StopTransfer(int ch)
Stop a DMA transfer.
Definition: em_ldma.c:284
#define LDMA_IEN_ERROR
#define _LDMA_CTRL_SYNCPRSSETEN_MASK
#define _LDMA_CTRL_SYNCPRSCLREN_MASK
#define CORE_ENTER_ATOMIC()
Definition: em_core.h:138
#define _LDMA_CH_CFG_SRCINCSIGN_MASK
#define CORE_ATOMIC_SECTION(yourcode)
Definition: em_core.h:126
void LDMA_DeInit(void)
De-initialize the LDMA controller.
Definition: em_ldma.c:90
#define _LDMA_CH_CTRL_XFERCNT_MASK
#define _LDMA_CH_CFG_DSTINCSIGN_SHIFT
uint8_t ldmaInitCtrlSyncPrsClrEn
Definition: em_ldma.h:553
#define _LDMA_CTRL_NUMFIXED_MASK
Core interrupt handling API.
void CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)
Enable/disable a clock.
Definition: em_cmu.c:1453
uint8_t ldmaCtrlSyncPrsClrOff
Definition: em_ldma.h:567
bool LDMA_TransferDone(int ch)
Check if a DMA transfer has completed.
Definition: em_ldma.c:306
uint8_t ldmaCtrlSyncPrsSetOff
Definition: em_ldma.h:569
#define _LDMA_CH_CFG_ARBSLOTS_SHIFT
#define CORE_EXIT_ATOMIC()
Definition: em_core.h:142
#define _LDMA_CTRL_SYNCPRSSETEN_SHIFT
Direct memory access (LDMA) API.
#define __NVIC_PRIO_BITS
DMA descriptor.
Definition: em_ldma.h:456
__STATIC_INLINE void BUS_RegMaskedClear(volatile uint32_t *addr, uint32_t mask)
Perform a masked clear operation on peripheral register address.
Definition: em_bus.h:253
LDMA initialization configuration structure.
Definition: em_ldma.h:550
#define _LDMA_CH_REQSEL_MASK
uint8_t ldmaInitCtrlNumFixed
Definition: em_ldma.h:552
uint8_t ldmaInitIrqPriority
Definition: em_ldma.h:555
#define _LDMA_CTRL_SYNCPRSCLREN_SHIFT
__STATIC_INLINE void BUS_RegBitWrite(volatile uint32_t *addr, unsigned int bit, unsigned int val)
Perform a single-bit write operation on a peripheral register.
Definition: em_bus.h:148
#define _LDMA_CH_CFG_ARBSLOTS_MASK
uint8_t ldmaCfgSrcIncSign
Definition: em_ldma.h:574
#define _LDMA_CH_CTRL_XFERCNT_SHIFT
uint8_t ldmaLoopCnt
Definition: em_ldma.h:576
#define LDMA_IF_ERROR
#define LDMA
void LDMA_EnableChannelRequest(int ch, bool enable)
Enable or disable a LDMA channel request.
Definition: em_ldma.c:112