ADuCM302x Device Drivers API Reference Manual  Release 3.1.2.0
adi_dma.c
1 
52 /*============= I N C L U D E S =============*/
53 #include <adi_processor.h>
54 #include <drivers/dma/adi_dma.h>
55 #include <adi_callback.h>
56 #include <rtos_map/adi_rtos_map.h>
57 #include <drivers/general/adi_drivers_general.h>
58 
61 /*============= M I S R A =============*/
62 
63 #ifdef __ICCARM__
64 /*
65 * IAR MISRA C 2004 error suppressions.
66 *
67 * Pm011 (rule 6.3): he basic types of char, int, short, long, float, and double should not be used
68 * Need to use bool.
69 *
70 * Pm140 (rule 11.3): a cast should not be performed between a pointer type and an integral type
71 * The rule makes an exception for memory-mapped register accesses.
72 */
73 #pragma diag_suppress=Pm011,Pm140
74 #endif /* __ICCARM__ */
75 
76 /*============= D E F I N E S =============*/
77 
78 /* CCD array allocation macros */
79 #define CCD_ALIGN (0x400) /* Memory alignment required for CCD array */
80 #define CCD_SIZE (32u) /* Configure CCD allocation as an integral power of two,
81  i.e., 24 channels is allocated as 32 */
82 
83 /*============= R E G I S T E R D E F I N E S =============*/
84 
85 
86 
87 
88 /*============= T Y P E D E F I N E S =============*/
89 
91 typedef struct _DMA_CHANNEL {
92  ADI_CALLBACK pfCallback;
93  void* pCBParam;
94 } DMA_CHANNEL_CALLBACK_INFO;
95 
105 typedef struct {
106  bool Initialized;
107  DMA_CHANNEL_CALLBACK_INFO CallbackInfo[NUM_DMA_CHANNELSn];
108  uint32_t ChannelsInUse;
109 } ADI_DMA_DEV_DATA;
110 
111 
112 /*============= D A T A =============*/
113 
114 /* DMA descriptor arrays must be contiguous */
115 /* AND impose strict alignment requirements */
116 /* Each compiler has different alignment directives */
117 
118 /* ALIGNED: DMA channel control data array declaration */
119 ADI_ALIGNED_PRAGMA(CCD_ALIGN)
120 static ADI_DCC_TypeDef gChannelControlDataArray[CCD_SIZE * 2u] ADI_ALIGNED_ATTRIBUTE(CCD_ALIGN)
121 
122 #ifdef ADI_DMA_DESCRIPTORS_IN_VOLATILE_MEMORY
123  /* conditional placement of DMA descriptor table to volatile memory */
124  @ "volatile_ram";
125 #else
126  /* default placement to non-volatile memory (no override) */
127  ;
128 #endif
129 
130 
131 /* pointer to the primary CCD array */
132 ADI_DCC_TypeDef* const pPrimaryCCD = &gChannelControlDataArray[0];
133 
134 /* pointer to the alternate CCD array */
135 ADI_DCC_TypeDef* const pAlternateCCD = &gChannelControlDataArray[CCD_SIZE];
136 
137 
142 static ADI_DMA_DEV_DATA DMA_DevData = {
143 
144  false,
145  {{0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
146  {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
147  {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
148  {0,0}, {0,0}, {0,0}},
149  0ul
150 };
151 
153 static ADI_DMA_DEV_DATA* const pDMA_DevData = &DMA_DevData;
154 
155 /*============= Local function declarations =============*/
156 
157 /*========== DMA HANDLERS ==========*/
158 
160 void DMA_Err_Int_Handler(void);
161 
162 /*========== U T I L I T Y M A C R O S ==========*/
163 
165 /*============= A P I I M P L E M E N T A T I O N S =============*/
166 
175 void adi_dma_Init(void)
176 {
177  ADI_INT_STATUS_ALLOC();
178  ADI_ENTER_CRITICAL_REGION();
179 
180  if( false == pDMA_DevData->Initialized )
181  {
182  pDMA_DevData->Initialized = true;
183 
184  /* Enable the DMA Controller */
185  pADI_DMA0->CFG |= BITM_DMA_CFG_MEN;
186 
187  /* Set descriptor memory base pointer on DMA controller */
188  pADI_DMA0->PDBPTR = (uint32_t)pPrimaryCCD;
189 
190  /* Enable the DMA Error Interrupt */
191  NVIC_EnableIRQ(DMA_CHAN_ERR_IRQn);
192 
193  /* Reset per-channel, bitmapped control registers (W1C) */
194  const uint32_t w1r_value = (uint32_t) ((1 << NUM_DMA_CHANNELSn) - 1);
195  pADI_DMA0->RMSK_SET = w1r_value;
196  pADI_DMA0->EN_CLR = w1r_value;
197  pADI_DMA0->ALT_CLR = w1r_value;
198  pADI_DMA0->PRI_CLR = w1r_value;
199  pADI_DMA0->ERRCHNL_CLR = w1r_value;
200  pADI_DMA0->ERR_CLR = w1r_value;
201  pADI_DMA0->INVALIDDESC_CLR = w1r_value;
202  }
203 
204  ADI_EXIT_CRITICAL_REGION();
205 }
206 
224  DMA_CHANn_TypeDef const eChannelID,
225  ADI_CALLBACK const pfCallback,
226  void* const pCBParam
227  )
228 {
230 
231 #ifdef ADI_DEBUG
232  /* DMA must be initialized first */
233  if (false == pDMA_DevData->Initialized) {
235  }else{
236  const size_t numChannelId = sizeof(pDMA_DevData->CallbackInfo) / sizeof(DMA_CHANNEL_CALLBACK_INFO);
237  if (numChannelId <= eChannelID)
238  {
240  }
241  }
242  if (ADI_DMA_SUCCESS == result) /* if no errors previously detected */
243 #endif
244  {
245  /* eChannelID cannot be out of range by definition (we use DMA_CHANn_TypeDef) */
246  DMA_CHANNEL_CALLBACK_INFO * pChannel = &pDMA_DevData->CallbackInfo[eChannelID];
247 
248  /* Set the callback parameters */
249  pChannel->pfCallback = pfCallback; /* assign the pointer to a callback function */
250  pChannel->pCBParam = pCBParam; /* store the parameters to be used with the callback function */
251 
252  const uint32_t nChannelBit = (1u << eChannelID);
253  if (NULL != pfCallback) {
254  pDMA_DevData->ChannelsInUse |= nChannelBit; /* set the bit to mark the channel as "being used" */
255  }else{
256  pDMA_DevData->ChannelsInUse &= (~nChannelBit); /* clear the bit to mark the channel as "not being used" */
257  }
258  }
259  return result;
260 }
261 
265 #if defined(__ICCARM__)
266 
267 /* ARM Cortex-M3/M4, IAR compiler (CMSIS standard) */
268 #define ADI_CLZ(X) __CLZ(X)
269 
270 #elif defined(__GNUC__)
271 
272 /* ARM Cortex-M3/M4, GNU-ARM compiler */
273 #define ADI_CLZ(X) __builtin_clz(X)
274 
275 #elif defined(__CC_ARM)
276 
277 /* ARM Cortex-M3/M4, Keil compiler */
278 #define ADI_CLZ(X) __clz(X)
279 
280 #else
281 
282 #error "Macro ADI_CLZ undefined!!!"
283 
284 #endif
285 
295 void DMA_Err_Int_Handler(void)
296 {
297  ISR_PROLOG()
298 
299  const uint32_t nErrClr = pADI_DMA0->ERR_CLR; /* get all the bits set in ERR_CLR */
300  const uint32_t nErrChnClr = pADI_DMA0->ERRCHNL_CLR; /* get all the bits set in ERRCHNL_CLR */
301  const uint32_t nInvdDescClr = pADI_DMA0->INVALIDDESC_CLR; /* get all the bits set in INVALIDDESC_CLR */
302 
303  /* if there are invalid channel descriptors or channel errors amongts the channels in use */
304  uint32_t functionsToBeCalled = pDMA_DevData->ChannelsInUse & (nErrChnClr | nInvdDescClr);
305 
306  if (functionsToBeCalled > 0u)
307  {
308  const uint32_t numBits = sizeof(uint32_t) << 3; /* maximum number of bits to be considered */
309  uint32_t nlz; /* number of leading zeroes in functionsToBeCalled */
310 
311  /* For all the bits set in functionsToBeCalled, starting from the MSB */
312  for (nlz = (uint32_t) ADI_CLZ(functionsToBeCalled); nlz < numBits; nlz = (uint32_t) ADI_CLZ(functionsToBeCalled))
313  {
314  const uint32_t bitSet = numBits - nlz - 1u; /* bit position in functionsToBeCalled */
315  const uint32_t selected_bit = ((uint32_t)1u << bitSet);
316  DMA_CHANNEL_CALLBACK_INFO* pChannel = &pDMA_DevData->CallbackInfo[bitSet];
317 
318  /* if there's a callback function to be called */
319  if (NULL != pChannel->pfCallback)
320  {
321  /* define the nature of the error: DMA bus error or else invalid descriptor */
322  uint32_t nEvent = ((nErrChnClr & selected_bit) != 0u)
323  ? (uint32_t)ADI_DMA_EVENT_ERR_BUS
325 
326  /* report the error to the peripheral through the callback function */
327  pChannel->pfCallback (pChannel->pCBParam, nEvent, NULL );
328  }
329 
330  functionsToBeCalled &= ~selected_bit; /* clear bit in functionsToBeCalled */
331  }
332  }
333 
334  /* Clear the errors processed in the loop above */
335  pADI_DMA0->ERRCHNL_CLR = nErrChnClr; /* W1C: clear only all the bits set in nErrChnClr */
336  pADI_DMA0->INVALIDDESC_CLR = nInvdDescClr; /* W1C: clear only all the bits set in nInvdDescClr */
337  pADI_DMA0->ERR_CLR = nErrClr; /* W1C: clear only all the bits set in nErrClr */
338 
339  ISR_EPILOG()
340 }
341 
ADI_DMA_RESULT adi_dma_RegisterCallback(DMA_CHANn_TypeDef const eChannelID, ADI_CALLBACK const pfCallback, void *const pCBParam)
Register a call-back function for a DMA channel.
Definition: adi_dma.c:223
void adi_dma_Init(void)
Initialize the DMA peripheral.
Definition: adi_dma.c:175
ADI_DMA_RESULT
Definition: adi_dma.h:154