[docs][libcpu][arm][cortex-a] add comment for gic.c

This commit is contained in:
laidene
2026-01-06 15:14:02 +08:00
committed by R b b666
parent 45fe9ee96b
commit ff5c5eab6b

View File

@@ -25,41 +25,60 @@ struct arm_gic
rt_uint32_t cpu_hw_base; /* the base addrees of the gic cpu interface */
};
/* 'ARM_GIC_MAX_NR' is the number of cores */
static struct arm_gic _gic_table[ARM_GIC_MAX_NR];
/** Macro to access the Generic Interrupt Controller Interface (GICC)
*/
#define GIC_CPU_CTRL(hw_base) __REG32((hw_base) + 0x00U)
#define GIC_CPU_PRIMASK(hw_base) __REG32((hw_base) + 0x04U)
#define GIC_CPU_BINPOINT(hw_base) __REG32((hw_base) + 0x08U)
#define GIC_CPU_INTACK(hw_base) __REG32((hw_base) + 0x0cU)
#define GIC_CPU_EOI(hw_base) __REG32((hw_base) + 0x10U)
#define GIC_CPU_RUNNINGPRI(hw_base) __REG32((hw_base) + 0x14U)
#define GIC_CPU_HIGHPRI(hw_base) __REG32((hw_base) + 0x18U)
#define GIC_CPU_IIDR(hw_base) __REG32((hw_base) + 0xFCU)
#define GIC_CPU_CTRL(hw_base) __REG32((hw_base) + 0x00U) /* GICC_CTLR */
#define GIC_CPU_PRIMASK(hw_base) __REG32((hw_base) + 0x04U) /* GICC_PMR */
#define GIC_CPU_BINPOINT(hw_base) __REG32((hw_base) + 0x08U) /* GICC_BPR */
#define GIC_CPU_INTACK(hw_base) __REG32((hw_base) + 0x0cU) /* GICC_IAR */
#define GIC_CPU_EOI(hw_base) __REG32((hw_base) + 0x10U) /* GICC_EOIR */
#define GIC_CPU_RUNNINGPRI(hw_base) __REG32((hw_base) + 0x14U) /* GICC_RPR */
#define GIC_CPU_HIGHPRI(hw_base) __REG32((hw_base) + 0x18U) /* GICC_HPPIR */
#define GIC_CPU_IIDR(hw_base) __REG32((hw_base) + 0xFCU) /* GICC_IIDR */
/** Macro to access the Generic Interrupt Controller Distributor (GICD)
*/
#define GIC_DIST_CTRL(hw_base) __REG32((hw_base) + 0x000U)
#define GIC_DIST_TYPE(hw_base) __REG32((hw_base) + 0x004U)
#define GIC_DIST_IGROUP(hw_base, n) __REG32((hw_base) + 0x080U + ((n)/32U) * 4U)
#define GIC_DIST_ENABLE_SET(hw_base, n) __REG32((hw_base) + 0x100U + ((n)/32U) * 4U)
#define GIC_DIST_ENABLE_CLEAR(hw_base, n) __REG32((hw_base) + 0x180U + ((n)/32U) * 4U)
#define GIC_DIST_PENDING_SET(hw_base, n) __REG32((hw_base) + 0x200U + ((n)/32U) * 4U)
#define GIC_DIST_PENDING_CLEAR(hw_base, n) __REG32((hw_base) + 0x280U + ((n)/32U) * 4U)
#define GIC_DIST_ACTIVE_SET(hw_base, n) __REG32((hw_base) + 0x300U + ((n)/32U) * 4U)
#define GIC_DIST_ACTIVE_CLEAR(hw_base, n) __REG32((hw_base) + 0x380U + ((n)/32U) * 4U)
#define GIC_DIST_PRI(hw_base, n) __REG32((hw_base) + 0x400U + ((n)/4U) * 4U)
#define GIC_DIST_TARGET(hw_base, n) __REG32((hw_base) + 0x800U + ((n)/4U) * 4U)
#define GIC_DIST_CONFIG(hw_base, n) __REG32((hw_base) + 0xc00U + ((n)/16U) * 4U)
#define GIC_DIST_SOFTINT(hw_base) __REG32((hw_base) + 0xf00U)
#define GIC_DIST_CPENDSGI(hw_base, n) __REG32((hw_base) + 0xf10U + ((n)/4U) * 4U)
#define GIC_DIST_SPENDSGI(hw_base, n) __REG32((hw_base) + 0xf20U + ((n)/4U) * 4U)
#define GIC_DIST_ICPIDR2(hw_base) __REG32((hw_base) + 0xfe8U)
#define GIC_DIST_CTRL(hw_base) __REG32((hw_base) + 0x000U) /* GICD_CTLR */
#define GIC_DIST_TYPE(hw_base) __REG32((hw_base) + 0x004U) /* GICD_TYPER */
#define GIC_DIST_IGROUP(hw_base, n) __REG32((hw_base) + 0x080U + ((n)/32U) * 4U) /* GICD_IGROUPRn */
#define GIC_DIST_ENABLE_SET(hw_base, n) __REG32((hw_base) + 0x100U + ((n)/32U) * 4U) /* GICD_ISENABLERn */
#define GIC_DIST_ENABLE_CLEAR(hw_base, n) __REG32((hw_base) + 0x180U + ((n)/32U) * 4U) /* GICD_ICENABLERn */
#define GIC_DIST_PENDING_SET(hw_base, n) __REG32((hw_base) + 0x200U + ((n)/32U) * 4U) /* GICD_ISPENDRn */
#define GIC_DIST_PENDING_CLEAR(hw_base, n) __REG32((hw_base) + 0x280U + ((n)/32U) * 4U) /* GICD_ICPENDRn */
#define GIC_DIST_ACTIVE_SET(hw_base, n) __REG32((hw_base) + 0x300U + ((n)/32U) * 4U) /* GICD_ISACTIVERn */
#define GIC_DIST_ACTIVE_CLEAR(hw_base, n) __REG32((hw_base) + 0x380U + ((n)/32U) * 4U) /* GICD_ICACTIVERn */
#define GIC_DIST_PRI(hw_base, n) __REG32((hw_base) + 0x400U + ((n)/4U) * 4U) /* GICD_IPRIORITYRn */
#define GIC_DIST_TARGET(hw_base, n) __REG32((hw_base) + 0x800U + ((n)/4U) * 4U) /* GICD_ITARGETSRn */
#define GIC_DIST_CONFIG(hw_base, n) __REG32((hw_base) + 0xc00U + ((n)/16U) * 4U) /* GICD_ICFGRn */
#define GIC_DIST_SOFTINT(hw_base) __REG32((hw_base) + 0xf00U) /* GICD_SGIR */
#define GIC_DIST_CPENDSGI(hw_base, n) __REG32((hw_base) + 0xf10U + ((n)/4U) * 4U) /* GICD_CPENDSGIRn */
#define GIC_DIST_SPENDSGI(hw_base, n) __REG32((hw_base) + 0xf20U + ((n)/4U) * 4U) /* GICD_SPENDSGIRn */
#define GIC_DIST_ICPIDR2(hw_base) __REG32((hw_base) + 0xfe8U) /* ICPIDR2 */
static unsigned int _gic_max_irq;
/**
* @brief Get the active interrupt number
*
* @note Read the GICC_IAR register and add the interrupt number offset to get
* the actual interrupt number.
* This read acts as an acknowledge for the interrupt, changing the interrupt
* state from pending to active.
*
* GICC_IAR register bit fields:
* - GICC_IAR[31:13]: Reserved, read as 0
* - GICC_IAR[12:10]: CPUID
* For SGIs: This value is the CPUID that requested the interrupt.
* For other interrupts: This value reads as 0 (RAZ).
* - GICC_IAR[9:0]: Interrupt ID
*
* @param index GIC controller index
*
* @return The actual interrupt number (with offset added).
* Note: For SGIs, the return value may include CPUID information in the upper bits.
*/
int arm_gic_get_active_irq(rt_uint32_t index)
{
int irq;
@@ -71,6 +90,21 @@ int arm_gic_get_active_irq(rt_uint32_t index)
return irq;
}
/**
* @brief Acknowledge and end the interrupt
*
* @note This function completes the interrupt handling by:
* 1. Clearing the pending status of the interrupt in the Distributor (GICD_ICPENDRn).
* 2. Writing the interrupt ID to the End of Interrupt Register (GICC_EOIR).
* This signals the GIC that interrupt processing is complete and changes
* the interrupt state from active to inactive.
*
* This function should be called after the interrupt handler has finished
* processing the interrupt, typically at the end of the interrupt service routine.
*
* @param index GIC controller index
* @param irq The actual interrupt number (with offset) to acknowledge
*/
void arm_gic_ack(rt_uint32_t index, int irq)
{
rt_uint32_t mask = 1U << (irq % 32U);
@@ -84,6 +118,12 @@ void arm_gic_ack(rt_uint32_t index, int irq)
GIC_CPU_EOI(_gic_table[index].cpu_hw_base) = irq;
}
/**
* @brief Disable the forwarding of the corresponding interrupt
*
* @param index GIC controller index
* @param irq The actual interrupt number(with offset)
*/
void arm_gic_mask(rt_uint32_t index, int irq)
{
rt_uint32_t mask = 1U << (irq % 32U);
@@ -96,6 +136,12 @@ void arm_gic_mask(rt_uint32_t index, int irq)
GIC_DIST_ENABLE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
}
/**
* @brief Enables the forwarding of the corresponding interrupt
*
* @param index GIC controller index
* @param irq The actual interrupt number(with offset)
*/
void arm_gic_umask(rt_uint32_t index, int irq)
{
rt_uint32_t mask = 1U << (irq % 32U);
@@ -105,9 +151,17 @@ void arm_gic_umask(rt_uint32_t index, int irq)
irq = irq - _gic_table[index].offset;
RT_ASSERT(irq >= 0U);
GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, irq) = mask;
GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, irq) = mask; /* GICD_ISENABLERn */
}
/**
* @brief Identifies whether the interrupt is pending
*
* @param index GIC controller index
* @param irq The actual interrupt number(with offset)
*
* @return 0: not pending, 1: pending
*/
rt_uint32_t arm_gic_get_pending_irq(rt_uint32_t index, int irq)
{
rt_uint32_t pend;
@@ -119,12 +173,12 @@ rt_uint32_t arm_gic_get_pending_irq(rt_uint32_t index, int irq)
if (irq >= 16U)
{
pend = (GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32U)) & 0x1UL;
pend = (GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32U)) & 0x1UL; /* GICD_ISPENDRn */
}
else
{
/* INTID 0-15 Software Generated Interrupt */
pend = (GIC_DIST_SPENDSGI(_gic_table[index].dist_hw_base, irq) >> ((irq % 4U) * 8U)) & 0xFFUL;
pend = (GIC_DIST_SPENDSGI(_gic_table[index].dist_hw_base, irq) >> ((irq % 4U) * 8U)) & 0xFFUL; /* GICD_SPENDSGIRn */
/* No CPU identification offered */
if (pend != 0U)
{
@@ -139,6 +193,12 @@ rt_uint32_t arm_gic_get_pending_irq(rt_uint32_t index, int irq)
return (pend);
}
/**
* @brief Set the interrupt as pending
*
* @param index GIC controller index
* @param irq The actual interrupt number(with offset)
*/
void arm_gic_set_pending_irq(rt_uint32_t index, int irq)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
@@ -158,6 +218,12 @@ void arm_gic_set_pending_irq(rt_uint32_t index, int irq)
}
}
/**
* @brief clears the pending state of the interrupt
*
* @param index GIC controller index
* @param irq The actual interrupt number(with offset)
*/
void arm_gic_clear_pending_irq(rt_uint32_t index, int irq)
{
rt_uint32_t mask;
@@ -179,6 +245,24 @@ void arm_gic_clear_pending_irq(rt_uint32_t index, int irq)
}
}
/**
* @brief Configure whether the corresponding interrupt is edge-triggered or level-sensitive
*
* @note For SGIs (interrupt IDs 0-15), the Int_config fields are read-only,
* meaning that GICD_ICFGR0 is read-only. Writing to this register for SGIs
* will have no effect.
*
* For PPIs (interrupt IDs 16-31), it is IMPLEMENTATION DEFINED whether
* the most significant bit of the Int_config field is programmable.
* Some implementations may make PPI configuration registers read-only.
*
* This function is primarily intended for configuring SPIs (interrupt IDs 32+),
* which have fully programmable configuration registers.
*
* @param index GIC controller index
* @param irq The actual interrupt number(with offset)
* @param config 0: level-sensitive, 1: edge-triggered
*/
void arm_gic_set_configuration(rt_uint32_t index, int irq, rt_uint32_t config)
{
rt_uint32_t icfgr;
@@ -198,6 +282,14 @@ void arm_gic_set_configuration(rt_uint32_t index, int irq, rt_uint32_t config)
GIC_DIST_CONFIG(_gic_table[index].dist_hw_base, irq) = icfgr;
}
/**
* @brief Identifies whether the corresponding interrupt is edge-triggered or level-sensitive
*
* @param index GIC controller index
* @param irq The actual interrupt number(with offset)
*
* @return 0: level-sensitive, 1: edge-triggered
*/
rt_uint32_t arm_gic_get_configuration(rt_uint32_t index, int irq)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
@@ -208,6 +300,12 @@ rt_uint32_t arm_gic_get_configuration(rt_uint32_t index, int irq)
return (GIC_DIST_CONFIG(_gic_table[index].dist_hw_base, irq) >> ((irq % 16U) >> 1U));
}
/**
* @brief Deactivates the corresponding interrupt
*
* @param index GIC controller index
* @param irq The actual interrupt number(with offset)
*/
void arm_gic_clear_active(rt_uint32_t index, int irq)
{
rt_uint32_t mask = 1U << (irq % 32U);
@@ -220,7 +318,14 @@ void arm_gic_clear_active(rt_uint32_t index, int irq)
GIC_DIST_ACTIVE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
}
/* Set up the cpu mask for the specific interrupt */
/**
* @brief Set up the cpu mask for the specific interrupt
*
* @param index GIC controller index
* @param irq The actual interrupt number(with offset)
*
* @param cpumask CPU targets. Only the lower 8 bits are valid (bits [7:0]).
*/
void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask)
{
rt_uint32_t old_tgt;
@@ -238,6 +343,14 @@ void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask)
GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq) = old_tgt;
}
/**
* @brief Get the CPU targets for the specific interrupt
*
* @param index GIC controller index
* @param irq The actual interrupt number(with offset)
*
* @return CPU targets
*/
rt_uint32_t arm_gic_get_target_cpu(rt_uint32_t index, int irq)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
@@ -248,6 +361,15 @@ rt_uint32_t arm_gic_get_target_cpu(rt_uint32_t index, int irq)
return (GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq) >> ((irq % 4U) * 8U)) & 0xFFUL;
}
/**
* @brief Set the priority for the specific interrupt
*
* @note The lower the value, the greater the priority of the corresponding interrupt.
*
* @param index GIC controller index
* @param irq The actual interrupt number(with offset)
* @param priority The priority to set.Only the lower 8 bits are valid (bits [7:0]).
*/
void arm_gic_set_priority(rt_uint32_t index, int irq, rt_uint32_t priority)
{
rt_uint32_t mask;
@@ -263,6 +385,15 @@ void arm_gic_set_priority(rt_uint32_t index, int irq, rt_uint32_t priority)
GIC_DIST_PRI(_gic_table[index].dist_hw_base, irq) = mask;
}
/**
* @brief Get the priority for the specific interrupt
*
* @param index GIC controller index
* @param irq The actual interrupt number(with offset)
*
* @return The priority of the corresponding interrupt.Only the lower 8 bits are valid (bits [7:0]).
*/
rt_uint32_t arm_gic_get_priority(rt_uint32_t index, int irq)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
@@ -273,6 +404,15 @@ rt_uint32_t arm_gic_get_priority(rt_uint32_t index, int irq)
return (GIC_DIST_PRI(_gic_table[index].dist_hw_base, irq) >> ((irq % 4U) * 8U)) & 0xFFUL;
}
/**
* @brief Set the priority mask for the specific CPU
*
* @note Only interrupts with higher priority than the value in this
* register are signaled to the processor.
*
* @param index GIC controller index
* @param priority The priority mask to set.Only the lower 8 bits are valid (bits [7:0]).
*/
void arm_gic_set_interface_prior_mask(rt_uint32_t index, rt_uint32_t priority)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
@@ -281,6 +421,13 @@ void arm_gic_set_interface_prior_mask(rt_uint32_t index, rt_uint32_t priority)
GIC_CPU_PRIMASK(_gic_table[index].cpu_hw_base) = priority & 0xFFUL;
}
/**
* @brief Get the priority mask for the specific CPU
*
* @param index GIC controller index
*
* @return The priority mask to return. Only the lower 8 bits are valid (bits [7:0]).
*/
rt_uint32_t arm_gic_get_interface_prior_mask(rt_uint32_t index)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
@@ -288,16 +435,49 @@ rt_uint32_t arm_gic_get_interface_prior_mask(rt_uint32_t index)
return GIC_CPU_PRIMASK(_gic_table[index].cpu_hw_base);
}
/**
* @brief Set the binary point value for interrupt priority splitting
*
* @note This function sets the GICC_BPR (Binary Point Register) value, which is used
* to split the priority field into group priority and subpriority fields.
* The binary point determines how many bits are used for group priority:
* - A larger value results in fewer bits for group priority,
* reducing interrupt preemption capability.
* - A smaller value results in more bits for group priority,
* increasing interrupt preemption capability.
* - Only the lower 3 bits are valid (bits [2:0], range 0-7).
*
* @param index GIC controller index
* @param binary_point Binary point value. Only the lower 3 bits are valid (bits [2:0]).
*/
void arm_gic_set_binary_point(rt_uint32_t index, rt_uint32_t binary_point)
{
GIC_CPU_BINPOINT(_gic_table[index].cpu_hw_base) = binary_point & 0x7U;
}
/**
* @brief Get the binary point value for interrupt priority splitting
*
* @param index GIC controller index
* @return Binary point value. Only the lower 3 bits are valid (bits [2:0]).
*/
rt_uint32_t arm_gic_get_binary_point(rt_uint32_t index)
{
return GIC_CPU_BINPOINT(_gic_table[index].cpu_hw_base);
}
/**
* @brief Get the status of the specified interrupt
*
* @note This function reads both the active and pending status of the interrupt
*
* @param index GIC controller index
* @param irq The actual interrupt number (with offset)
*
* @return Encoded interrupt status:
* - Bit 0: Pending status
* - Bit 1: Active status
*/
rt_uint32_t arm_gic_get_irq_status(rt_uint32_t index, int irq)
{
rt_uint32_t pending;
@@ -314,6 +494,28 @@ rt_uint32_t arm_gic_get_irq_status(rt_uint32_t index, int irq)
return ((active << 1U) | pending);
}
/**
* @brief Send a Software Generated Interrupt (SGI) to specified CPU(s)
*
* @note This function writes to the GICD_SGIR (Software Generated Interrupt Register)
* to generate an SGI. The register value is constructed as follows:
* - Bits [25:24]: TargetListFilter - determines how the SGI is forwarded
* * 0b00: Forward to CPUs specified in CPUTargetList
* * 0b01: Forward to all CPUs except the requesting CPU
* * 0b10: Forward only to the requesting CPU
* * 0b11: Reserved
* - Bits [23:16]: CPUTargetList - 8-bit mask specifying target CPUs
* (only used when TargetListFilter = 0b00)
* * Each bit represents a CPU: bit 0 = CPU 0, bit 1 = CPU 1, etc.
* - Bits [3:0]: SGIINTID - the SGI interrupt ID (0-15)
*
* @param index GIC controller index
* @param irq The actual interrupt number (with offset).
* @param target_list CPU target mask. Only the lower 8 bits are valid (bits [7:0]).
* Each bit represents a CPU. Used when filter_list = 0b00.
* @param filter_list Target list filter mode. Only the lower 2 bits are valid (bits [1:0]).
* Determines how the SGI is forwarded to CPUs.
*/
void arm_gic_send_sgi(rt_uint32_t index, int irq, rt_uint32_t target_list, rt_uint32_t filter_list)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
@@ -324,6 +526,21 @@ void arm_gic_send_sgi(rt_uint32_t index, int irq, rt_uint32_t target_list, rt_ui
GIC_DIST_SOFTINT(_gic_table[index].dist_hw_base) = ((filter_list & 0x3U) << 24U) | ((target_list & 0xFFUL) << 16U) | (irq & 0x0FUL);
}
/**
* @brief Get the highest priority pending interrupt ID without acknowledging it
*
* @note This function reads the GICC_HPPIR (Highest Priority Pending Interrupt Register)
* to get the interrupt ID of the highest priority pending interrupt.
*
* Unlike reading GICC_IAR (via arm_gic_get_active_irq()), reading GICC_HPPIR
* does NOT acknowledge the interrupt. This means:
* - The interrupt state remains unchanged (still pending)
*
* @param index GIC controller index
*
* @return The 32-bit value read from the GICC_HPPIR register.
* The caller can extract specific fields (hardware interrupt ID without offset added).
*/
rt_uint32_t arm_gic_get_high_pending_irq(rt_uint32_t index)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
@@ -331,6 +548,14 @@ rt_uint32_t arm_gic_get_high_pending_irq(rt_uint32_t index)
return GIC_CPU_HIGHPRI(_gic_table[index].cpu_hw_base);
}
/**
* @brief Get the CPU Interface Identification Register (GICC_IIDR) value
*
* @param index GIC controller index
*
* @return The 32-bit value read from the GICC_IIDR register.
* The caller can extract specific fields (implementer, product ID, revision, architecture version.)
*/
rt_uint32_t arm_gic_get_interface_id(rt_uint32_t index)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
@@ -338,6 +563,19 @@ rt_uint32_t arm_gic_get_interface_id(rt_uint32_t index)
return GIC_CPU_IIDR(_gic_table[index].cpu_hw_base);
}
/**
* @brief Set the interrupt group for the specified interrupt
*
* @note This function configures the interrupt group in the GICD_IGROUPRn register.
* The interrupt group determines the security classification of the interrupt
* when the GIC implements Security Extensions:
* - Group 0 (group = 0): Secure interrupts, used for secure world
* - Group 1 (group = 1): Non-secure interrupts, used for non-secure world
*
* @param index GIC controller index
* @param irq The actual interrupt number (with offset)
* @param group Interrupt group: 0 for Group 0 (secure), 1 for Group 1 (non-secure)
*/
void arm_gic_set_group(rt_uint32_t index, int irq, rt_uint32_t group)
{
rt_uint32_t igroupr;
@@ -357,6 +595,19 @@ void arm_gic_set_group(rt_uint32_t index, int irq, rt_uint32_t group)
GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, irq) = igroupr;
}
/**
* @brief Get the interrupt group for the specified interrupt
*
* @note This function reads the interrupt group from the GICD_IGROUPRn register.
* The return value indicates which security group the interrupt belongs to:
* - 0: Group 0 (Secure interrupt)
* - 1: Group 1 (Non-secure interrupt)
*
* @param index GIC controller index
* @param irq The actual interrupt number (with offset)
*
* @return The interrupt group: 0 for Group 0 (secure), 1 for Group 1 (non-secure)
*/
rt_uint32_t arm_gic_get_group(rt_uint32_t index, int irq)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
@@ -367,6 +618,19 @@ rt_uint32_t arm_gic_get_group(rt_uint32_t index, int irq)
return (GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, irq) >> (irq % 32U)) & 0x1UL;
}
/**
* @brief Initialize the GIC Distributor (GICD)
*
* @note: The exact bit definitions and behavior may vary depending on
* the GIC implementation (GICv1/GICv2) and security context.
*
*
* @param index GIC controller index
* @param dist_base Base address of the GIC Distributor (GICD)
* @param irq_start The first interrupt index offset in the vector table
*
* @return 0
*/
int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start)
{
unsigned int gic_type, i;
@@ -427,6 +691,17 @@ int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start)
return 0;
}
/**
* @brief Initialize the GIC CPU Interface (GICC)
*
* @note: The exact bit definitions and behavior may vary depending on
* the GIC implementation (GICv1/GICv2) and security context..
*
* @param index GIC controller index
* @param cpu_base Base address of the GIC CPU Interface (GICC)
*
* @return 0
*/
int arm_gic_cpu_init(rt_uint32_t index, rt_uint32_t cpu_base)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
@@ -445,6 +720,11 @@ int arm_gic_cpu_init(rt_uint32_t index, rt_uint32_t cpu_base)
return 0;
}
/**
* @brief Print the GIC infomations(version, base addr, max irq nums, security extension)
*
* @param index GIC controller index
*/
void arm_gic_dump_type(rt_uint32_t index)
{
unsigned int gic_type;
@@ -458,6 +738,11 @@ void arm_gic_dump_type(rt_uint32_t index)
gic_type);
}
/**
* @brief Print the GIC status(highest priority pending interrupt, enable status, pending status , active status)
*
* @param index
*/
void arm_gic_dump(rt_uint32_t index)
{
unsigned int i, k;