arc: enable gen_isr_tables mechanism
Change-Id: I5897e110f554377796bfe38dd5c0f8652c29e5be Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
parent
3944d8313e
commit
35fcb2736c
10 changed files with 56 additions and 212 deletions
|
@ -144,6 +144,12 @@ config XIP
|
||||||
default n if NSIM
|
default n if NSIM
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config GEN_ISR_TABLES
|
||||||
|
default y
|
||||||
|
|
||||||
|
config GEN_IRQ_START_VECTOR
|
||||||
|
default 16
|
||||||
|
|
||||||
config HARVARD
|
config HARVARD
|
||||||
prompt "Harvard Architecture"
|
prompt "Harvard Architecture"
|
||||||
bool
|
bool
|
||||||
|
@ -208,46 +214,6 @@ config FLASH_BASE_ADDRESS
|
||||||
normally set by the board's defconfig file and the user should generally
|
normally set by the board's defconfig file and the user should generally
|
||||||
avoid modifying it via the menu configuration.
|
avoid modifying it via the menu configuration.
|
||||||
|
|
||||||
config SW_ISR_TABLE
|
|
||||||
bool
|
|
||||||
prompt "Enable software interrupt handler table"
|
|
||||||
default y
|
|
||||||
help
|
|
||||||
Enable an interrupt handler table implemented in software. This
|
|
||||||
table, unlike ISRs connected directly in the vector table, allow
|
|
||||||
a parameter to be passed to the interrupt handlers. Also, invoking
|
|
||||||
the exeception/interrupt exit stub is automatically done.
|
|
||||||
|
|
||||||
config IRQ_VECTOR_TABLE_CUSTOM
|
|
||||||
bool
|
|
||||||
prompt "Projects provide a custom static IRQ part of vector table"
|
|
||||||
depends on !SW_ISR_TABLE
|
|
||||||
default n
|
|
||||||
help
|
|
||||||
Projects, not the BSP, provide the IRQ part of the vector table.
|
|
||||||
|
|
||||||
This is the table of interrupt handlers with the best potential
|
|
||||||
performance, but is the less flexible.
|
|
||||||
|
|
||||||
The ISRs are installed directly in the vector table, thus are
|
|
||||||
directly called by the CPU when an interrupt is taken. This adds
|
|
||||||
the least overhead when handling an interrupt.
|
|
||||||
|
|
||||||
Downsides:
|
|
||||||
|
|
||||||
- ISRs cannot have a parameter
|
|
||||||
- ISRs cannot be connected at runtime
|
|
||||||
- ISRs must notify the kernel manually by invoking _ExcExit() when
|
|
||||||
then are about to return.
|
|
||||||
|
|
||||||
config IRQ_VECTOR_TABLE_BSP
|
|
||||||
bool
|
|
||||||
# omit prompt to signify a "hidden" option
|
|
||||||
depends on SW_ISR_TABLE || !IRQ_VECTOR_TABLE_CUSTOM
|
|
||||||
default y
|
|
||||||
help
|
|
||||||
Not user-selectable, helps build system logic.
|
|
||||||
|
|
||||||
config CACHE_LINE_SIZE_DETECT
|
config CACHE_LINE_SIZE_DETECT
|
||||||
bool
|
bool
|
||||||
prompt "Detect d-cache line size at runtime"
|
prompt "Detect d-cache line size at runtime"
|
||||||
|
|
|
@ -16,5 +16,3 @@ obj-$(CONFIG_IRQ_OFFLOAD) += irq_offload.o
|
||||||
# Some ARC cores like the EM4 lack the atomic LLOCK/SCOND and
|
# Some ARC cores like the EM4 lack the atomic LLOCK/SCOND and
|
||||||
# can't use these.
|
# can't use these.
|
||||||
obj-$(CONFIG_ATOMIC_OPERATIONS_CUSTOM) += atomic.o
|
obj-$(CONFIG_ATOMIC_OPERATIONS_CUSTOM) += atomic.o
|
||||||
obj-$(CONFIG_IRQ_VECTOR_TABLE_BSP) += irq_vector_table.o
|
|
||||||
obj-$(CONFIG_SW_ISR_TABLE) += sw_isr_table.o
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ SECTION_FUNC(TEXT, _firq_enter)
|
||||||
* If CONFIG_RGF_NUM_BANKS>1, firq uses a 2nd register bank so GPRs do
|
* If CONFIG_RGF_NUM_BANKS>1, firq uses a 2nd register bank so GPRs do
|
||||||
* not need to be saved.
|
* not need to be saved.
|
||||||
* If CONFIG_RGF_NUM_BANKS==1, firq must use the stack to save registers.
|
* If CONFIG_RGF_NUM_BANKS==1, firq must use the stack to save registers.
|
||||||
* This has already been done by _isr_enter.
|
* This has already been done by _isr_wrapper.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2014 Wind River Systems, Inc.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief IRQ part of vector table for Quark SE Sensor Subsystem
|
|
||||||
*
|
|
||||||
* This file contains the IRQ part of the vector table. It is meant to be used
|
|
||||||
* for one of two cases:
|
|
||||||
*
|
|
||||||
* a) When software-managed ISRs (SW_ISR_TABLE) is enabled, and in that case it
|
|
||||||
* binds _IsrWrapper() to all the IRQ entries in the vector table.
|
|
||||||
*
|
|
||||||
* b) When the BSP is written so that device ISRs are installed directly in the
|
|
||||||
* vector table, they are enumerated here.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <toolchain.h>
|
|
||||||
#include <sections.h>
|
|
||||||
|
|
||||||
extern void _isr_enter(void);
|
|
||||||
typedef void (*vth)(void); /* Vector Table Handler */
|
|
||||||
|
|
||||||
#if defined(CONFIG_SW_ISR_TABLE)
|
|
||||||
|
|
||||||
vth __irq_vector_table _irq_vector_table[CONFIG_NUM_IRQS - 16] = {
|
|
||||||
[0 ...(CONFIG_NUM_IRQS - 17)] = _isr_enter
|
|
||||||
};
|
|
||||||
|
|
||||||
#elif !defined(CONFIG_IRQ_VECTOR_TABLE_CUSTOM)
|
|
||||||
|
|
||||||
extern void _SpuriousIRQ(void);
|
|
||||||
|
|
||||||
/* placeholders: fill with real ISRs */
|
|
||||||
|
|
||||||
vth __irq_vector_table _irq_vector_table[CONFIG_NUM_IRQS - 16] = {
|
|
||||||
[0 ...(CONFIG_NUM_IRQS - 17)] = _SpuriousIRQ
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* CONFIG_SW_ISR_TABLE */
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include <kernel_structs.h>
|
#include <kernel_structs.h>
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
|
|
||||||
GTEXT(_isr_enter)
|
GTEXT(_isr_wrapper)
|
||||||
GTEXT(_isr_demux)
|
GTEXT(_isr_demux)
|
||||||
|
|
||||||
#if CONFIG_RGF_NUM_BANKS == 1
|
#if CONFIG_RGF_NUM_BANKS == 1
|
||||||
|
@ -41,9 +41,9 @@ _rirq_enter/_firq_enter: they are jump points.
|
||||||
|
|
||||||
The flow is the following:
|
The flow is the following:
|
||||||
|
|
||||||
ISR -> _isr_enter -- + -> _rirq_enter -> _isr_demux -> ISR -> _rirq_exit
|
ISR -> _isr_wrapper -- + -> _rirq_enter -> _isr_demux -> ISR -> _rirq_exit
|
||||||
|
|
|
|
||||||
+ -> _firq_enter -> _isr_demux -> ISR -> _firq_exit
|
+ -> _firq_enter -> _isr_demux -> ISR -> _firq_exit
|
||||||
|
|
||||||
Context switch explanation:
|
Context switch explanation:
|
||||||
|
|
||||||
|
@ -216,7 +216,7 @@ From RIRQ:
|
||||||
interrupt.
|
interrupt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SECTION_FUNC(TEXT, _isr_enter)
|
SECTION_FUNC(TEXT, _isr_wrapper)
|
||||||
#if CONFIG_RGF_NUM_BANKS == 1
|
#if CONFIG_RGF_NUM_BANKS == 1
|
||||||
st r0,[saved_r0]
|
st r0,[saved_r0]
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
/* sw_isr_table.S - ISR table for static ISR declarations for ARC */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2015 Intel Corporation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <toolchain.h>
|
|
||||||
#include <sections.h>
|
|
||||||
#include <arch/cpu.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* enable preprocessor features, such
|
|
||||||
* as %expr - evaluate the expression and use it as a string
|
|
||||||
*/
|
|
||||||
.altmacro
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Define an ISR table entry
|
|
||||||
* Define symbol as weak and give the section .gnu.linkonce
|
|
||||||
* prefix. This allows linker overload the symbol and the
|
|
||||||
* whole section by the one defined by a device driver
|
|
||||||
*/
|
|
||||||
.macro _isr_table_entry_declare index
|
|
||||||
WDATA(_isr_irq\index)
|
|
||||||
.section .gnu.linkonce.isr_irq\index
|
|
||||||
_isr_irq\index: .word 0xABAD1DEA, _irq_spurious
|
|
||||||
.endm
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Declare the ISR table
|
|
||||||
*/
|
|
||||||
.macro _isr_table_declare from, to
|
|
||||||
counter = \from
|
|
||||||
.rept (\to - \from)
|
|
||||||
_isr_table_entry_declare %counter
|
|
||||||
counter = counter + 1
|
|
||||||
.endr
|
|
||||||
.endm
|
|
||||||
|
|
||||||
GTEXT(_irq_spurious)
|
|
||||||
GDATA(_sw_isr_table)
|
|
||||||
|
|
||||||
.section .isr_irq16
|
|
||||||
.align
|
|
||||||
_sw_isr_table:
|
|
||||||
|
|
||||||
/*In ARC architecture, IRQ 0-15 are reserved for the system and are not
|
|
||||||
assignable by the user, for that reason the isr table linker section
|
|
||||||
start at IRQ 16*/
|
|
||||||
_isr_table_declare 16 CONFIG_NUM_IRQS
|
|
|
@ -134,7 +134,7 @@ parameter.
|
||||||
executing. A common interrupt handler demuxer is installed for all entries of
|
executing. A common interrupt handler demuxer is installed for all entries of
|
||||||
the real interrupt vector table, which then fetches the device's ISR and
|
the real interrupt vector table, which then fetches the device's ISR and
|
||||||
parameter from the separate table. This approach is commonly used in the ARC
|
parameter from the separate table. This approach is commonly used in the ARC
|
||||||
and ARM architectures via the :option:`CONFIG_SW_ISR_TABLE` implementation.
|
and ARM architectures via the :option:`CONFIG_GEN_ISR_TABLES` implementation.
|
||||||
You can find examples of the stubs by looking at :code:`_interrupt_enter()` in
|
You can find examples of the stubs by looking at :code:`_interrupt_enter()` in
|
||||||
x86, :code:`_IntExit()` in ARM, :code:`_isr_wrapper()` in ARM, or the full
|
x86, :code:`_IntExit()` in ARM, :code:`_isr_wrapper()` in ARM, or the full
|
||||||
implementation description for ARC in :file:`arch/arc/core/isr_wrapper.S`.
|
implementation description for ARC in :file:`arch/arc/core/isr_wrapper.S`.
|
||||||
|
|
|
@ -43,53 +43,4 @@ extern "C" {
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _ASMLANGUAGE
|
|
||||||
#include <irq.h>
|
|
||||||
|
|
||||||
/* internal routine documented in C file, needed by IRQ_CONNECT() macro */
|
|
||||||
extern void _irq_priority_set(unsigned int irq, unsigned int prio,
|
|
||||||
uint32_t flags);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure a static interrupt.
|
|
||||||
*
|
|
||||||
* All arguments must be computable by the compiler at build time.
|
|
||||||
*
|
|
||||||
* Internally this function does a few things:
|
|
||||||
*
|
|
||||||
* 1. The enum statement has no effect but forces the compiler to only
|
|
||||||
* accept constant values for the irq_p parameter, very important as the
|
|
||||||
* numerical IRQ line is used to create a named section.
|
|
||||||
*
|
|
||||||
* 2. An instance of struct _isr_table_entry is created containing the ISR and
|
|
||||||
* its parameter. If you look at how _sw_isr_table is created, each entry in
|
|
||||||
* the array is in its own section named by the IRQ line number. What we are
|
|
||||||
* doing here is to override one of the default entries (which points to the
|
|
||||||
* spurious IRQ handler) with what was supplied here.
|
|
||||||
*
|
|
||||||
* 3. The priority level for the interrupt is configured by a call to
|
|
||||||
* _irq_priority_set()
|
|
||||||
*
|
|
||||||
* @param irq_p IRQ line number
|
|
||||||
* @param priority_p Interrupt priority, in range 0-13
|
|
||||||
* @param isr_p Interrupt service routine
|
|
||||||
* @param isr_param_p ISR parameter
|
|
||||||
* @param flags_p IRQ options (ignored for now)
|
|
||||||
*
|
|
||||||
* @return The vector assigned to this interrupt
|
|
||||||
*/
|
|
||||||
#define _ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \
|
|
||||||
({ \
|
|
||||||
enum { IRQ = irq_p }; \
|
|
||||||
static struct _isr_table_entry _CONCAT(_isr_irq, irq_p) \
|
|
||||||
__attribute__ ((used)) \
|
|
||||||
__attribute__ ((section(STRINGIFY(_CONCAT(.gnu.linkonce.isr_irq, irq_p))))) = \
|
|
||||||
{isr_param_p, isr_p}; \
|
|
||||||
_irq_priority_set(irq_p, priority_p, flags_p); \
|
|
||||||
irq_p; \
|
|
||||||
})
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _ARC_ARCH__H_ */
|
#endif /* _ARC_ARCH__H_ */
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <toolchain/common.h>
|
#include <toolchain/common.h>
|
||||||
#include <irq.h>
|
#include <irq.h>
|
||||||
#include <misc/util.h>
|
#include <misc/util.h>
|
||||||
|
#include <sw_isr_table.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -33,6 +34,40 @@ extern void _arch_irq_enable(unsigned int irq);
|
||||||
extern void _arch_irq_disable(unsigned int irq);
|
extern void _arch_irq_disable(unsigned int irq);
|
||||||
|
|
||||||
extern void _irq_exit(void);
|
extern void _irq_exit(void);
|
||||||
|
extern void _irq_priority_set(unsigned int irq, unsigned int prio,
|
||||||
|
uint32_t flags);
|
||||||
|
extern void _isr_wrapper(void);
|
||||||
|
extern void _irq_spurious(void *unused);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure a static interrupt.
|
||||||
|
*
|
||||||
|
* All arguments must be computable by the compiler at build time.
|
||||||
|
*
|
||||||
|
* _ISR_DECLARE will populate the .intList section with the interrupt's
|
||||||
|
* parameters, which will then be used by gen_irq_tables.py to create
|
||||||
|
* the vector table and the software ISR table. This is all done at
|
||||||
|
* build-time.
|
||||||
|
*
|
||||||
|
* We additionally set the priority in the interrupt controller at
|
||||||
|
* runtime.
|
||||||
|
*
|
||||||
|
* @param irq_p IRQ line number
|
||||||
|
* @param priority_p Interrupt priority
|
||||||
|
* @param isr_p Interrupt service routine
|
||||||
|
* @param isr_param_p ISR parameter
|
||||||
|
* @param flags_p IRQ options
|
||||||
|
*
|
||||||
|
* @return The vector assigned to this interrupt
|
||||||
|
*/
|
||||||
|
#define _ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \
|
||||||
|
({ \
|
||||||
|
_ISR_DECLARE(irq_p, 0, isr_p, isr_param_p); \
|
||||||
|
_irq_priority_set(irq_p, priority_p, flags_p); \
|
||||||
|
irq_p; \
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
|
@ -57,6 +57,8 @@ MEMORY {
|
||||||
#ifdef DCCM_START
|
#ifdef DCCM_START
|
||||||
DCCM (rw) : ORIGIN = DCCM_START, LENGTH = DCCM_SIZE*1k
|
DCCM (rw) : ORIGIN = DCCM_START, LENGTH = DCCM_SIZE*1k
|
||||||
#endif
|
#endif
|
||||||
|
/* Used by and documented in include/linker/intlist.ld */
|
||||||
|
IDT_LIST (wx) : ORIGIN = 0xFFFFF7FF, LENGTH = 2K
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
|
@ -72,25 +74,9 @@ SECTIONS {
|
||||||
KEEP(*(".exc_vector_table.*"))
|
KEEP(*(".exc_vector_table.*"))
|
||||||
KEEP(*(IRQ_VECTOR_TABLE))
|
KEEP(*(IRQ_VECTOR_TABLE))
|
||||||
|
|
||||||
KEEP(*(.isr_irq*))
|
#ifdef CONFIG_GEN_SW_ISR_TABLE
|
||||||
|
KEEP(*(SW_ISR_TABLE))
|
||||||
/*
|
#endif
|
||||||
* The following sections maps the location of the different
|
|
||||||
* rows for the _sw_isr_table. Each row maps to an IRQ entry
|
|
||||||
* (handler, argument).
|
|
||||||
*
|
|
||||||
* In ARC architecture, IRQ 0-15 are reserved for the system
|
|
||||||
* and are not * assignable by the user, for that reason the
|
|
||||||
* linker sections start on IRQ 16
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* sections for IRQ16-19 */
|
|
||||||
KEEP(*(SORT(.gnu.linkonce.isr_irq[1][6-9])))
|
|
||||||
/* sections for IRQ20-99 */
|
|
||||||
KEEP(*(SORT(.gnu.linkonce.isr_irq[2-9][0-9])))
|
|
||||||
/* sections for IRQ100-999 */
|
|
||||||
KEEP(*(SORT(.gnu.linkonce.isr_irq[1-9][0-9][0-9])))
|
|
||||||
|
|
||||||
*(.text)
|
*(.text)
|
||||||
*(".text.*")
|
*(".text.*")
|
||||||
*(.gnu.linkonce.t.*)
|
*(.gnu.linkonce.t.*)
|
||||||
|
@ -189,4 +175,7 @@ SECTIONS {
|
||||||
#include <custom-sections.ld>
|
#include <custom-sections.ld>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_GEN_ISR_TABLES
|
||||||
|
#include <linker/intlist.ld>
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue