nios2: add static interrupt handling code
Supports Internal Interrupt Controller only for now; EIC supoort tracked in ZEP-258. Change-Id: I2d9c5180e61c06b377fce4bda8a59042b68d58f2 Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
parent
e2ff2fdd91
commit
738dec483e
8 changed files with 159 additions and 6 deletions
|
@ -4,6 +4,6 @@ ccflags-y += -I$(srctree)/kernel/microkernel/include
|
||||||
|
|
||||||
obj-y += reset.o irq_manage.o fatal.o swap.o thread.o \
|
obj-y += reset.o irq_manage.o fatal.o swap.o thread.o \
|
||||||
cpu_idle.o irq_offload.o prep_c.o crt0.o \
|
cpu_idle.o irq_offload.o prep_c.o crt0.o \
|
||||||
exception.o
|
exception.o sw_isr_table.o
|
||||||
|
|
||||||
obj-$(CONFIG_IRQ_OFFLOAD) += irq_offload.o
|
obj-$(CONFIG_IRQ_OFFLOAD) += irq_offload.o
|
||||||
|
|
|
@ -111,12 +111,10 @@ SECTION_FUNC(exception.entry, _exception)
|
||||||
|
|
||||||
BRANCH_LABEL(on_irq_stack)
|
BRANCH_LABEL(on_irq_stack)
|
||||||
|
|
||||||
#if 0 /* TODO enable interrupt handling code */
|
|
||||||
/* Enter C interrupt handling code. Value of ipending will be the
|
/* Enter C interrupt handling code. Value of ipending will be the
|
||||||
* function parameter since we put it in r4
|
* function parameter since we put it in r4
|
||||||
*/
|
*/
|
||||||
call _enter_irq
|
call _enter_irq
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Interrupt handler finished and the interrupt should be serviced
|
/* Interrupt handler finished and the interrupt should be serviced
|
||||||
* now, the appropriate bits in ipending should be cleared */
|
* now, the appropriate bits in ipending should be cleared */
|
||||||
|
|
|
@ -14,9 +14,27 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Nios II C-domain interrupt management code for use with Internal
|
||||||
|
* Interrupt Controller (IIC)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <nanokernel.h>
|
#include <nanokernel.h>
|
||||||
|
#include <nano_private.h>
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
#include <irq.h>
|
#include <irq.h>
|
||||||
|
#include <misc/printk.h>
|
||||||
|
#include <sw_isr_table.h>
|
||||||
|
|
||||||
|
void _irq_spurious(void *unused)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(unused);
|
||||||
|
printk("Spurious interrupt detected! ipending: %x\n",
|
||||||
|
_nios2_creg_read(NIOS2_CR_IPENDING));
|
||||||
|
_NanoFatalErrorHandler(_NANO_ERR_SPURIOUS_INT, &_default_esf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void _arch_irq_enable(unsigned int irq)
|
void _arch_irq_enable(unsigned int irq)
|
||||||
|
@ -34,6 +52,7 @@ void _arch_irq_enable(unsigned int irq)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void _arch_irq_disable(unsigned int irq)
|
void _arch_irq_disable(unsigned int irq)
|
||||||
{
|
{
|
||||||
uint32_t ienable;
|
uint32_t ienable;
|
||||||
|
@ -65,3 +84,25 @@ int _arch_irq_connect_dynamic(unsigned int irq,
|
||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interrupt demux function
|
||||||
|
*
|
||||||
|
* Given a bitfield of pending interrupts, execute the appropriate handler
|
||||||
|
*
|
||||||
|
* @param ipending Bitfield of interrupts
|
||||||
|
*/
|
||||||
|
void _enter_irq(uint32_t ipending)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
|
||||||
|
while (ipending) {
|
||||||
|
_IsrTableEntry_t *ite;
|
||||||
|
|
||||||
|
index = find_lsb_set(ipending) - 1;
|
||||||
|
ipending &= ~(1 << index);
|
||||||
|
|
||||||
|
ite = &_sw_isr_table[index];
|
||||||
|
ite->isr(ite->arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
61
arch/nios2/core/sw_isr_table.S
Normal file
61
arch/nios2/core/sw_isr_table.S
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/* sw_isr_table.S - ISR table for static ISR declarations for ARC */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015 Intel Corporation
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* http://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _ASMLANGUAGE
|
||||||
|
|
||||||
|
#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_irq0
|
||||||
|
.align
|
||||||
|
_sw_isr_table:
|
||||||
|
|
||||||
|
_isr_table_declare 0 NIOS2_NIRQ
|
|
@ -43,9 +43,46 @@ extern "C" {
|
||||||
#ifndef _ASMLANGUAGE
|
#ifndef _ASMLANGUAGE
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <irq.h>
|
#include <irq.h>
|
||||||
|
#include <sw_isr_table.h>
|
||||||
|
|
||||||
/* STUB. Eventually port ARC/ARM interrupt stuff */
|
/**
|
||||||
#define _ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p)
|
* Configure a static interrupt.
|
||||||
|
*
|
||||||
|
* All arguments must be computable by the compiler at build time; if this
|
||||||
|
* can't be done use irq_connect_dynamic() instead.
|
||||||
|
*
|
||||||
|
* 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 _IsrTableEntry 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.
|
||||||
|
*
|
||||||
|
* There is no notion of priority with the Nios II internal interrupt
|
||||||
|
* controller and no flags are currently supported.
|
||||||
|
*
|
||||||
|
* @param irq_p IRQ line number
|
||||||
|
* @param priority_p Interrupt priority (ignored)
|
||||||
|
* @param isr_p Interrupt service routine
|
||||||
|
* @param isr_param_p ISR parameter
|
||||||
|
* @param flags_p IRQ triggering options (currently unused)
|
||||||
|
*
|
||||||
|
* @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 _IsrTableEntry _CONCAT(_isr_irq, irq_p) \
|
||||||
|
__attribute__ ((used)) \
|
||||||
|
__attribute__ ((section(STRINGIFY(_CONCAT(.gnu.linkonce.isr_irq, irq_p))))) = \
|
||||||
|
{isr_param_p, isr_p}; \
|
||||||
|
irq_p; \
|
||||||
|
})
|
||||||
|
|
||||||
static ALWAYS_INLINE unsigned int _arch_irq_lock(void)
|
static ALWAYS_INLINE unsigned int _arch_irq_lock(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -189,6 +189,18 @@ SECTIONS
|
||||||
#endif
|
#endif
|
||||||
*(.data)
|
*(.data)
|
||||||
*(".data.*")
|
*(".data.*")
|
||||||
|
|
||||||
|
KEEP(*(.isr_irq*))
|
||||||
|
|
||||||
|
/* sections for IRQ0-9 */
|
||||||
|
KEEP(*(SORT(.gnu.linkonce.isr_irq[0-9])))
|
||||||
|
|
||||||
|
/* sections for IRQ10-99 */
|
||||||
|
KEEP(*(SORT(.gnu.linkonce.isr_irq[0-9][0-9])))
|
||||||
|
|
||||||
|
/* sections for IRQ100-999 */
|
||||||
|
KEEP(*(SORT(.gnu.linkonce.isr_irq[0-9][0-9][0-9])))
|
||||||
|
|
||||||
} GROUP_LINK_IN(RAMABLE_REGION)
|
} GROUP_LINK_IN(RAMABLE_REGION)
|
||||||
|
|
||||||
SECTION_PROLOGUE(initlevel, (OPTIONAL),)
|
SECTION_PROLOGUE(initlevel, (OPTIONAL),)
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#ifndef _SW_ISR_TABLE__H_
|
#ifndef _SW_ISR_TABLE__H_
|
||||||
#define _SW_ISR_TABLE__H_
|
#define _SW_ISR_TABLE__H_
|
||||||
|
|
||||||
|
#include <arch/cpu.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -43,6 +45,8 @@ typedef struct _IsrTableEntry _IsrTableEntry_t;
|
||||||
|
|
||||||
#ifdef CONFIG_ARC
|
#ifdef CONFIG_ARC
|
||||||
extern _IsrTableEntry_t _sw_isr_table[CONFIG_NUM_IRQS - 16];
|
extern _IsrTableEntry_t _sw_isr_table[CONFIG_NUM_IRQS - 16];
|
||||||
|
#elif CONFIG_NIOS2
|
||||||
|
extern _IsrTableEntry_t _sw_isr_table[NIOS2_NIRQ];
|
||||||
#else
|
#else
|
||||||
extern _IsrTableEntry_t _sw_isr_table[CONFIG_NUM_IRQS];
|
extern _IsrTableEntry_t _sw_isr_table[CONFIG_NUM_IRQS];
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -133,7 +133,7 @@ A##a:
|
||||||
|
|
||||||
#if defined(_ASMLANGUAGE) && !defined(_LINKER)
|
#if defined(_ASMLANGUAGE) && !defined(_LINKER)
|
||||||
|
|
||||||
#ifdef CONFIG_ARM
|
#if defined(CONFIG_ARM) || defined(CONFIG_NIOS2)
|
||||||
#define GTEXT(sym) .global FUNC(sym); .type FUNC(sym), %function
|
#define GTEXT(sym) .global FUNC(sym); .type FUNC(sym), %function
|
||||||
#define GDATA(sym) .global FUNC(sym); .type FUNC(sym), %object
|
#define GDATA(sym) .global FUNC(sym); .type FUNC(sym), %object
|
||||||
#define WTEXT(sym) .weak FUNC(sym); .type FUNC(sym), %function
|
#define WTEXT(sym) .weak FUNC(sym); .type FUNC(sym), %function
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue