arch: arm: aarch32: Refactor interrupt interface
The current AArch32 (Cortex-R and to-be-added Cortex-A) interrupt system relies on the multi-level interrupt mechanism and the `irq_nextlevel` public interface to invoke the Generic Interrupt Controller (GIC) driver functions. Since the GIC driver has been refactored to provide a direct interface, in order to resolve various implementation issues described in the GIC driver refactoring commit, the architecture interrupt control functions are updated to directly invoke the GIC driver functions. This commit also adds support for the Cortex-R cores (Cortex-R4 and R5) that allow interfacing to a custom external interrupt controller (i.e. non-GIC) by introducing the `ARM_CUSTOM_INTERRUPT_CONTROLLER` configuration that maps the architecture interrupt control functions to the SoC layer interrupt control functions. Signed-off-by: Stephanos Ioannidis <root@stephanos.io>
This commit is contained in:
parent
5ab698bd56
commit
2c5ca5505c
6 changed files with 134 additions and 39 deletions
|
@ -16,4 +16,24 @@ config ARM64
|
|||
bool
|
||||
select 64BIT
|
||||
|
||||
config ARM_CUSTOM_INTERRUPT_CONTROLLER
|
||||
bool
|
||||
depends on !CPU_CORTEX_M
|
||||
help
|
||||
This option indicates that the ARM CPU is connected to a custom (i.e.
|
||||
non-GIC) interrupt controller.
|
||||
|
||||
A number of Cortex-A and Cortex-R cores (Cortex-A5, Cortex-R4/5, ...)
|
||||
allow interfacing to a custom external interrupt controller and this
|
||||
option must be selected when such cores are connected to an interrupt
|
||||
controller that is not the ARM Generic Interrupt Controller (GIC).
|
||||
|
||||
When this option is selected, the architecture interrupt control
|
||||
functions are mapped to the SoC interrupt control interface, which is
|
||||
implemented at the SoC level.
|
||||
|
||||
N.B. This option is only applicable to the Cortex-A and Cortex-R
|
||||
family cores. The Cortex-M family cores are always equipped with
|
||||
the ARM Nested Vectored Interrupt Controller (NVIC).
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -6,6 +6,7 @@ zephyr_library_sources(
|
|||
vector_table.S
|
||||
reset.S
|
||||
fault.c
|
||||
irq_init.c
|
||||
reboot.c
|
||||
stacks.c
|
||||
)
|
||||
|
|
33
arch/arm/core/aarch32/cortex_r/irq_init.c
Normal file
33
arch/arm/core/aarch32/cortex_r/irq_init.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Stephanos Ioannidis <root@stephanos.io>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief ARM Cortex-R interrupt initialization
|
||||
*/
|
||||
|
||||
#include <arch/cpu.h>
|
||||
#include <drivers/interrupt_controller/gic.h>
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Initialize interrupts
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
void z_arm_interrupt_init(void)
|
||||
{
|
||||
/*
|
||||
* Initialise interrupt controller.
|
||||
*/
|
||||
#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER)
|
||||
/* Initialise the Generic Interrupt Controller (GIC) driver */
|
||||
arm_gic_init();
|
||||
#else
|
||||
/* Invoke SoC-specific interrupt controller initialisation */
|
||||
z_soc_irq_init();
|
||||
#endif
|
||||
}
|
|
@ -18,9 +18,8 @@
|
|||
#include <arch/cpu.h>
|
||||
#if defined(CONFIG_CPU_CORTEX_M)
|
||||
#include <arch/arm/aarch32/cortex_m/cmsis.h>
|
||||
#elif defined(CONFIG_CPU_CORTEX_R)
|
||||
#include <device.h>
|
||||
#include <irq_nextlevel.h>
|
||||
#elif defined(CONFIG_CPU_CORTEX_A) || defined(CONFIG_CPU_CORTEX_R)
|
||||
#include <drivers/interrupt_controller/gic.h>
|
||||
#endif
|
||||
#include <sys/__assert.h>
|
||||
#include <toolchain.h>
|
||||
|
@ -96,26 +95,32 @@ void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, u32_t flags)
|
|||
NVIC_SetPriority((IRQn_Type)irq, prio);
|
||||
}
|
||||
|
||||
#elif defined(CONFIG_CPU_CORTEX_R)
|
||||
#elif defined(CONFIG_CPU_CORTEX_A) || defined(CONFIG_CPU_CORTEX_R)
|
||||
/*
|
||||
* For Cortex-A and Cortex-R cores, the default interrupt controller is the ARM
|
||||
* Generic Interrupt Controller (GIC) and therefore the architecture interrupt
|
||||
* control functions are mapped to the GIC driver interface.
|
||||
*
|
||||
* When a custom interrupt controller is used (i.e.
|
||||
* CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER is enabled), the architecture
|
||||
* interrupt control functions are mapped to the SoC layer in
|
||||
* `include/arch/arm/aarch32/irq.h`.
|
||||
*/
|
||||
|
||||
#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER)
|
||||
void arch_irq_enable(unsigned int irq)
|
||||
{
|
||||
struct device *dev = _sw_isr_table[0].arg;
|
||||
|
||||
irq_enable_next_level(dev, (irq >> 8) - 1);
|
||||
arm_gic_irq_enable(irq);
|
||||
}
|
||||
|
||||
void arch_irq_disable(unsigned int irq)
|
||||
{
|
||||
struct device *dev = _sw_isr_table[0].arg;
|
||||
|
||||
irq_disable_next_level(dev, (irq >> 8) - 1);
|
||||
arm_gic_irq_disable(irq);
|
||||
}
|
||||
|
||||
int arch_irq_is_enabled(unsigned int irq)
|
||||
{
|
||||
struct device *dev = _sw_isr_table[0].arg;
|
||||
|
||||
return irq_is_enabled_next_level(dev);
|
||||
return arm_gic_irq_is_enabled(irq);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -132,15 +137,11 @@ int arch_irq_is_enabled(unsigned int irq)
|
|||
*/
|
||||
void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, u32_t flags)
|
||||
{
|
||||
struct device *dev = _sw_isr_table[0].arg;
|
||||
|
||||
if (irq == 0)
|
||||
return;
|
||||
|
||||
irq_set_priority_next_level(dev, (irq >> 8) - 1, prio, flags);
|
||||
arm_gic_irq_set_priority(irq, prio, flags);
|
||||
}
|
||||
#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */
|
||||
|
||||
#endif
|
||||
#endif /* CONFIG_CPU_CORTEX_M */
|
||||
|
||||
void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf);
|
||||
|
||||
|
|
|
@ -126,7 +126,6 @@ _idle_state_cleared:
|
|||
|
||||
#if defined(CONFIG_CPU_CORTEX_M)
|
||||
mrs r0, IPSR /* get exception number */
|
||||
#endif
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
ldr r1, =16
|
||||
subs r0, r1 /* get IRQ number */
|
||||
|
@ -134,15 +133,19 @@ _idle_state_cleared:
|
|||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
sub r0, r0, #16 /* get IRQ number */
|
||||
lsl r0, r0, #3 /* table is 8-byte wide */
|
||||
#elif defined(CONFIG_ARMV7_R)
|
||||
/*
|
||||
* Cortex-R only has one IRQ line so the main handler will be at
|
||||
* offset 0 of the table.
|
||||
*/
|
||||
mov r0, #0
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
||||
#elif defined(CONFIG_CPU_CORTEX_R)
|
||||
/* Get active IRQ number from the interrupt controller */
|
||||
#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER)
|
||||
bl arm_gic_get_active
|
||||
#else
|
||||
bl z_soc_irq_get_active
|
||||
#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */
|
||||
push {r0, r1}
|
||||
lsl r0, r0, #3 /* table is 8-byte wide */
|
||||
#else
|
||||
#error Unknown ARM architecture
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
||||
#endif /* CONFIG_CPU_CORTEX_M */
|
||||
ldr r1, =_sw_isr_table
|
||||
add r1, r1, r0 /* table entry: ISRs must have their MSB set to stay
|
||||
* in thumb mode */
|
||||
|
@ -162,6 +165,16 @@ _idle_state_cleared:
|
|||
#endif /* CONFIG_EXECUTION_BENCHMARKING */
|
||||
blx r3 /* call ISR */
|
||||
|
||||
#if defined(CONFIG_CPU_CORTEX_R)
|
||||
/* Signal end-of-interrupt */
|
||||
pop {r0, r1}
|
||||
#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER)
|
||||
bl arm_gic_eoi
|
||||
#else
|
||||
bl z_soc_irq_eoi
|
||||
#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */
|
||||
#endif /* CONFIG_CPU_CORTEX_R */
|
||||
|
||||
#ifdef CONFIG_TRACING_ISR
|
||||
bl sys_trace_isr_exit
|
||||
#endif
|
||||
|
|
|
@ -29,20 +29,52 @@ GTEXT(z_arm_int_exit);
|
|||
GTEXT(arch_irq_enable)
|
||||
GTEXT(arch_irq_disable)
|
||||
GTEXT(arch_irq_is_enabled)
|
||||
#if defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER)
|
||||
GTEXT(z_soc_irq_get_active)
|
||||
GTEXT(z_soc_irq_eoi)
|
||||
#endif /* CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */
|
||||
#else
|
||||
|
||||
#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER)
|
||||
|
||||
extern void arch_irq_enable(unsigned int irq);
|
||||
extern void arch_irq_disable(unsigned int irq);
|
||||
extern int arch_irq_is_enabled(unsigned int irq);
|
||||
|
||||
/* internal routine documented in C file, needed by IRQ_CONNECT() macro */
|
||||
extern void z_arm_irq_priority_set(unsigned int irq, unsigned int prio,
|
||||
u32_t flags);
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* When a custom interrupt controller is specified, map the architecture
|
||||
* interrupt control functions to the SoC layer interrupt control functions.
|
||||
*/
|
||||
|
||||
void z_soc_irq_init(void);
|
||||
void z_soc_irq_enable(unsigned int irq);
|
||||
void z_soc_irq_disable(unsigned int irq);
|
||||
int z_soc_irq_is_enabled(unsigned int irq);
|
||||
|
||||
void z_soc_irq_priority_set(
|
||||
unsigned int irq, unsigned int prio, unsigned int flags);
|
||||
|
||||
unsigned int z_soc_irq_get_active(void);
|
||||
void z_soc_irq_eoi(unsigned int irq);
|
||||
|
||||
#define arch_irq_enable(irq) z_soc_irq_enable(irq)
|
||||
#define arch_irq_disable(irq) z_soc_irq_disable(irq)
|
||||
#define arch_irq_is_enabled(irq) z_soc_irq_is_enabled(irq)
|
||||
|
||||
#define z_arm_irq_priority_set(irq, prio, flags) \
|
||||
z_soc_irq_priority_set(irq, prio, flags)
|
||||
|
||||
#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */
|
||||
|
||||
extern void z_arm_int_exit(void);
|
||||
|
||||
#if defined(CONFIG_ARMV7_R)
|
||||
static ALWAYS_INLINE void z_arm_interrupt_init(void)
|
||||
{
|
||||
}
|
||||
#else
|
||||
extern void z_arm_interrupt_init(void);
|
||||
#endif
|
||||
|
||||
/* macros convert value of it's argument to a string */
|
||||
#define DO_TOSTR(s) #s
|
||||
|
@ -52,11 +84,6 @@ extern void z_arm_interrupt_init(void);
|
|||
#define DO_CONCAT(x, y) x ## y
|
||||
#define CONCAT(x, y) DO_CONCAT(x, y)
|
||||
|
||||
/* internal routine documented in C file, needed by IRQ_CONNECT() macro */
|
||||
extern void z_arm_irq_priority_set(unsigned int irq, unsigned int prio,
|
||||
u32_t flags);
|
||||
|
||||
|
||||
/* Flags for use with IRQ_CONNECT() */
|
||||
#ifdef CONFIG_ZERO_LATENCY_IRQS
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue