ADuCM4x50 Device Drivers API Reference Manual  Release 4.0.0.0
adi_xint.c
1 
13 #include <stddef.h>
14 #include <string.h>
15 #include <assert.h>
16 #include <drivers/xint/adi_xint.h>
17 #include <rtos_map/adi_rtos_map.h>
18 #include "adi_xint_def.h"
19 
20 #ifdef __ICCARM__
21 /*
22 * IAR MISRA C 2004 error suppressions.
23 *
24 * Pm073 (rule 14.7): a function should have a single point of exit
25 * Pm143 (rule 14.7): a function should have a single point of exit at the end of the function
26 * Multiple returns are used for error handling.
27 * Pm140 (rule 11.3): a cast should not be performed between a pointer type and an integral type
28 * The rule makes an exception for memory-mapped register accesses.
29 * Pm140 (rule 10.3): illegal explicit conversion from underlying MISRA type unsigned int to enum
30 * The typecast is used for efficiency of the code.
31 * Pm140 (rule 17.4): array indexing shall only be applied to objects defined as an array
32 * Array indexing is required on the pointer. The memory for gpCallbackTable is passed from application
33 */
34 #pragma diag_suppress=Pm073,Pm143,Pm140,Pm136,Pm152
35 #endif /* __ICCARM__ */
36 
37 static inline void XIntCommonInterruptHandler (const ADI_XINT_EVENT eEvent);
38 void Ext_Int0_Handler(void);
39 void Ext_Int1_Handler(void);
40 void Ext_Int2_Handler(void);
41 void Ext_Int3_Handler(void);
42 
43 
44 
45 /*========== D A T A ==========*/
46 
47 static ADI_XINT_CALLBACK_INFO *gpCallbackTable;
48 
74 ADI_XINT_RESULT adi_xint_Init(void* const pMemory,
75  uint32_t const MemorySize
76 )
77 {
78 
79 #ifdef ADI_DEBUG
80  /* Verify the given memory pointer */
81  if(NULL == pMemory)
82  {
84  }
85  /* Check if the memory size is sufficient to operate the driver */
86  if(MemorySize < ADI_XINT_MEMORY_SIZE)
87  {
89  }
90  assert(MemorySize == (sizeof(ADI_XINT_CALLBACK_INFO) * ADI_XINT_EVENT_MAX));
91 #endif
92 
93  /* Only initialize on 1st init call, i.e., preserve callbacks on multiple inits */
94  if (gpCallbackTable == NULL)
95  {
96  /* Clear the memory passed by the application */
97  memset(pMemory, 0, MemorySize);
98 
99  gpCallbackTable = (ADI_XINT_CALLBACK_INFO *)pMemory;
100  }
101  return (ADI_XINT_SUCCESS);
102 }
103 
104 
117 {
118 
119 #ifdef ADI_DEBUG
120  /* IF (not initialized) */
121  if (NULL == gpCallbackTable)
122  {
123  /* return error if not initialized */
124  return (ADI_XINT_NOT_INITIALIZED);
125  }
126 #endif
127 
128  /* Clear the callback pointer */
129  gpCallbackTable = NULL;
130 
131  return (ADI_XINT_SUCCESS);
132 }
133 
134 
135 
159 {
160  uint32_t Mask; /* mask to manipulate the register */
161  uint32_t Pattern; /* bit pattern that will be written into the register */
162  uint32_t CfgReg; /* interrupt config register value */
163  IRQn_Type XintIrq;
164  ADI_INT_STATUS_ALLOC();
165 
166 #ifdef ADI_DEBUG
167  /* make sure we're initialized */
168  if (NULL == gpCallbackTable)
169  {
170  return (ADI_XINT_NOT_INITIALIZED);
171  }
172 #endif
173 
174  /* create the mask we'll use to clear the relevant bits in the config register */
175  Mask = (BITM_XINT_CFG0_IRQ0MDE | BITM_XINT_CFG0_IRQ0EN) << (ADI_XINT_CFG_BITS * (uint32_t)eEvent);
176 
177  /* The Pattern has to be created differently for UART RX wakeup and other events as the
178  mode and enable bits are flipped in case of UART RX */
179 
180  /* Based on the event figure out the interrupt it is mapped to */
181  if(eEvent == ADI_XINT_EVENT_UART_RX)
182  {
183  /* create the bit pattern we're going to write into the configuration register */
184  Pattern = (BITM_XINT_CFG0_UART_RX_EN | ((uint32_t)eMode << BITP_XINT_CFG0_UART_RX_MDE));
185 
186  XintIrq = XINT_EVT3_IRQn;
187  }
188  else
189  {
190  /* create the bit pattern we're going to write into the configuration register */
191  Pattern = (BITM_XINT_CFG0_IRQ0EN | eMode) << (ADI_XINT_CFG_BITS * (uint32_t)eEvent);
192 
193  XintIrq = (IRQn_Type)((uint32_t)XINT_EVT0_IRQn + (uint32_t)eEvent);
194  }
195 
196 
197  ADI_ENTER_CRITICAL_REGION();
198 
199  /* read/modify/write the appropriate bits in the register */
200  CfgReg = pADI_XINT0->CFG0;
201  CfgReg &= ~Mask;
202  CfgReg |= Pattern;
203  pADI_XINT0->CFG0 = CfgReg;
204 
205  ADI_EXIT_CRITICAL_REGION();
206 
207  /* enable the interrupt */
208  NVIC_EnableIRQ(XintIrq);
209 
210  return (ADI_XINT_SUCCESS);
211 }
212 
213 
229 {
230  uint32_t Mask; /* mask to manipulate the register */
231  uint32_t CfgReg; /* interrupt config register value */
232  IRQn_Type XintIrq; /* External interrupt IRQ the event is mapped to */
233 
234  ADI_INT_STATUS_ALLOC();
235 
236 #ifdef ADI_DEBUG
237  /* make sure we're initialized */
238  if (NULL == gpCallbackTable)
239  {
240  return (ADI_XINT_NOT_INITIALIZED);
241  }
242 #endif
243 
244  /* Based on the event figure out the interrupt it is mapped to */
245  if(eEvent == ADI_XINT_EVENT_UART_RX)
246  {
247  XintIrq = XINT_EVT3_IRQn;
248  }
249  else
250  {
251  XintIrq = (IRQn_Type)((uint32_t)XINT_EVT0_IRQn + (uint32_t)eEvent);
252  }
253 
254  /* disable the interrupt */
255  NVIC_DisableIRQ(XintIrq);
256 
257  /* create the mask we'll use to clear the relevant bits in the config register */
258  Mask = (BITM_XINT_CFG0_IRQ0MDE | BITM_XINT_CFG0_IRQ0EN) << (ADI_XINT_CFG_BITS * (uint32_t)eEvent);
259 
260  ADI_ENTER_CRITICAL_REGION();
261  /* read/modify/write the appropriate bits in the register */
262  CfgReg = pADI_XINT0->CFG0;
263  CfgReg &= ~Mask;
264  pADI_XINT0->CFG0 = CfgReg;
265  ADI_EXIT_CRITICAL_REGION();
266 
267  return (ADI_XINT_SUCCESS);
268 }
269 
270 
300 ADI_XINT_RESULT adi_xint_RegisterCallback (const ADI_XINT_EVENT eEvent, ADI_CALLBACK const pfCallback, void *const pCBParam )
301 {
302  ADI_INT_STATUS_ALLOC();
303 
304 #ifdef ADI_DEBUG
305  /* make sure we're initialized */
306  if (NULL == gpCallbackTable)
307  {
308  return (ADI_XINT_NOT_INITIALIZED);
309  }
310 #endif
311 
312  ADI_ENTER_CRITICAL_REGION();
313  gpCallbackTable[eEvent].pfCallback = pfCallback;
314  gpCallbackTable[eEvent].pCBParam = pCBParam;
315  ADI_EXIT_CRITICAL_REGION();
316 
317  /* return the status */
318  return (ADI_XINT_SUCCESS);
319 }
320 
324 /* All of the following is excluded from the doxygen output... */
325 
326 /* Common external interrupt handler */
327 static inline void XIntCommonInterruptHandler(const ADI_XINT_EVENT eEvent)
328 {
329  /* Clear the IRQ */
330  pADI_XINT0->CLR = (1u << (uint32_t)eEvent);
331 
332  /* params list is: application-registered cbParam, Event ID, and NULL */
333  if(gpCallbackTable[eEvent].pfCallback != NULL)
334  {
335  gpCallbackTable[eEvent].pfCallback (gpCallbackTable[eEvent].pCBParam, (uint32_t) eEvent, NULL);
336  }
337 }
338 
339 /* strongly-bound interrupt handlers to override the default weak bindings */
340 void Ext_Int0_Handler(void)
341 {
342  ISR_PROLOG()
343  XIntCommonInterruptHandler(ADI_XINT_EVENT_INT0);
344  ISR_EPILOG()
345 }
346 
347 void Ext_Int1_Handler(void)
348 {
349  ISR_PROLOG()
350  XIntCommonInterruptHandler(ADI_XINT_EVENT_INT1);
351  ISR_EPILOG()
352 }
353 
354 void Ext_Int2_Handler(void)
355 {
356  ISR_PROLOG()
357  XIntCommonInterruptHandler(ADI_XINT_EVENT_INT2);
358  ISR_EPILOG()
359 
360 }
361 
362 void Ext_Int3_Handler(void)
363 {
364  ISR_PROLOG()
365  if((pADI_XINT0->EXT_STAT & BITM_XINT_EXT_STAT_STAT_UART_RXWKUP)==BITM_XINT_EXT_STAT_STAT_UART_RXWKUP)
366  {
367  XIntCommonInterruptHandler(ADI_XINT_EVENT_UART_RX);
368  }
369  else
370  {
371  XIntCommonInterruptHandler(ADI_XINT_EVENT_INT3);
372  }
373  ISR_EPILOG()
374 }
375 
378 /*
379 ** EOF
380 */
ADI_XINT_EVENT
Definition: adi_xint.h:65
ADI_XINT_RESULT adi_xint_Init(void *const pMemory, uint32_t const MemorySize)
Initializes the External Interrupt Driver.
Definition: adi_xint.c:74
ADI_XINT_RESULT adi_xint_RegisterCallback(const ADI_XINT_EVENT eEvent, ADI_CALLBACK const pfCallback, void *const pCBParam)
Register or unregister an application callback function for external pin interrupts.
Definition: adi_xint.c:300
ADI_XINT_RESULT adi_xint_UnInit(void)
Un-initialize the external interrupt driver.
Definition: adi_xint.c:116
#define ADI_XINT_MEMORY_SIZE
Definition: adi_xint.h:40
ADI_XINT_RESULT
Definition: adi_xint.h:43
ADI_XINT_RESULT adi_xint_DisableIRQ(const ADI_XINT_EVENT eEvent)
Disable an External Interrupt.
Definition: adi_xint.c:228
ADI_XINT_RESULT adi_xint_EnableIRQ(const ADI_XINT_EVENT eEvent, const ADI_XINT_IRQ_MODE eMode)
Enable an External Interrupt.
Definition: adi_xint.c:158
ADI_XINT_IRQ_MODE
Definition: adi_xint.h:56