Sfoglia il codice sorgente

Added IRQ Controller API, implementation using ARM GIC and basic documentation

Vladimir Umek 8 anni fa
parent
commit
c852bdd089

+ 24 - 2
ARM.CMSIS.pdsc

@@ -11,6 +11,7 @@
     <release version="5.0.2-dev4">
       CMSIS Device:
       - Added OS Tick API
+      - Added IRQ Controller API
     </release>
     <release version="5.0.2-dev3">
       CMSIS-Core_A: 
@@ -558,6 +559,12 @@ and 8-bit Java bytecodes in Jazelle state.
 
   <apis>
     <!-- CMSIS Device API -->
+    <api Cclass="Device" Cgroup="IRQ Controller" Capiversion="1.0.0" exclusive="1">
+      <description>Device interrupt controller interface</description>
+      <files>
+        <file category="header" name="CMSIS/Core_A/Include/irq_ctrl.h"/>
+      </files>
+    </api>
     <api Cclass="Device" Cgroup="OS Tick" Capiversion="1.0.0" exclusive="1">
       <description>RTOS Kernel system tick timer interface</description>
       <files>
@@ -1840,6 +1847,7 @@ and 8-bit Java bytecodes in Jazelle state.
       <require Cclass="CMSIS"  Cgroup="CORE"/>
       <require Cclass="Device" Cgroup="Startup"/>
       <require Cclass="Device" Cgroup="OS Tick"/>
+      <require Cclass="Device" Cgroup="IRQ Controller"/>
     </condition>
     <condition id="RTOS2 RTX5 Lib">
       <description>Components required for RTOS2 RTX5 Library</description>
@@ -1855,6 +1863,13 @@ and 8-bit Java bytecodes in Jazelle state.
       <require Cclass="CMSIS"  Cgroup="CORE"/>
       <require Cclass="Device" Cgroup="Startup"/>
     </condition>
+    
+    <!-- OS Tick -->
+    <condition id="OS Tick PTIM">
+      <description>Components required for OS Tick Private Timer</description>
+      <require condition="CA5_CA9"/>
+      <require Cclass="Device" Cgroup="IRQ Controller"/>
+    </condition>
 
   </conditions>
 
@@ -2236,8 +2251,16 @@ and 8-bit Java bytecodes in Jazelle state.
       </files>
     </component>
 
+    <!-- IRQ Controller -->
+    <component Cclass="Device" Cgroup="IRQ Controller" Csub="GIC" Capiversion="1.0.0" Cversion="1.0.0" condition="ARMv7-A Device">
+      <description>IRQ Controller implementation using GIC</description>
+      <files>
+        <file category="sourceC" name="CMSIS/Core_A/Source/irq_ctrl_gic.c"/>
+      </files>
+    </component>
+
     <!-- OS Tick -->
-    <component Cclass="Device" Cgroup="OS Tick" Csub="Private Timer" Capiversion="1.0.0" Cversion="1.0.0" condition="CA5_CA9">
+    <component Cclass="Device" Cgroup="OS Tick" Csub="Private Timer" Capiversion="1.0.0" Cversion="1.0.0" condition="OS Tick PTIM">
       <description>OS Tick implementation using Private Timer</description>
       <files>
         <file category="sourceC" name="CMSIS/RTOS2/Source/os_tick_ptim.c"/>
@@ -2646,7 +2669,6 @@ and 8-bit Java bytecodes in Jazelle state.
         <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_msgqueue.c"/>
         <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_system.c"/>
         <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_evr.c"/>
-        <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_gic.c"/>
         <!-- RTX sources (library configuration) -->
         <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_lib.c"/>
         <!-- RTX sources (handlers ARMCC) -->

+ 180 - 0
CMSIS/Core_A/Include/irq_ctrl.h

@@ -0,0 +1,180 @@
+/**************************************************************************//**
+ * @file     irq_ctrl.h
+ * @brief    Interrupt Controller API header file
+ * @version  V1.0.0
+ * @date     23. June 2017
+ ******************************************************************************/
+/*
+ * Copyright (c) 2017 ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IRQ_CTRL_H_
+#define IRQ_CTRL_H_
+
+#include <stdint.h>
+
+#ifndef IRQHANDLER_T
+#define IRQHANDLER_T
+/// Interrupt handler data type
+typedef void (*IRQHandler_t) (void);
+#endif
+
+#ifndef IRQN_ID_T
+#define IRQN_ID_T
+/// Interrupt ID number data type
+typedef int32_t IRQn_ID_t;
+#endif
+
+/* Interrupt mode bit-masks */
+#define IRQ_MODE_TRIG_Pos           (0U)
+#define IRQ_MODE_TRIG_Msk           (0x07UL /*<< IRQ_MODE_TRIG_Pos*/)
+#define IRQ_MODE_TRIG_LEVEL         (0x00UL /*<< IRQ_MODE_TRIG_Pos*/) ///< Trigger: level triggered interrupt
+#define IRQ_MODE_TRIG_LEVEL_LOW     (0x01UL /*<< IRQ_MODE_TRIG_Pos*/) ///< Trigger: low level triggered interrupt
+#define IRQ_MODE_TRIG_LEVEL_HIGH    (0x02UL /*<< IRQ_MODE_TRIG_Pos*/) ///< Trigger: high level triggered interrupt
+#define IRQ_MODE_TRIG_EDGE          (0x04UL /*<< IRQ_MODE_TRIG_Pos*/) ///< Trigger: edge triggered interrupt
+#define IRQ_MODE_TRIG_EDGE_RISING   (0x05UL /*<< IRQ_MODE_TRIG_Pos*/) ///< Trigger: rising edge triggered interrupt
+#define IRQ_MODE_TRIG_EDGE_FALLING  (0x06UL /*<< IRQ_MODE_TRIG_Pos*/) ///< Trigger: falling edge triggered interrupt
+#define IRQ_MODE_TRIG_EDGE_BOTH     (0x07UL /*<< IRQ_MODE_TRIG_Pos*/) ///< Trigger: rising and falling edge triggered interrupt
+
+#define IRQ_MODE_TYPE_Pos           (3U)
+#define IRQ_MODE_TYPE_Msk           (0x01UL << IRQ_MODE_TYPE_Pos)
+#define IRQ_MODE_TYPE_IRQ           (0x00UL << IRQ_MODE_TYPE_Pos)     ///< Type: interrupt source triggers CPU IRQ line
+#define IRQ_MODE_TYPE_FIQ           (0x01UL << IRQ_MODE_TYPE_Pos)     ///< Type: interrupt source triggers CPU FIQ line
+
+#define IRQ_MODE_DOMAIN_Pos         (4U)
+#define IRQ_MODE_DOMAIN_Msk         (0x01UL << IRQ_MODE_DOMAIN_Pos)
+#define IRQ_MODE_DOMAIN_NONSECURE   (0x00UL << IRQ_MODE_DOMAIN_Pos)   ///< Domain: interrupt is targeting non-secure domain
+#define IRQ_MODE_DOMAIN_SECURE      (0x01UL << IRQ_MODE_DOMAIN_Pos)   ///< Domain: interrupt is targeting secure domain
+
+#define IRQ_MODE_CPU_Pos            (5U)
+#define IRQ_MODE_CPU_Msk            (0xFFUL << IRQ_MODE_CPU_Pos)
+#define IRQ_MODE_CPU_ALL            (0x00UL << IRQ_MODE_CPU_Pos)      ///< CPU: interrupt targets all CPUs
+#define IRQ_MODE_CPU_0              (0x01UL << IRQ_MODE_CPU_Pos)      ///< CPU: interrupt targets CPU 0
+#define IRQ_MODE_CPU_1              (0x02UL << IRQ_MODE_CPU_Pos)      ///< CPU: interrupt targets CPU 1
+#define IRQ_MODE_CPU_2              (0x04UL << IRQ_MODE_CPU_Pos)      ///< CPU: interrupt targets CPU 2
+#define IRQ_MODE_CPU_3              (0x08UL << IRQ_MODE_CPU_Pos)      ///< CPU: interrupt targets CPU 3
+#define IRQ_MODE_CPU_4              (0x10UL << IRQ_MODE_CPU_Pos)      ///< CPU: interrupt targets CPU 4
+#define IRQ_MODE_CPU_5              (0x20UL << IRQ_MODE_CPU_Pos)      ///< CPU: interrupt targets CPU 5
+#define IRQ_MODE_CPU_6              (0x40UL << IRQ_MODE_CPU_Pos)      ///< CPU: interrupt targets CPU 6
+#define IRQ_MODE_CPU_7              (0x80UL << IRQ_MODE_CPU_Pos)      ///< CPU: interrupt targets CPU 7
+
+#define IRQ_MODE_ERROR              (0x80000000UL)                    ///< Bit indicating mode value error
+
+/* Interrupt priority bit-masks */
+#define IRQ_PRIORITY_Msk            (0x0000FFFFUL)                    ///< Interrupt priority value bit-mask
+#define IRQ_PRIORITY_ERROR          (0x80000000UL)                    ///< Bit indicating priority value error
+
+/// Initialize interrupt controller.
+/// \return 0 on success, -1 on error.
+int32_t IRQ_Initialize (void);
+
+/// Register interrupt handler.
+/// \param[in]     irqn          interrupt ID number
+/// \param[in]     handler       interrupt handler function address
+/// \return 0 on success, -1 on error.
+int32_t IRQ_SetHandler (IRQn_ID_t irqn, IRQHandler_t handler);
+
+/// Get the registered interrupt handler.
+/// \param[in]     irqn          interrupt ID number
+/// \return registered interrupt handler function address.
+IRQHandler_t IRQ_GetHandler (IRQn_ID_t irqn);
+
+/// Enable interrupt.
+/// \param[in]     irqn          interrupt ID number
+/// \return 0 on success, -1 on error.
+int32_t IRQ_Enable (IRQn_ID_t irqn);
+
+/// Disable interrupt.
+/// \param[in]     irqn          interrupt ID number
+/// \return 0 on success, -1 on error.
+int32_t IRQ_Disable (IRQn_ID_t irqn);
+
+/// Get interrupt enable state.
+/// \param[in]     irqn          interrupt ID number
+/// \return 0 - interrupt is disabled, 1 - interrupt is enabled.
+uint32_t IRQ_GetEnableState (IRQn_ID_t irqn);
+
+/// Configure interrupt request mode.
+/// \param[in]     irqn          interrupt ID number
+/// \param[in]     mode          mode configuration
+/// \return 0 on success, -1 on error.
+int32_t IRQ_SetMode (IRQn_ID_t irqn, uint32_t mode);
+
+/// Get interrupt mode configuration.
+/// \param[in]     irqn          interrupt ID number
+/// \return current interrupt mode configuration with optional IRQ_MODE_ERROR bit set.
+uint32_t IRQ_GetMode (IRQn_ID_t irqn);
+
+/// Get ID number of current interrupt request (IRQ).
+/// \return interrupt ID number.
+IRQn_ID_t IRQ_GetActiveIRQ (void);
+
+/// Get ID number of current fast interrupt request (FIQ).
+/// \return interrupt ID number.
+IRQn_ID_t IRQ_GetActiveFIQ (void);
+
+/// Signal end of interrupt processing.
+/// \param[in]     irqn          interrupt ID number
+/// \return 0 on success, -1 on error.
+int32_t IRQ_EndOfInterrupt (IRQn_ID_t irqn);
+
+/// Set interrupt pending flag.
+/// \param[in]     irqn          interrupt ID number
+/// \return 0 on success, -1 on error.
+int32_t IRQ_SetPending (IRQn_ID_t irqn);
+
+/// Get interrupt pending flag.
+/// \param[in]     irqn          interrupt ID number
+/// \return 0 - interrupt is not pending, 1 - interrupt is pending.
+uint32_t IRQ_GetPending (IRQn_ID_t irqn);
+
+/// Clear interrupt pending flag.
+/// \param[in]     irqn          interrupt ID number
+/// \return 0 on success, -1 on error.
+int32_t IRQ_ClearPending (IRQn_ID_t irqn);
+
+/// Set interrupt priority value.
+/// \param[in]     irqn          interrupt ID number
+/// \param[in]     priority      interrupt priority value
+/// \return 0 on success, -1 on error.
+int32_t IRQ_SetPriority (IRQn_ID_t irqn, uint32_t priority);
+
+/// Get interrupt priority.
+/// \param[in]     irqn          interrupt ID number
+/// \return current interrupt priority value with optional IRQ_PRIORITY_ERROR bit set.
+uint32_t IRQ_GetPriority (IRQn_ID_t irqn);
+
+/// Set priority masking threshold.
+/// \param[in]     priority      priority masking threshold value
+/// \return 0 on success, -1 on error.
+int32_t IRQ_SetPriorityMask (uint32_t priority);
+
+/// Get priority masking threshold
+/// \return current priority masking threshold value with optional IRQ_PRIORITY_ERROR bit set.
+uint32_t IRQ_GetPriorityMask (void);
+
+/// Set priority grouping field split point
+/// \param[in]     bits          number of MSB bits included in the group priority field comparison
+/// \return 0 on success, -1 on error.
+int32_t IRQ_SetPriorityGroupBits (uint32_t bits);
+
+/// Get priority grouping field split point
+/// \return current number of MSB bits included in the group priority field comparison with
+///         optional IRQ_PRIORITY_ERROR bit set.
+uint32_t IRQ_GetPriorityGroupBits (void);
+
+#endif  // IRQ_CTRL_H_

+ 396 - 0
CMSIS/Core_A/Source/irq_ctrl_gic.c

@@ -0,0 +1,396 @@
+/**************************************************************************//**
+ * @file     irq_ctrl_gic.c
+ * @brief    Interrupt controller handling implementation for GIC
+ * @version  V1.0.0
+ * @date     30. June 2017
+ ******************************************************************************/
+/*
+ * Copyright (c) 2017 ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stddef.h>
+
+#include "RTE_Components.h"
+#include CMSIS_device_header
+
+#include "irq_ctrl.h"
+
+#if defined(__GIC_PRESENT) && (__GIC_PRESENT == 1U)
+
+/// Number of implemented interrupt lines
+#ifndef IRQ_GIC_LINE_COUNT
+#define IRQ_GIC_LINE_COUNT      (1020U)
+#endif
+
+static IRQHandler IRQTable[IRQ_GIC_LINE_COUNT] = { 0U };
+static uint32_t   IRQ_ID0;
+
+/// Initialize interrupt controller.
+__WEAK int32_t IRQ_Initialize (void) {
+  uint32_t i;
+
+  for (i = 0U; i < IRQ_GIC_LINE_COUNT; i++) {
+    IRQTable[i] = (IRQHandler)NULL;
+  }
+  GIC_Enable();
+  return (0);
+}
+
+
+/// Register interrupt handler.
+__WEAK int32_t IRQ_SetHandler (IRQn_ID_t irqn, IRQHandler_t handler) {
+  int32_t status;
+
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    IRQTable[irqn] = handler;
+    status =  0;
+  } else {
+    status = -1;
+  }
+
+  return (status);
+}
+
+
+/// Get the registered interrupt handler.
+__WEAK IRQHandler_t IRQ_GetHandler (IRQn_ID_t irqn) {
+  IRQHandler h;
+
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    h = IRQTable[irqn];
+  } else {
+    h = (IRQHandler_t)0;
+  }
+
+  return (h);
+}
+
+
+/// Enable interrupt.
+__WEAK int32_t IRQ_Enable (IRQn_ID_t irqn) {
+  int32_t status;
+
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    GIC_EnableIRQ ((IRQn_Type)irqn);
+    status = 0;
+  } else {
+    status = -1;
+  }
+
+  return (status);
+}
+
+
+/// Disable interrupt.
+__WEAK int32_t IRQ_Disable (IRQn_ID_t irqn) {
+  int32_t status;
+
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    GIC_DisableIRQ ((IRQn_Type)irqn);
+    status = 0;
+  } else {
+    status = -1;
+  }
+
+  return (status);
+}
+
+
+/// Get interrupt enable state.
+__WEAK uint32_t IRQ_GetEnableState (IRQn_ID_t irqn) {
+  uint32_t enable;
+
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    enable = GIC_GetEnableIRQ((IRQn_Type)irqn);
+  } else {
+    enable = 0U;
+  }
+
+  return (enable);
+}
+
+
+/// Configure interrupt request mode.
+__WEAK int32_t IRQ_SetMode (IRQn_ID_t irqn, uint32_t mode) {
+  int32_t status;
+  uint32_t val;
+  uint8_t cfg;
+  uint8_t secure;
+  uint8_t cpu;
+
+  status = 0;
+
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    // Check triggering mode
+    val = (mode & IRQ_MODE_TRIG_Msk);
+
+    if (val == IRQ_MODE_TRIG_LEVEL) {
+      cfg = 0x00U;
+    } else if (val == IRQ_MODE_TRIG_EDGE) {
+      cfg = 0x02U;
+    } else {
+      status = -1;
+    }
+
+    // Check interrupt type
+    val = mode & IRQ_MODE_TYPE_Msk;
+
+    if (val != IRQ_MODE_TYPE_IRQ) {
+      status = -1;
+    }
+
+    // Check interrupt domain
+    val = mode & IRQ_MODE_DOMAIN_Msk;
+
+    if (val == IRQ_MODE_DOMAIN_NONSECURE) {
+      secure = 0;
+    } else {
+      // Check security extensions support
+      val = GIC_DistributorInfo() & (1UL << 10U);
+
+      if (val != 0U) {
+        // Security extensions are supported
+        secure = 1;
+      } else {
+        status = -1;
+      }
+    }
+
+    // Check interrupt CPU targets
+    val = mode & IRQ_MODE_CPU_Msk;
+
+    if (val == IRQ_MODE_CPU_ALL) {
+      cpu = 0xFF;
+    } else {
+      cpu = val >> IRQ_MODE_CPU_Pos;
+    }
+
+    // Apply configuration if no mode error
+    if (status == 0) {
+      GIC_SetConfiguration((IRQn_Type)irqn, cfg);
+      GIC_SetTarget       ((IRQn_Type)irqn, cpu);
+
+      if (secure != 0U) {
+        GIC_SetGroup ((IRQn_Type)irqn, secure);
+      }
+    }
+  }
+
+  return (status);
+}
+
+
+/// Get interrupt mode configuration.
+__WEAK uint32_t IRQ_GetMode (IRQn_ID_t irqn) {
+  uint32_t mode;
+  uint32_t val;
+
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    mode = IRQ_MODE_TYPE_IRQ;
+
+    // Get trigger mode
+    val = GIC_GetConfiguration((IRQn_Type)irqn);
+
+    if ((val & 2U) != 0U) {
+      // Corresponding interrupt is edge triggered
+      mode |= IRQ_MODE_TRIG_EDGE;
+    } else {
+      // Corresponding interrupt is level triggered
+      mode |= IRQ_MODE_TRIG_LEVEL;
+    }
+
+    // Get interrupt CPU targets
+    mode |= GIC_GetTarget ((IRQn_Type)irqn) << IRQ_MODE_CPU_Pos;
+
+  } else {
+    mode = IRQ_MODE_ERROR;
+  }
+
+  return (mode);
+}
+
+
+/// Get ID number of current interrupt request (IRQ).
+__WEAK IRQn_ID_t IRQ_GetActiveIRQ (void) {
+  IRQn_ID_t irqn;
+  uint32_t prio;
+
+  /* Dummy read to avoid GIC 390 errata 801120 */
+  GIC_GetHighPendingIRQ();
+
+  irqn = GIC_AcknowledgePending();
+
+  __DSB();
+
+  /* Workaround GIC 390 errata 733075 (GIC-390_Errata_Notice_v6.pdf, 09-Jul-2014)  */
+  /* The following workaround code is for a single-core system.  It would be       */
+  /* different in a multi-core system.                                             */
+  /* If the ID is 0 or 0x3FE or 0x3FF, then the GIC CPU interface may be locked-up */
+  /* so unlock it, otherwise service the interrupt as normal.                      */
+  /* Special IDs 1020=0x3FC and 1021=0x3FD are reserved values in GICv1 and GICv2  */
+  /* so will not occur here.                                                       */
+
+  if ((irqn == 0) || (irqn >= 0x3FE)) {
+    /* Unlock the CPU interface with a dummy write to Interrupt Priority Register */
+    prio = GIC_GetPriority((IRQn_Type)0);
+    GIC_SetPriority ((IRQn_Type)0, prio);
+
+    __DSB();
+
+    if ((irqn == 0U) && ((GIC_GetIRQStatus ((IRQn_Type)irqn) & 1U) != 0U) && (IRQ_ID0 == 0U)) {
+      /* If the ID is 0, is active and has not been seen before */
+      IRQ_ID0 = 1U;
+    }
+    /* End of Workaround GIC 390 errata 733075 */
+  }
+
+  return (irqn);
+}
+
+
+/// Get ID number of current fast interrupt request (FIQ).
+__WEAK IRQn_ID_t IRQ_GetActiveFIQ (void) {
+  return ((IRQn_ID_t)-1);
+}
+
+
+/// Signal end of interrupt processing.
+__WEAK int32_t IRQ_EndOfInterrupt (IRQn_ID_t irqn) {
+  int32_t status;
+
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    GIC_EndInterrupt ((IRQn_Type)irqn);
+
+    if (irqn == 0) {
+      IRQ_ID0 = 0U;
+    }
+
+    status = 0;
+  } else {
+    status = -1;
+  }
+
+  return (status);
+}
+
+
+/// Set interrupt pending flag.
+__WEAK int32_t IRQ_SetPending (IRQn_ID_t irqn) {
+  int32_t status;
+
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    GIC_SetPendingIRQ ((IRQn_Type)irqn);
+    status = 0;
+  } else {
+    status = -1;
+  }
+
+  return (status);
+}
+
+/// Get interrupt pending flag.
+__WEAK uint32_t IRQ_GetPending (IRQn_ID_t irqn) {
+  uint32_t pending;
+
+  if ((irqn >= 16) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    pending = GIC_GetPendingIRQ ((IRQn_Type)irqn);
+  } else {
+    pending = 0U;
+  }
+
+  return (pending & 1U);
+}
+
+
+/// Clear interrupt pending flag.
+__WEAK int32_t IRQ_ClearPending (IRQn_ID_t irqn) {
+  int32_t status;
+
+  if ((irqn >= 16) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    GIC_ClearPendingIRQ ((IRQn_Type)irqn);
+    status = 0;
+  } else {
+    status = -1;
+  }
+
+  return (status);
+}
+
+
+/// Set interrupt priority value.
+__WEAK int32_t IRQ_SetPriority (IRQn_ID_t irqn, uint32_t priority) {
+  int32_t status;
+
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    GIC_SetPriority ((IRQn_Type)irqn, priority);
+    status = 0;
+  } else {
+    status = -1;
+  }
+
+  return (status);
+}
+
+
+/// Get interrupt priority.
+__WEAK uint32_t IRQ_GetPriority (IRQn_ID_t irqn) {
+  uint32_t priority;
+
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    priority = GIC_GetPriority ((IRQn_Type)irqn);
+  } else {
+    priority = IRQ_PRIORITY_ERROR;
+  }
+
+  return (priority);
+}
+
+
+/// Set priority masking threshold.
+__WEAK int32_t IRQ_SetPriorityMask (uint32_t priority) {
+  GIC_SetInterfacePriorityMask (priority);
+  return (0);
+}
+
+
+/// Get priority masking threshold
+__WEAK uint32_t IRQ_GetPriorityMask (void) {
+  return GIC_GetInterfacePriorityMask();
+}
+
+
+/// Set priority grouping field split point
+__WEAK int32_t IRQ_SetPriorityGroupBits (uint32_t bits) {
+  int32_t status;
+
+  if (bits < 8U) {
+    GIC_SetBinaryPoint (bits);
+    status = 0;
+  } else {
+    status = -1;
+  }
+
+  return (status);
+}
+
+
+/// Get priority grouping field split point
+__WEAK uint32_t IRQ_GetPriorityGroupBits (void) {
+  return (GIC_GetBinaryPoint() & 0x07U);
+}
+
+#endif

+ 3 - 0
CMSIS/DoxyGen/Core_A/core_A.dxy

@@ -758,6 +758,9 @@ INPUT                  = src/Overview.txt \
                          src/core_ca.txt \
                          ../../Core_A/Include/cmsis_armcc.h \
                          src/cmsis_armcc.txt \
+                         ../../Core_A/Source/irq_ctrl_gic.c \
+                         ../../Core_A/Include/irq_ctrl.h \
+                         src/irq_ctrl.txt \
                          ../../../Device/ARM/ARMCA9/Include/ARMCA9.h \
                          ../../../Device/ARM/ARMCA9/Include/mem_ARMCA9.h \
                          ../../../Device/ARM/ARMCA9/Include/system_ARMCA9.h \

+ 0 - 6
CMSIS/DoxyGen/Core_A/src/core_ca.txt

@@ -573,12 +573,6 @@ Adds the pending state to the corresponding interrupt.
 \details
 Removes the pending state from the corresponding interrupt.
 
-\fn __STATIC_INLINE void GIC_SetLevelModel(IRQn_Type IRQn, uint8_t edge_level, uint8_t model)
-\details
-Determines whether the corresponding interrupt is edge-triggered or level-sensitive.
-
-\note The handling model is not available on all GIC implementations.
-
 \fn __STATIC_INLINE void GIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
 \details 
 Configures the priority of the given interrupt.

+ 612 - 0
CMSIS/DoxyGen/Core_A/src/irq_ctrl.txt

@@ -0,0 +1,612 @@
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+//  ==== IRQ Controller API ====
+/** 
+\defgroup irq_ctrl_gr IRQ Controller Functions
+\brief Provides a low level API between an device agnostic interrupt handling implementation and specific interrupt controller.
+
+\details The IRQ Controller API may be used by an arbitrary interrupt handling implementation to be easily potable across a wide range
+of controllers.
+
+A default implementation for ARM GIC (Generic Interrupt Controller) can be found in \ref irq_ctrl_gic.c.
+
+\note The default implementation is defined \c weak thus it can easily be overwritten by an alternative user implementation.
+
+@{
+*/
+
+/**
+\defgroup irq_mode_defs IRQ Mode Bit-Masks
+\brief Configure interrupt line mode
+\details
+@{
+The following codes are used as values for the parameter \em mode of the function \ref IRQ_SetMode to configure interrupt line mode.
+They are also returned by the function \ref IRQ_GetMode when retrieving interrupt line mode.
+
+The values of \b IRQ_MODE_TRIG_x definitions specify
+The values of \b IRQ_MODE_TYPE_x definitions specify
+The values of \b IRQ_MODE_DOMAIN_x definitions specify
+The values of \b IRQ_MODE_CPU_x definitions specify
+
+// Interrupt mode bit-masks
+\def IRQ_MODE_TRIG_LEVEL
+\def IRQ_MODE_TRIG_LEVEL_LOW
+\def IRQ_MODE_TRIG_LEVEL_HIGH
+\def IRQ_MODE_TRIG_EDGE
+\def IRQ_MODE_TRIG_EDGE_RISING
+\def IRQ_MODE_TRIG_EDGE_FALLING
+\def IRQ_MODE_TRIG_EDGE_BOTH
+
+\def IRQ_MODE_TYPE_IRQ
+\def IRQ_MODE_TYPE_FIQ
+
+\def IRQ_MODE_DOMAIN_NONSECURE
+\def IRQ_MODE_DOMAIN_SECURE
+
+\def IRQ_MODE_CPU_ALL
+\def IRQ_MODE_CPU_0
+\def IRQ_MODE_CPU_1
+\def IRQ_MODE_CPU_2
+\def IRQ_MODE_CPU_3
+\def IRQ_MODE_CPU_4
+\def IRQ_MODE_CPU_5
+\def IRQ_MODE_CPU_6
+\def IRQ_MODE_CPU_7
+
+\def IRQ_MODE_ERROR
+@}
+*/
+
+/**
+\defgroup irq_priority_defs IRQ Priority Bit-Masks
+\brief Definitions used by interrupt priority functions.
+\details
+@{
+The following values are used by the interrupt priority functions.
+
+The value of \b IRQ_PRIORITY_Msk specifies maximum interrupt priority value and can be used as parameter for the functions
+\ref IRQ_GetPriority and \ref IRQ_SetPriorityGroupBits to retrieve implementation specific priority values.
+
+The value of \b IRQ_PRIORITY_ERROR is used by functions \ref IRQ_GetPriority, IRQ_GetPriorityMask and \ref IRQ_GetPriorityGroupBits
+to signal function execution error.
+
+\def IRQ_PRIORITY_Msk
+\def IRQ_PRIORITY_ERROR
+@}
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn int32_t IRQ_Initialize (void) 
+\details This function initializes interrupt controller.
+
+It disables all interrupt sources, clears all pending interrupts, sets interrupt priorities to highest priority and
+configures priority mask to lowest priority. IRQ and FIQ signal lines should be enabled and all interrupt handlers should
+be set to NULL.
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+/// Number of implemented interrupt lines
+#ifndef IRQ_GIC_LINE_COUNT
+#define IRQ_GIC_LINE_COUNT      (1020U)
+#endif
+ 
+static IRQHandler IRQTable[IRQ_GIC_LINE_COUNT] = { 0U };
+ 
+int32_t IRQ_Initialize (void) {
+  uint32_t i;
+ 
+  for (i = 0U; i < IRQ_GIC_LINE_COUNT; i++) {
+    IRQTable[i] = (IRQHandler)NULL;
+  }
+  GIC_Enable();
+  return (0);
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn int32_t IRQ_SetHandler (IRQn_ID_t irqn, IRQHandler_t handler) 
+\details This function registers address of the interrupt handler callback function corresponding to the specified interrupt
+ID number.
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+int32_t IRQ_SetHandler (IRQn_ID_t irqn, IRQHandler_t handler) {
+  int32_t status;
+ 
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    IRQTable[irqn] = handler;
+    status =  0;
+  } else {
+    status = -1;
+  }
+ 
+  return (status);
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn IRQHandler_t IRQ_GetHandler (IRQn_ID_t irqn) 
+\details This function retrieves address of the interrupt handler callback function corresponding to the specified interrupt
+ID number.
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+IRQHandler_t IRQ_GetHandler (IRQn_ID_t irqn) {
+  IRQHandler h;
+ 
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    h = IRQTable[irqn];
+  } else {
+    h = (IRQHandler_t)0;
+  }
+ 
+  return (h);
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn int32_t IRQ_Enable (IRQn_ID_t irqn)
+\details This function enables forwarding of the corresponding interrupt to the CPU.
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+int32_t IRQ_Enable (IRQn_ID_t irqn) {
+  int32_t status;
+ 
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    GIC_EnableIRQ ((IRQn_Type)irqn);
+    status = 0;
+  } else {
+    status = -1;
+  }
+ 
+  return (status);
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn int32_t IRQ_Disable (IRQn_ID_t irqn)
+\details This function disabled forwarding of the corresponding interrupt to the CPU. 
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+int32_t IRQ_Disable (IRQn_ID_t irqn) {
+  int32_t status;
+ 
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    GIC_DisableIRQ ((IRQn_Type)irqn);
+    status = 0;
+  } else {
+    status = -1;
+  }
+ 
+  return (status);
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn uint32_t IRQ_GetEnableState (IRQn_ID_t irqn) 
+\details This function retrieves the interrupt enable status of the interrupt identified by the irqn parameter.
+
+Interrupt enable status can be either disabled (0) or enabled (1). Disabled status is returned for interrupts
+which cannot be identified by irqn. 
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+uint32_t IRQ_GetEnableState (IRQn_ID_t irqn) {
+  uint32_t enable;
+ 
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    enable = GIC_GetEnableIRQ((IRQn_Type)irqn);
+  } else {
+    enable = 0U;
+  }
+ 
+  return (enable);
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn int32_t IRQ_SetMode (IRQn_ID_t irqn, uint32_t mode)
+\details This function configures the interrupt triggering mode, type, secure access and target CPUs of the interrupt
+identified by the irqn parameter.
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+int32_t IRQ_SetMode (IRQn_ID_t irqn, uint32_t mode) {
+  int32_t status;
+  uint32_t val;
+  uint8_t cfg;
+  uint8_t secure;
+  uint8_t cpu;
+ 
+  status = 0;
+ 
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    // Check triggering mode
+    val = (mode & IRQ_MODE_TRIG_Msk);
+
+    if (val == IRQ_MODE_TRIG_LEVEL) {
+      cfg = 0x00U;
+    } else if (val == IRQ_MODE_TRIG_EDGE) {
+      cfg = 0x02U;
+    } else {
+      status = -1;
+    }
+ 
+    // Check interrupt type
+    val = mode & IRQ_MODE_TYPE_Msk;
+ 
+    if (val != IRQ_MODE_TYPE_IRQ) {
+      status = -1;
+    }
+ 
+    // Check interrupt domain
+    val = mode & IRQ_MODE_DOMAIN_Msk;
+ 
+    if (val == IRQ_MODE_DOMAIN_NONSECURE) {
+      secure = 0;
+    } else {
+      // Check security extensions support
+      val = GIC_DistributorInfo() & (1UL << 10U);
+ 
+      if (val != 0U) {
+        // Security extensions are supported
+        secure = 1;
+      } else {
+        status = -1;
+      }
+    }
+ 
+    // Check interrupt CPU targets
+    val = mode & IRQ_MODE_CPU_Msk;
+ 
+    if (val == IRQ_MODE_CPU_ALL) {
+      cpu = 0xFF;
+    } else {
+      cpu = val >> IRQ_MODE_CPU_Pos;
+    }
+ 
+    // Apply configuration if no mode error
+    if (status == 0) {
+      GIC_SetConfiguration((IRQn_Type)irqn, cfg);
+      GIC_SetTarget       ((IRQn_Type)irqn, cpu);
+ 
+      if (secure != 0U) {
+        GIC_SetGroup ((IRQn_Type)irqn, secure);
+      }
+    }
+  }
+ 
+  return (status);
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn uint32_t IRQ_GetMode (IRQn_ID_t irqn)
+\details This function retrieves interrupt mode configuration of the interrupt identified by the irqn parameter.
+\ref IRQ_MODE_ERROR is returned for interrupts which cannot be identified by irqn.
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+uint32_t IRQ_GetMode (IRQn_ID_t irqn) {
+  uint32_t mode;
+  uint32_t val;
+ 
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    mode = IRQ_MODE_TYPE_IRQ;
+ 
+    // Get trigger mode
+    val = GIC_GetConfiguration((IRQn_Type)irqn);
+ 
+    if ((val & 2U) != 0U) {
+      // Corresponding interrupt is edge triggered
+      mode |= IRQ_MODE_TRIG_EDGE;
+    } else {
+      // Corresponding interrupt is level triggered
+      mode |= IRQ_MODE_TRIG_LEVEL;
+    }
+ 
+    // Get interrupt CPU targets
+    mode |= GIC_GetTarget ((IRQn_Type)irqn) << IRQ_MODE_CPU_Pos;
+ 
+  } else {
+    mode = IRQ_MODE_ERROR;
+  }
+ 
+  return (mode);
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn IRQn_ID_t IRQ_GetActiveIRQ (void)
+\details This function retrieves the interrupt ID number of current IRQ source and acknowledges the interrupt. 
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+IRQn_ID_t IRQ_GetActiveIRQ (void) {
+  IRQn_ID_t irqn;
+ 
+  irqn = (IRQn_ID_t)GIC_AcknowledgePending();
+ 
+  return (irqn);
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn IRQn_ID_t IRQ_GetActiveFIQ (void)
+\details This function retrieves the interrupt ID number of current FIQ source and acknowledges the interrupt.
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+IRQn_ID_t IRQ_GetActiveFIQ (void) {
+  // FIQ is not supported, return invalid ID
+  return ((IRQn_ID_t)-1);
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn int32_t IRQ_EndOfInterrupt (IRQn_ID_t irqn)
+\details This function informs the interrupt controller that the interrupt service routine processing of the currently
+active interrupt request is completed.
+
+The parameter irqn should specify the value previously returned by the \ref IRQ_GetActiveIRQ or \ref IRQ_GetActiveFIQ functions.
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+int32_t IRQ_EndOfInterrupt (IRQn_ID_t irqn) {
+  int32_t status;
+ 
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    GIC_EndInterrupt ((IRQn_Type)irqn);
+ 
+    if (irqn == 0) {
+      IRQ_ID0 = 0U;
+    }
+ 
+    status = 0;
+  } else {
+    status = -1;
+  }
+ 
+  return (status);
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn int32_t IRQ_SetPending (IRQn_ID_t irqn) 
+\details This function sets the pending status of the interrupt identified by the irqn parameter.
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+int32_t IRQ_SetPending (IRQn_ID_t irqn) {
+  int32_t status;
+ 
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    GIC_SetPendingIRQ ((IRQn_Type)irqn);
+    status = 0;
+  } else {
+    status = -1;
+  }
+ 
+  return (status);
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn uint32_t IRQ_GetPending (IRQn_ID_t irqn)
+\details This function retrieves the pending status of the interrupt identified by the irqn parameter.
+
+Interrupt pending status can be either not pending (0) or pending (1). Not pending status is returned for interrupts which
+cannot be identified by irqn.
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+uint32_t IRQ_GetPending (IRQn_ID_t irqn) {
+  uint32_t pending;
+ 
+  if ((irqn >= 16) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    pending = GIC_GetPendingIRQ ((IRQn_Type)irqn);
+  } else {
+    pending = 0U;
+  }
+ 
+  return (pending & 1U);
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn int32_t IRQ_ClearPending (IRQn_ID_t irqn) 
+\details This function clears the pending status of the interrupt identified by the irqn parameter.
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+int32_t IRQ_ClearPending (IRQn_ID_t irqn) {
+  int32_t status;
+ 
+  if ((irqn >= 16) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    GIC_ClearPendingIRQ ((IRQn_Type)irqn);
+    status = 0;
+  } else {
+    status = -1;
+  }
+ 
+  return (status);
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn int32_t IRQ_SetPriority (IRQn_ID_t irqn, uint32_t priority)
+\details This function sets the priority of the interrupt identified by the irqn parameter.
+
+Higher priority numbers have lower priority. The highest interrupt priority has priority value 0, while the lowest value
+depends on the number of implemented priority levels.
+
+The number of implemented priority bits can be determined by setting value \ref IRQ_PRIORITY_Msk to arbitrary irqn and by
+retrieving the actual stored value with IRQ_GetPriority function.
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+int32_t IRQ_SetPriority (IRQn_ID_t irqn, uint32_t priority) {
+  int32_t status;
+ 
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    GIC_SetPriority ((IRQn_Type)irqn, priority);
+    status = 0;
+  } else {
+    status = -1;
+  }
+ 
+  return (status);
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn uint32_t IRQ_GetPriority (IRQn_ID_t irqn) 
+\details This function retrieves the priority of the interrupt identified by the irqn parameter.
+
+The valid priority value can be from zero (0) to the value of \ref IRQ_PRIORITY_Msk. \ref IRQ_PRIORITY_ERROR bit is set in
+returned value for interrupts which cannot be identified by irqn.
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+uint32_t IRQ_GetPriority (IRQn_ID_t irqn) {
+  uint32_t priority;
+ 
+  if ((irqn >= 0) && (irqn < IRQ_GIC_LINE_COUNT)) {
+    priority = GIC_GetPriority ((IRQn_Type)irqn);
+  } else {
+    priority = IRQ_PRIORITY_ERROR;
+  }
+ 
+  return (priority);
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn int32_t IRQ_SetPriorityMask (uint32_t priority) 
+\details This function sets the priority masking threshold for the current processor.
+
+It ensures that only interrupts with a higher priority than priority threshold value are signaled to the target processor.
+Function returns error status -1 if priority masking is not supported.
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+IRQ_SetPriorityMask (uint32_t priority) {
+  GIC_SetInterfacePriorityMask (priority);
+  return (0);
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn uint32_t IRQ_GetPriorityMask (void)
+\details This function retrieves the priority masking threshold for the current processor.
+
+\ref IRQ_PRIORITY_ERROR value is returned if priority masking is not supported.
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+uint32_t IRQ_GetPriorityMask (void) {
+  return GIC_GetInterfacePriorityMask();
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn int32_t IRQ_SetPriorityGroupBits (uint32_t bits)
+\details This function sets the number of MSB priority bits used to determine whether a pending interrupt has sufficient
+priority to preempt a currently active interrupt.
+
+The number of implemented group priority bits can be determined by setting value \ref IRQ_PRIORITY_Msk and by retrieving the
+actual stored value with \ref IRQ_GetPriorityGroupBits function.
+Function returns error status -1 if priority grouping is not supported.
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+int32_t IRQ_SetPriorityGroupBits (uint32_t bits) {
+  int32_t status;
+ 
+  if (bits < 8U) {
+    GIC_SetBinaryPoint (bits);
+    status = 0;
+  } else {
+    status = -1;
+  }
+ 
+  return (status);
+}
+\endcode
+*/
+
+/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
+/**
+\fn uint32_t IRQ_GetPriorityGroupBits (void) 
+\details This function retrieves the number of MSB bits used to determine whether a pending interrupt has sufficient
+priority to preempt a currently active interrupt.
+
+\ref IRQ_PRIORITY_ERROR value is returned when priority grouping is not supported.
+
+For ARM GIC the default implementation looks like the following example:
+
+\code
+uint32_t IRQ_GetPriorityGroupBits (void) {
+  return (GIC_GetBinaryPoint() & 0x07U);
+}
+\endcode
+*/
+
+/** @} */ /* group irq_ctrl_gr */