nios2: add base exception handling code
Change-Id: I56b0ec1a3576a77ca7bd6f2c0217de8053406927 Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
parent
b6d9c5ca80
commit
e2ff2fdd91
5 changed files with 420 additions and 24 deletions
|
@ -3,7 +3,7 @@ ccflags-y +=-I$(srctree)/arch/$(ARCH)/include
|
|||
ccflags-y += -I$(srctree)/kernel/microkernel/include
|
||||
|
||||
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
|
||||
|
||||
obj-$(CONFIG_IRQ_OFFLOAD) += irq_offload.o
|
||||
|
||||
|
|
244
arch/nios2/core/exception.S
Normal file
244
arch/nios2/core/exception.S
Normal file
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* Copyright (c) 2016 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 <arch/nios2/asm.h>
|
||||
#include <nano_private.h>
|
||||
|
||||
/* exports */
|
||||
GTEXT(_exception)
|
||||
GTEXT(_exception_exit)
|
||||
GTEXT(_exception_enter_fault)
|
||||
|
||||
/* import */
|
||||
GTEXT(_Fault)
|
||||
GTEXT(_Swap)
|
||||
GTEXT(_exception_try_muldiv)
|
||||
|
||||
/* Allows use of r1/at register, otherwise reserved for assembler use */
|
||||
.set noat
|
||||
|
||||
/* Placed into special 'exception' section so that the linker can put this code
|
||||
* at ALT_CPU_EXCEPTION_ADDR defined in system.h
|
||||
*
|
||||
* This is the common entry point for processor exceptions and interrupts from
|
||||
* the Internal Interrupt Controller (IIC).
|
||||
*
|
||||
* If the External (EIC) controller is in use, then we will never get here on
|
||||
* behalf of an interrupt, instead the EIC driver will have set up a vector
|
||||
* table and the processor will jump directly into the appropriate table
|
||||
* entry.
|
||||
*/
|
||||
SECTION_FUNC(exception.entry, _exception)
|
||||
/* Reserve thread stack space for saving context */
|
||||
addi sp, sp, -76
|
||||
|
||||
/* Preserve all caller-saved registers onto the thread's stack */
|
||||
stw ra, 0(sp)
|
||||
/* Gap here for muldiv handler to store zero register */
|
||||
stw r1, 8(sp)
|
||||
stw r2, 12(sp)
|
||||
stw r3, 16(sp)
|
||||
stw r4, 20(sp)
|
||||
stw r5, 24(sp)
|
||||
stw r6, 28(sp)
|
||||
stw r7, 32(sp)
|
||||
stw r8, 36(sp)
|
||||
stw r9, 40(sp)
|
||||
stw r10, 44(sp)
|
||||
stw r11, 48(sp)
|
||||
stw r12, 52(sp)
|
||||
stw r13, 56(sp)
|
||||
stw r14, 60(sp)
|
||||
stw r15, 64(sp)
|
||||
|
||||
/* Store value of estatus control register */
|
||||
rdctl et, estatus
|
||||
stw et, 68(sp)
|
||||
|
||||
/* ea-4 is the address of the instruction when the exception happened,
|
||||
* put this in the stack frame as well
|
||||
*/
|
||||
addi r15, ea, -4
|
||||
stw r15, 72(sp)
|
||||
|
||||
/* Figure out whether we are here because of an interrupt or an
|
||||
* exception. If an interrupt, switch stacks and enter IRQ handling
|
||||
* code. If an exception, remain on current stack and enter exception
|
||||
* handing code. From the CPU manual, ipending must be nonzero and
|
||||
* estatis.PIE must be enabled for this to be considered an interrupt.
|
||||
*
|
||||
* Stick ipending in r4 since it will be an arg for _enter_irq
|
||||
*/
|
||||
rdctl r4, ipending
|
||||
beq r4, zero, not_interrupt
|
||||
/* We stashed estatus in et earlier */
|
||||
andi r15, et, 1
|
||||
beq r15, zero, not_interrupt
|
||||
|
||||
/* If we get here, this is an interrupt */
|
||||
|
||||
/* Grab a reference to _nanokernel in r10 so we can determine the
|
||||
* current irq stack pointer
|
||||
*/
|
||||
movhi r10, %hi(_nanokernel)
|
||||
ori r10, r10, %lo(_nanokernel)
|
||||
|
||||
/* Stash a copy of thread's sp in r12 so that we can put it on the IRQ
|
||||
* stack
|
||||
*/
|
||||
mov r12, sp
|
||||
|
||||
/* Switch to interrupt stack */
|
||||
ldw sp, __tNANO_irq_sp_OFFSET(r10)
|
||||
|
||||
/* Store thread stack pointer onto IRQ stack */
|
||||
addi sp, sp, -4
|
||||
stw r12, 0(sp)
|
||||
|
||||
BRANCH_LABEL(on_irq_stack)
|
||||
|
||||
#if 0 /* TODO enable interrupt handling code */
|
||||
/* Enter C interrupt handling code. Value of ipending will be the
|
||||
* function parameter since we put it in r4
|
||||
*/
|
||||
call _enter_irq
|
||||
#endif
|
||||
|
||||
/* Interrupt handler finished and the interrupt should be serviced
|
||||
* now, the appropriate bits in ipending should be cleared */
|
||||
|
||||
/* Get a reference to _nanokernel again in r10 */
|
||||
movhi r10, %hi(_nanokernel)
|
||||
ori r10, r10, %lo(_nanokernel)
|
||||
|
||||
/* Determine whether the execution of the ISR requires a context
|
||||
* switch. If the interrupted thread is PREEMPTIBLE (a task) and
|
||||
* _nanokernel.fiber is non-NULL, a _Swap() needs to occur.
|
||||
*/
|
||||
|
||||
/* Check (_nanokernel.current->flags & PREEMPTIBLE), if not
|
||||
* goto no_reschedule
|
||||
*/
|
||||
ldw r11, __tNANO_current_OFFSET(r10)
|
||||
ldw r12, __tTCS_flags_OFFSET(r11)
|
||||
movi r13, PREEMPTIBLE
|
||||
and r12, r13, r12
|
||||
beq r12, zero, no_reschedule
|
||||
|
||||
/* Check _nanokernel.fiber != NULL, if NULL goto no_reschedule */
|
||||
ldw r11, __tNANO_fiber_OFFSET(r10)
|
||||
beq r11, zero, no_reschedule
|
||||
|
||||
/*
|
||||
* A context reschedule is required: keep the volatile registers of
|
||||
* the interrupted thread on the context's stack. Utilize
|
||||
* the existing _Swap() primitive to save the remaining
|
||||
* thread's registers (including floating point) and perform
|
||||
* a switch to the new thread.
|
||||
*/
|
||||
|
||||
/* We put the thread stack pointer on top of the IRQ stack before
|
||||
* we switched stacks. Restore it to go back to thread stack
|
||||
*/
|
||||
ldw sp, 0(sp)
|
||||
|
||||
/* Argument to Swap() is estatus since that's the state of the
|
||||
* status register before the exception happened. When coming
|
||||
* out of the context switch we need this info to restore
|
||||
* IRQ lock state. We put this value in et earlier.
|
||||
*/
|
||||
mov r4, et
|
||||
|
||||
call _Swap
|
||||
jmpi _exception_exit
|
||||
|
||||
BRANCH_LABEL(not_interrupt)
|
||||
|
||||
#if 0 /* TODO enable multiply / divide exception handing */
|
||||
|
||||
/* Since this wasn't an interrupt we're not going to restart the
|
||||
* faulting instruction. If it's an unimplemented math instruction,
|
||||
* the muldiv code will handle it, else we just give up and _Fault.
|
||||
*
|
||||
* We earlier put ea - 4 in the stack frame, replace it with just ea
|
||||
*/
|
||||
stw ea, 72(sp)
|
||||
|
||||
/* Could be an unimplemented instruction we have to emulate.
|
||||
* Smaller Nios II cores don't have multiply or divide instructions.
|
||||
* This code comes back to either _exception_enter_fault or
|
||||
* _exception_exit
|
||||
*/
|
||||
jmpi _exception_try_muldiv
|
||||
#endif
|
||||
|
||||
SECTION_FUNC(exception.entry, _exception_enter_fault)
|
||||
/* If we get here, the exception wasn't in interrupt or an
|
||||
* unimplemented math instruction. Let _Fault() handle it in
|
||||
* C domain
|
||||
*/
|
||||
|
||||
ldw r4, 0(sp)
|
||||
call _Fault
|
||||
jmpi _exception_exit
|
||||
|
||||
BRANCH_LABEL(no_reschedule)
|
||||
|
||||
/* We put the thread stack pointer on top of the IRQ stack before
|
||||
* we switched stacks. Restore it to go back to thread stack
|
||||
*/
|
||||
ldw sp, 0(sp)
|
||||
|
||||
/* Fall through */
|
||||
|
||||
SECTION_FUNC(exception.entry, _exception_exit)
|
||||
/* We are on the thread stack. Restore all saved registers
|
||||
* and return to the interrupted context */
|
||||
|
||||
/* Return address from the exception */
|
||||
ldw ea, 72(sp)
|
||||
|
||||
/* Restore estatus
|
||||
* XXX is this right??? */
|
||||
ldw r5, 68(sp)
|
||||
wrctl estatus, r5
|
||||
|
||||
/* Restore caller-saved registers */
|
||||
ldw ra, 0(sp)
|
||||
ldw r1, 8(sp)
|
||||
ldw r2, 12(sp)
|
||||
ldw r3, 16(sp)
|
||||
ldw r4, 20(sp)
|
||||
ldw r5, 24(sp)
|
||||
ldw r6, 28(sp)
|
||||
ldw r7, 32(sp)
|
||||
ldw r8, 36(sp)
|
||||
ldw r9, 40(sp)
|
||||
ldw r10, 44(sp)
|
||||
ldw r11, 48(sp)
|
||||
ldw r12, 52(sp)
|
||||
ldw r13, 56(sp)
|
||||
ldw r14, 60(sp)
|
||||
ldw r15, 64(sp)
|
||||
|
||||
/* Put the stack pointer back where it was when we entered
|
||||
* exception state
|
||||
*/
|
||||
addi sp, sp, 76
|
||||
|
||||
/* All done, copy estatus into status and transfer to ea */
|
||||
eret
|
|
@ -19,9 +19,26 @@
|
|||
#include <nano_private.h>
|
||||
#include <misc/printk.h>
|
||||
|
||||
/* TODO initialize with sentinel values */
|
||||
const NANO_ESF _default_esf;
|
||||
|
||||
const NANO_ESF _default_esf = {
|
||||
0xdeadbaad,
|
||||
0xdeadbaad,
|
||||
0xdeadbaad,
|
||||
0xdeadbaad,
|
||||
0xdeadbaad,
|
||||
0xdeadbaad,
|
||||
0xdeadbaad,
|
||||
0xdeadbaad,
|
||||
0xdeadbaad,
|
||||
0xdeadbaad,
|
||||
0xdeadbaad,
|
||||
0xdeadbaad,
|
||||
0xdeadbaad,
|
||||
0xdeadbaad,
|
||||
0xdeadbaad,
|
||||
0xdeadbaad,
|
||||
0xdeadbaad,
|
||||
0xdeadbaad
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -42,22 +59,73 @@ const NANO_ESF _default_esf;
|
|||
FUNC_NORETURN void _NanoFatalErrorHandler(unsigned int reason,
|
||||
const NANO_ESF *esf)
|
||||
{
|
||||
/* STUB TODO: dump out reason for the error and any interesting
|
||||
* info in esf
|
||||
*/
|
||||
#ifdef CONFIG_PRINTK
|
||||
switch (reason) {
|
||||
case _NANO_ERR_CPU_EXCEPTION:
|
||||
case _NANO_ERR_SPURIOUS_INT:
|
||||
break;
|
||||
|
||||
case _NANO_ERR_INVALID_TASK_EXIT:
|
||||
printk("***** Invalid Exit Software Error! *****\n");
|
||||
break;
|
||||
|
||||
|
||||
case _NANO_ERR_ALLOCATION_FAIL:
|
||||
printk("**** Kernel Allocation Failure! ****\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("**** Unknown Fatal Error %d! ****\n", reason);
|
||||
break;
|
||||
}
|
||||
|
||||
printk("Current thread ID: 0x%x\n"
|
||||
"Faulting instruction: 0x%x\n"
|
||||
" r1: 0x%x r2: 0x%x r3: 0x%x r4: 0x%x\n"
|
||||
" r5: 0x%x r6: 0x%x r7: 0x%x r8: 0x%x\n"
|
||||
" r9: 0x%x r10: 0x%x r11: 0x%x r12: 0x%x\n"
|
||||
"r13: 0x%x r14: 0x%x r15: 0x%x ra: 0x%x\n"
|
||||
"estatus: %x\n", sys_thread_self_get(), esf->instr,
|
||||
esf->r1, esf->r2, esf->r3, esf->r4,
|
||||
esf->r5, esf->r6, esf->r7, esf->r8,
|
||||
esf->r9, esf->r10, esf->r11, esf->r12,
|
||||
esf->r13, esf->r14, esf->r15, esf->ra,
|
||||
esf->estatus);
|
||||
#endif
|
||||
|
||||
_SysFatalErrorHandler(reason, esf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
FUNC_NORETURN void _Fault(void)
|
||||
FUNC_NORETURN void _Fault(const NANO_ESF *esf)
|
||||
{
|
||||
/* STUB TODO dump out reason for this exception */
|
||||
#ifdef CONFIG_PRINTK
|
||||
/* Unfortunately, completely unavailable on Nios II/e cores */
|
||||
#ifdef NIOS2_HAS_EXTRA_EXCEPTION_INFO
|
||||
uint32_t exc_reg, badaddr_reg, eccftl;
|
||||
enum nios2_exception_cause cause;
|
||||
|
||||
_NanoFatalErrorHandler(_NANO_ERR_HW_EXCEPTION, &_default_esf);
|
||||
exc_reg = _nios2_creg_read(NIOS2_CR_EXCEPTION);
|
||||
|
||||
/* Bit 31 indicates potentially fatal ECC error */
|
||||
eccftl = (exc_reg & NIOS2_EXCEPTION_REG_ECCFTL_MASK) != 0;
|
||||
|
||||
/* Bits 2-6 contain the cause code */
|
||||
cause = (exc_reg & NIOS2_EXCEPTION_REG_CAUSE_MASK)
|
||||
>> NIOS2_EXCEPTION_REG_CAUSE_OFST;
|
||||
printk("Exception cause: 0x%x ECCFTL: %d\n", exc_reg, eccftl);
|
||||
if (BIT(cause) & NIOS2_BADADDR_CAUSE_MASK) {
|
||||
badaddr_reg = _nios2_creg_read(NIOS2_CR_BADADDR);
|
||||
printk("Badaddr: 0x%x\n", badaddr_reg);
|
||||
}
|
||||
#endif /* NIOS2_HAS_EXTRA_EXCEPTION_INFO */
|
||||
#endif /* CONFIG_PRINTK */
|
||||
|
||||
_NanoFatalErrorHandler(_NANO_ERR_CPU_EXCEPTION, esf);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Fatal error handler
|
||||
|
@ -74,20 +142,42 @@ FUNC_NORETURN void _Fault(void)
|
|||
* information to a persistent repository and/or rebooting the system.
|
||||
*
|
||||
* @param reason the fatal error reason
|
||||
* @param pEsf the pointer to the exception stack frame
|
||||
* @param pEsf pointer to exception stack frame
|
||||
*
|
||||
* @return This function does not return.
|
||||
* @return N/A
|
||||
*/
|
||||
FUNC_NORETURN void _SysFatalErrorHandler(unsigned int reason,
|
||||
const NANO_ESF *esf)
|
||||
const NANO_ESF *pEsf)
|
||||
{
|
||||
/* STUB TODO try to abort task/fibers like in the x86 implementation */
|
||||
printk("Fatal error!\n");
|
||||
nano_context_type_t curCtx = sys_execution_context_type_get();
|
||||
|
||||
while (1) {
|
||||
/* whee! */
|
||||
ARG_UNUSED(reason);
|
||||
ARG_UNUSED(pEsf);
|
||||
|
||||
if ((curCtx != NANO_CTX_ISR) && !_is_thread_essential()) {
|
||||
#ifdef CONFIG_MICROKERNEL
|
||||
if (curCtx == NANO_CTX_TASK) {
|
||||
extern FUNC_NORETURN void _TaskAbort(void);
|
||||
printk("Fatal task error! Aborting task.\n");
|
||||
_TaskAbort();
|
||||
} else
|
||||
#endif /* CONFIG_MICROKERNEL */
|
||||
{
|
||||
printk("Fatal fiber error! Aborting fiber.\n");
|
||||
fiber_abort();
|
||||
}
|
||||
CODE_UNREACHABLE;
|
||||
}
|
||||
|
||||
printk("Fatal fault in %s ! Spinning...\n",
|
||||
curCtx == NANO_CTX_ISR
|
||||
? "ISR"
|
||||
: curCtx == NANO_CTX_FIBER ? "essential fiber"
|
||||
: "essential task");
|
||||
#ifdef NIOS2_HAS_DEBUG_STUB
|
||||
_nios2_break();
|
||||
#endif
|
||||
for (;;)
|
||||
; /* Spin forever */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -154,6 +154,7 @@ struct s_NANO {
|
|||
|
||||
typedef struct s_NANO tNANO;
|
||||
extern tNANO _nanokernel;
|
||||
extern char _interrupt_stack[CONFIG_ISR_STACK_SIZE];
|
||||
|
||||
|
||||
/* Arch-specific nanokernel APIs */
|
||||
|
@ -162,7 +163,8 @@ void nano_cpu_atomic_idle(unsigned int key);
|
|||
|
||||
static ALWAYS_INLINE void nanoArchInit(void)
|
||||
{
|
||||
/* STUB */
|
||||
_nanokernel.irq_sp = (char *)STACK_ROUND_DOWN(_interrupt_stack +
|
||||
CONFIG_ISR_STACK_SIZE);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void fiberRtnValueSet(struct tcs *fiber,
|
||||
|
|
|
@ -34,10 +34,11 @@ extern "C" {
|
|||
|
||||
#define STACK_ALIGN 4
|
||||
|
||||
#define _NANO_ERR_HW_EXCEPTION (0) /* MPU/Bus/Usage fault */
|
||||
#define _NANO_ERR_CPU_EXCEPTION (0) /* Any unhandled exception */
|
||||
#define _NANO_ERR_INVALID_TASK_EXIT (1) /* Invalid task exit */
|
||||
#define _NANO_ERR_STACK_CHK_FAIL (2) /* Stack corruption detected */
|
||||
#define _NANO_ERR_ALLOCATION_FAIL (3) /* Kernel Allocation Failure */
|
||||
#define _NANO_ERR_SPURIOUS_INT (4) /* Spurious interrupt */
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <stdint.h>
|
||||
|
@ -93,8 +94,25 @@ void _arch_irq_enable(unsigned int irq);
|
|||
void _arch_irq_disable(unsigned int irq);
|
||||
|
||||
struct __esf {
|
||||
/* XXX - not defined yet */
|
||||
uint32_t placeholder;
|
||||
uint32_t ra; /* return address r31 */
|
||||
uint32_t r0; /* zero register */
|
||||
uint32_t r1; /* at */
|
||||
uint32_t r2; /* return value */
|
||||
uint32_t r3; /* return value */
|
||||
uint32_t r4; /* register args */
|
||||
uint32_t r5; /* register args */
|
||||
uint32_t r6; /* register args */
|
||||
uint32_t r7; /* register args */
|
||||
uint32_t r8; /* Caller-saved general purpose */
|
||||
uint32_t r9; /* Caller-saved general purpose */
|
||||
uint32_t r10; /* Caller-saved general purpose */
|
||||
uint32_t r11; /* Caller-saved general purpose */
|
||||
uint32_t r12; /* Caller-saved general purpose */
|
||||
uint32_t r13; /* Caller-saved general purpose */
|
||||
uint32_t r14; /* Caller-saved general purpose */
|
||||
uint32_t r15; /* Caller-saved general purpose */
|
||||
uint32_t estatus;
|
||||
uint32_t instr; /* Instruction being executed when exc occurred */
|
||||
};
|
||||
|
||||
typedef struct __esf NANO_ESF;
|
||||
|
@ -103,6 +121,48 @@ extern const NANO_ESF _default_esf;
|
|||
FUNC_NORETURN void _SysFatalErrorHandler(unsigned int reason,
|
||||
const NANO_ESF *esf);
|
||||
|
||||
|
||||
enum nios2_exception_cause {
|
||||
NIOS2_EXCEPTION_UNKNOWN = -1,
|
||||
NIOS2_EXCEPTION_RESET = 0,
|
||||
NIOS2_EXCEPTION_CPU_ONLY_RESET_REQUEST = 1,
|
||||
NIOS2_EXCEPTION_INTERRUPT = 2,
|
||||
NIOS2_EXCEPTION_TRAP_INST = 3,
|
||||
NIOS2_EXCEPTION_UNIMPLEMENTED_INST = 4,
|
||||
NIOS2_EXCEPTION_ILLEGAL_INST = 5,
|
||||
NIOS2_EXCEPTION_MISALIGNED_DATA_ADDR = 6,
|
||||
NIOS2_EXCEPTION_MISALIGNED_TARGET_PC = 7,
|
||||
NIOS2_EXCEPTION_DIVISION_ERROR = 8,
|
||||
NIOS2_EXCEPTION_SUPERVISOR_ONLY_INST_ADDR = 9,
|
||||
NIOS2_EXCEPTION_SUPERVISOR_ONLY_INST = 10,
|
||||
NIOS2_EXCEPTION_SUPERVISOR_ONLY_DATA_ADDR = 11,
|
||||
NIOS2_EXCEPTION_TLB_MISS = 12,
|
||||
NIOS2_EXCEPTION_TLB_EXECUTE_PERM_VIOLATION = 13,
|
||||
NIOS2_EXCEPTION_TLB_READ_PERM_VIOLATION = 14,
|
||||
NIOS2_EXCEPTION_TLB_WRITE_PERM_VIOLATION = 15,
|
||||
NIOS2_EXCEPTION_MPU_INST_REGION_VIOLATION = 16,
|
||||
NIOS2_EXCEPTION_MPU_DATA_REGION_VIOLATION = 17,
|
||||
NIOS2_EXCEPTION_ECC_TLB_ERR = 18,
|
||||
NIOS2_EXCEPTION_ECC_FETCH_ERR = 19,
|
||||
NIOS2_EXCEPTION_ECC_REGISTER_FILE_ERR = 20,
|
||||
NIOS2_EXCEPTION_ECC_DATA_ERR = 21,
|
||||
NIOS2_EXCEPTION_ECC_DATA_CACHE_WRITEBACK_ERR = 22
|
||||
};
|
||||
|
||||
/* Bitfield indicating which exception cause codes report a valid
|
||||
* badaddr register. NIOS2_EXCEPTION_TLB_MISS and NIOS2_EXCEPTION_ECC_TLB_ERR
|
||||
* are deliberately not included here, you need to check if TLBMISC.D=1
|
||||
*/
|
||||
#define NIOS2_BADADDR_CAUSE_MASK \
|
||||
(BIT(NIOS2_EXCEPTION_SUPERVISOR_ONLY_DATA_ADDR) | \
|
||||
BIT(NIOS2_EXCEPTION_MISALIGNED_DATA_ADDR) | \
|
||||
BIT(NIOS2_EXCEPTION_MISALIGNED_TARGET_PC) | \
|
||||
BIT(NIOS2_EXCEPTION_TLB_READ_PERM_VIOLATION) | \
|
||||
BIT(NIOS2_EXCEPTION_TLB_WRITE_PERM_VIOLATION) | \
|
||||
BIT(NIOS2_EXCEPTION_MPU_DATA_REGION_VIOLATION) | \
|
||||
BIT(NIOS2_EXCEPTION_ECC_DATA_ERR))
|
||||
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue