S32 SDK
interrupt_manager.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * THIS SOFTWARE IS PROVIDED BY NXP "AS IS" AND ANY EXPRESSED OR
7  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
8  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
9  * IN NO EVENT SHALL NXP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
10  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
12  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
14  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
15  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
16  * THE POSSIBILITY OF SUCH DAMAGE.
17  */
18 
58 #include "interrupt_manager.h"
59 
60 /*******************************************************************************
61  * Definitions
62  ******************************************************************************/
63 
67 static int32_t g_interruptDisableCount = 0;
68 
74 extern uint32_t __VECTOR_RAM[((uint32_t)(FEATURE_INTERRUPT_IRQ_MAX)) + 16U + 1U];
75 
76 /*******************************************************************************
77  * Code
78  ******************************************************************************/
79 
80 /*FUNCTION**********************************************************************
81  *
82  * Function Name : INT_SYS_InstallHandler
83  * Description : Install an interrupt handler routine for a given IRQ number
84  * This function will let application register/replace the interrupt
85  * handler for specified IRQ number. IRQ number is different than Vector
86  * number. IRQ 0 will start from Vector 16 address. Refer to reference
87  * manual for details. Also refer to startup_<CPU>.s file for each chip
88  * family to find out the default interrupt handler for each device. This
89  * function will convert the IRQ number to vector number by adding 16 to
90  * it.
91  *
92  * Note : This method is applicable only if interrupt vector is
93  * copied in RAM, __flash_vector_table__ symbol is used to
94  * control this from linker options.
95  * Implements INT_SYS_InstallHandler_Activity
96  *
97  *END**************************************************************************/
99  const isr_t newHandler,
100  isr_t* const oldHandler)
101 {
102  /* Check IRQ number */
105  DEV_ASSERT(__VECTOR_RAM != 0U);
106  /* Check whether there is vector table in RAM */
107  DEV_ASSERT((uint32_t)__VECTOR_RAM == S32_SCB->VTOR);
108 
109  /* Save the former handler pointer */
110  if (oldHandler != (isr_t *) 0)
111  {
112  *oldHandler = (isr_t)__VECTOR_RAM[((int32_t)irqNumber) + 16];
113  }
114 
115 #if FEATURE_MSCM_HAS_INTERRUPT_ROUTER
116 
117  DEV_ASSERT((uint32_t)irqNumber < MSCM_IRSPRC_COUNT);
118  /* Check routing is not read-only in case it needs to be written */
119  uint16_t cpu_enable = (uint16_t)(1UL << (MSCM->CPXNUM));
120  if ((MSCM->IRSPRC[irqNumber] & cpu_enable) == 0U)
121  {
122  DEV_ASSERT((MSCM->IRSPRC[irqNumber] & (uint16_t)(MSCM_IRSPRC_RO_MASK)) == (uint16_t)MSCM_IRSPRC_RO(0));
123  }
124 
125 #endif /* FEATURE_MSCM_HAS_INTERRUPT_ROUTER */
126 
127  /* Set handler into vector table */
128  __VECTOR_RAM[((int32_t)irqNumber) + 16] = (uint32_t)newHandler;
129 }
130 
131 /*FUNCTION**********************************************************************
132  *
133  * Function Name : INT_SYS_EnableIRQ
134  * Description : Enables an interrupt for a given IRQ number.
135  * It calls the system NVIC API to access the interrupt control
136  * register and MSCM (if available) API for interrupt routing.
137  * The input IRQ number does not include the core interrupt, only
138  * the peripheral interrupt, from 0 to a maximum supported IRQ.
139  * Implements INT_SYS_EnableIRQ_Activity
140  *END**************************************************************************/
142 {
143  /* Check IRQ number */
144  DEV_ASSERT(0 <= (int32_t)irqNumber);
146 
147  /* Enable interrupt */
148  S32_NVIC->ISER[(uint32_t)(irqNumber) >> 5U] = (uint32_t)(1UL << ((uint32_t)(irqNumber) & (uint32_t)0x1FU));
149 
150 #if FEATURE_MSCM_HAS_INTERRUPT_ROUTER
151 
152  /* Enable routing to current CPU */
153  uint16_t cpu_enable = (uint16_t)(1UL << (MSCM->CPXNUM));
154  MSCM->IRSPRC[irqNumber] |= cpu_enable;
155 
156 #endif /* FEATURE_MSCM_HAS_INTERRUPT_ROUTER */
157 }
158 
159 /*FUNCTION**********************************************************************
160  *
161  * Function Name : INT_SYS_DisableIRQ
162  * Description : Disable individual interrupt for a specified IRQ
163  * It calls the system NVIC API to access the interrupt control register
164  * and MSCM (if available) API for interrupt routing.
165  * Implements INT_SYS_DisableIRQ_Activity
166  *
167  *END**************************************************************************/
169 {
170  /* Check IRQ number */
171  DEV_ASSERT(0 <= (int32_t)irqNumber);
173 
174  /* Disable interrupt */
175  S32_NVIC->ICER[((uint32_t)(irqNumber) >> 5U)] = (uint32_t)(1UL << ((uint32_t)(irqNumber) & (uint32_t)0x1FU));
176 
177 #if FEATURE_MSCM_HAS_INTERRUPT_ROUTER
178 
179  /* Disable routing to current CPU */
180  uint16_t cpu_enable = (uint16_t)(1UL << (MSCM->CPXNUM));
181  MSCM->IRSPRC[irqNumber] &= (uint16_t)~(cpu_enable);
182 
183 #endif /* FEATURE_MSCM_HAS_INTERRUPT_ROUTER */
184 
185 }
186 
187 /*FUNCTION**********************************************************************
188  *
189  * Function Name : INT_SYS_EnableIRQGlobal
190  * Description : Enable system interrupt
191  * This function will enable the global interrupt by calling the core API
192  * Implements INT_SYS_EnableIRQGlobal_Activity
193  *
194  *END**************************************************************************/
196 {
197  /* Check and update */
198  if (g_interruptDisableCount > 0)
199  {
201 
202  if (g_interruptDisableCount <= 0)
203  {
204  /* Enable the global interrupt*/
206  }
207  }
208 }
209 
210 /*FUNCTION**********************************************************************
211  *
212  * Function Name : INT_SYS_DisableIRQGlobal
213  * Description : Disable system interrupt
214  * This function will disable the global interrupt by calling the core API
215  * Implements INT_SYS_DisableIRQGlobal_Activity
216  *
217  *END**************************************************************************/
219 {
220  /* Disable the global interrupt */
222 
223  /* Update counter*/
225 }
226 
227 /*FUNCTION**********************************************************************
228  *
229  * Function Name : INT_SYS_SetPriority
230  * Description : Set the priority of an interrupt
231  * This function will set the priority of an interrupt.
232  * Note: The priority cannot be set for every core interrupt.
233  * Implements INT_SYS_SetPriority_Activity
234  *
235  *END**************************************************************************/
236 void INT_SYS_SetPriority(IRQn_Type irqNumber, uint8_t priority)
237 {
238  /* Check IRQ number and priority. */
240  DEV_ASSERT(priority < (uint8_t)(1U << FEATURE_NVIC_PRIO_BITS));
241 
242  uint8_t shift = (uint8_t) (8U - FEATURE_NVIC_PRIO_BITS);
243 
244  if ((int32_t)irqNumber < 0)
245  {
246  uint32_t intVectorId = ((uint32_t)(irqNumber) & 0xFU);
247  uint32_t regId = intVectorId / 4U;
248  /* Compute pointer to SHPR register - avoid MISRA violation. */
249  volatile uint8_t * shpr_reg_ptr = ((regId == 1U) ? (volatile uint8_t *)&S32_SCB->SHPR1 : ((regId == 2U) ? (volatile uint8_t *)&S32_SCB->SHPR2 : (volatile uint8_t *)&S32_SCB->SHPR3));
250  /* Set Priority for Cortex-M System Interrupts */
251  shpr_reg_ptr[intVectorId % 4U] = (uint8_t)(((((uint32_t)priority) << shift)) & 0xffUL);
252  }
253  else
254  {
255  /* Set Priority for device specific Interrupts */
256  S32_NVIC->IP[(uint32_t)(irqNumber)] = (uint8_t)(((((uint32_t)priority) << shift)) & 0xFFUL);
257  }
258 }
259 
260 /*FUNCTION**********************************************************************
261  *
262  * Function Name : INT_SYS_GetPriority
263  * Description : Get the priority of an interrupt
264  * This function will get the priority of an interrupt.
265  * Note: The priority cannot be obtained for every core interrupt.
266  * Implements INT_SYS_GetPriority_Activity
267  *
268  *END**************************************************************************/
269 uint8_t INT_SYS_GetPriority(IRQn_Type irqNumber)
270 {
271  /* Check IRQ number. */
273 
274  uint8_t priority = 0U;
275  uint8_t shift = (uint8_t) (8U - FEATURE_NVIC_PRIO_BITS);
276 
277  if ((int32_t)irqNumber < 0)
278  {
279  uint32_t intVectorId = ((uint32_t)(irqNumber) & 0xFU);
280  uint32_t regId = intVectorId / 4U;
281 
282  /* Compute pointer to SHPR register - avoid MISRA violation. */
283  volatile const uint8_t * shpr_reg_ptr = ((regId == 1U) ? (volatile uint8_t *)&S32_SCB->SHPR1 : ((regId == 2U) ? (volatile uint8_t *)&S32_SCB->SHPR2 : (volatile uint8_t *)&S32_SCB->SHPR3));
284  /* Get Priority from Cortex-M System Interrupts */
285  priority = (uint8_t)(shpr_reg_ptr[intVectorId % 4U] >> (shift));
286  }
287  else
288  {
289  /* Get Priority for device specific Interrupts */
290  priority = (uint8_t)(S32_NVIC->IP[(uint32_t)(irqNumber)] >> shift);
291  }
292 
293  return priority;
294 }
295 
296 #if FEATURE_INTERRUPT_HAS_PENDING_STATE
297 /*FUNCTION**********************************************************************
298  *
299  * Function Name : INT_SYS_ClearPending
300  * Description : Clear Pending Interrupt
301  * This function clears the pending bit of a peripheral interrupt
302  * or a directed interrupt to this CPU (if available).
303  * Implements INT_SYS_ClearPending_Activity
304  *
305  *END**************************************************************************/
306 void INT_SYS_ClearPending(IRQn_Type irqNumber)
307 {
308  /* Check IRQ number */
309  DEV_ASSERT(0 <= (int32_t)irqNumber);
311 
312 #if FEATURE_MSCM_HAS_CPU_INTERRUPT_ROUTER
313 
314  if ((FEATURE_DIRECTED_CPU_INT_MIN <= irqNumber) && (irqNumber <= FEATURE_DIRECTED_CPU_INT_MAX))
315  {
316  /* Clear Directed CPU Pending Interrupt */
317  switch (MSCM->CPXNUM)
318  {
319  case 0:
320  MSCM->IRCP0IR |= (1UL << ((uint32_t)irqNumber - (uint32_t)FEATURE_DIRECTED_CPU_INT_MIN));
321  break;
322  default:
323  MSCM->IRCP1IR |= (1UL << ((uint32_t)irqNumber - (uint32_t)FEATURE_DIRECTED_CPU_INT_MIN));
324  break;
325  }
326  return;
327  }
328 #endif /* FEATURE_MSCM_HAS_CPU_INTERRUPT_ROUTER */
329 
330  /* Clear Pending Interrupt */
331  S32_NVIC->ICPR[(uint32_t)(irqNumber) >> 5U] = (uint32_t)(1UL << ((uint32_t)(irqNumber) & (uint32_t)0x1FU));
332 }
333 
334 /*FUNCTION**********************************************************************
335  *
336  * Function Name : INT_SYS_SetPending
337  * Description : Set Pending Interrupt
338  * This function configures the pending bit of a peripheral interrupt.
339  * Implements INT_SYS_SetPending_Activity
340  *
341  *END**************************************************************************/
342 void INT_SYS_SetPending(IRQn_Type irqNumber)
343 {
344  /* Check IRQ number */
345  DEV_ASSERT(0 <= (int32_t)irqNumber);
347 
348  /* Set Pending Interrupt */
349  S32_NVIC->ISPR[(uint32_t)(irqNumber) >> 5U] = (uint32_t)(1UL << ((uint32_t)(irqNumber) & (uint32_t)0x1FU));
350 }
351 
352 /*FUNCTION**********************************************************************
353  *
354  * Function Name : INT_SYS_GetPending
355  * Description : Get Pending Interrupt
356  * This function gets the pending bit of a peripheral interrupt or a directed
357  * interrupt to this CPU (if available).
358  * Implements INT_SYS_GetPending_Activity
359  *
360  *END**************************************************************************/
361 uint32_t INT_SYS_GetPending(IRQn_Type irqNumber)
362 {
363  /* Check IRQ number */
364  DEV_ASSERT(0 <= (int32_t)irqNumber);
366 
367 #if FEATURE_MSCM_HAS_CPU_INTERRUPT_ROUTER
368  /* Get Directed CPU Pending Interrupt */
369  if ((FEATURE_DIRECTED_CPU_INT_MIN <= irqNumber) && (irqNumber <= FEATURE_DIRECTED_CPU_INT_MAX))
370  {
371  return (((((MSCM->CPXNUM != 0UL) ? MSCM->IRCP1IR : MSCM->IRCP0IR) &
372  (1UL << ((uint32_t)irqNumber - (uint32_t)FEATURE_DIRECTED_CPU_INT_MIN))) != 0UL) ? 1UL : 0UL);
373  }
374 #endif /* FEATURE_MSCM_HAS_CPU_INTERRUPT_ROUTER */
375 
376  /* Get Pending Interrupt */
377  return ((uint32_t)(((S32_NVIC->ISPR[(((uint32_t)irqNumber) >> 5UL)] & (1UL << (((uint32_t)irqNumber) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
378 }
379 #endif /* FEATURE_INTERRUPT_HAS_PENDING_STATE */
380 
381 #if FEATURE_INTERRUPT_HAS_ACTIVE_STATE
382 /*FUNCTION**********************************************************************
383  *
384  * Function Name : INT_SYS_GetActive
385  * Description : Get active state of a peripheral interrupt
386  * This function gets the active state of a peripheral interrupt.
387  * Implements INT_SYS_GetActive_Activity
388  *
389  *END**************************************************************************/
390 uint32_t INT_SYS_GetActive(IRQn_Type irqNumber)
391 {
392  /* Check IRQ number */
393  DEV_ASSERT(0 <= (int32_t)irqNumber);
395 
396  /* Get Active Interrupt */
397  return ((uint32_t)(((S32_NVIC->IABR[(((uint32_t)irqNumber) >> 5UL)] & (1UL << (((uint32_t)irqNumber) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
398 }
399 #endif /* FEATURE_INTERRUPT_HAS_ACTIVE_STATE */
400 
401 #if FEATURE_MSCM_HAS_CPU_INTERRUPT_ROUTER
402 
412 /*FUNCTION**********************************************************************
413  *
414  * Function Name : INT_SYS_GenerateDirectedCpuInterrupt
415  * Description : Get active state of a peripheral interrupt
416  * This function gets the active state of a peripheral interrupt.
417  * Implements INT_SYS_GenerateDirectedCpuInterrupt_Activity
418  *
419  *END**************************************************************************/
420 void INT_SYS_GenerateDirectedCpuInterrupt(IRQn_Type irqNumber, interrupt_manager_cpu_targets_t cpu_target)
421 {
422  /* Check IRQ number */
423  DEV_ASSERT(FEATURE_DIRECTED_CPU_INT_MIN <= irqNumber);
424  DEV_ASSERT(irqNumber <= FEATURE_DIRECTED_CPU_INT_MAX);
425 
426  uint32_t reg_val = MSCM_IRCPGIR_INTID((uint32_t)irqNumber - (uint32_t)FEATURE_DIRECTED_CPU_INT_MIN);
427 
428  switch (cpu_target)
429  {
430  case INTERRUPT_MANAGER_TARGET_SELF:
431  reg_val |= MSCM_IRCPGIR_TLF(2);
432  break;
433  case INTERRUPT_MANAGER_TARGET_OTHERS:
434  reg_val |= MSCM_IRCPGIR_TLF(1);
435  break;
436  case INTERRUPT_MANAGER_TARGET_NONE:
437  case INTERRUPT_MANAGER_TARGET_CP0:
438  case INTERRUPT_MANAGER_TARGET_CP1:
439  case INTERRUPT_MANAGER_TARGET_CP0_CP1:
440  reg_val |= (MSCM_IRCPGIR_TLF(0) | MSCM_IRCPGIR_CPUTL(cpu_target));
441  break;
442  default:
443  /* Not treated case ? */
444  break;
445  }
446 
447  /* Generate Directed CPU Interrupt */
448  MSCM->IRCPGIR = reg_val;
449 }
450 
451 #endif /* FEATURE_MSCM_HAS_CPU_INTERRUPT_ROUTER */
452 
453 /*******************************************************************************
454  * EOF
455  ******************************************************************************/
uint32_t __VECTOR_RAM[((uint32_t)(FEATURE_INTERRUPT_IRQ_MAX))+16U+1U]
Declaration of vector table. FEATURE_INTERRUPT_IRQ_MAX is the highest interrupt request number...
#define S32_NVIC
Definition: S32K142.h:9116
#define FEATURE_INTERRUPT_IRQ_MIN
void INT_SYS_DisableIRQ(IRQn_Type irqNumber)
Disables an interrupt for a given IRQ number.
void INT_SYS_DisableIRQGlobal(void)
Disable system interrupt.
#define DEV_ASSERT(x)
Definition: devassert.h:77
static int32_t g_interruptDisableCount
Counter to manage the nested callings of global disable/enable interrupt.
#define S32_SCB
Definition: S32K142.h:9720
#define FEATURE_NVIC_PRIO_BITS
#define ENABLE_INTERRUPTS()
Enable FPU.
Definition: s32_core_cm4.h:97
void INT_SYS_SetPriority(IRQn_Type irqNumber, uint8_t priority)
Set Interrupt Priority.
void INT_SYS_EnableIRQGlobal(void)
Enables system interrupt.
#define FEATURE_INTERRUPT_IRQ_MAX
#define MSCM
Definition: S32K142.h:7792
uint8_t INT_SYS_GetPriority(IRQn_Type irqNumber)
Get Interrupt Priority.
void INT_SYS_EnableIRQ(IRQn_Type irqNumber)
Enables an interrupt for a given IRQ number.
void(* isr_t)(void)
Interrupt handler type.
#define DISABLE_INTERRUPTS()
Disable interrupts.
Definition: s32_core_cm4.h:106
IRQn_Type
Defines the Interrupt Numbers definitions.
Definition: S32K142.h:192
void INT_SYS_InstallHandler(IRQn_Type irqNumber, const isr_t newHandler, isr_t *const oldHandler)
Installs an interrupt handler routine for a given IRQ number.