mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 00:14:22 +08:00
Add exception handling logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3023 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
@@ -166,6 +166,22 @@ static int up_getgrp(unsigned int irq)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: avr32_xcptn
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Handlers for unexpected execptions. All are fatal error conditions.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int avr32_xcptn(int irq, FAR void *context)
|
||||||
|
{
|
||||||
|
(void)irqsave();
|
||||||
|
lldbg("PANIC!!! Exception IRQ: %d\n", irq);
|
||||||
|
PANIC(OSERR_UNEXPECTEDISR);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -177,6 +193,7 @@ static int up_getgrp(unsigned int irq)
|
|||||||
void up_irqinitialize(void)
|
void up_irqinitialize(void)
|
||||||
{
|
{
|
||||||
int group;
|
int group;
|
||||||
|
int irq;
|
||||||
|
|
||||||
/* Initialize the table that provides the value of the IPR register to
|
/* Initialize the table that provides the value of the IPR register to
|
||||||
* use to assign a group to different interrupt priorities.
|
* use to assign a group to different interrupt priorities.
|
||||||
@@ -204,9 +221,10 @@ void up_irqinitialize(void)
|
|||||||
|
|
||||||
/* Attach the exception handlers */
|
/* Attach the exception handlers */
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG
|
for (irq = 0; irq < AVR32_IRQ_NEVENTS; irq++)
|
||||||
#warning "Missing logic"
|
{
|
||||||
#endif
|
irq_attach(irq, avr32_xcptn);
|
||||||
|
}
|
||||||
|
|
||||||
/* And finally, enable interrupts */
|
/* And finally, enable interrupts */
|
||||||
|
|
||||||
@@ -246,10 +264,13 @@ int up_prioritize_irq(int irq, int priority)
|
|||||||
* Name: avr32_intirqno
|
* Name: avr32_intirqno
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Return the highest priority pending INT0 interrupt.
|
* Return the highest priority pending INTn interrupt (hwere n=level).
|
||||||
|
* This is called directly from interrupt handling logic. This should be
|
||||||
|
* save since the UC3B will save all C scratch/volatile registers (and
|
||||||
|
* this function should not alter the perserved/static registers).
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#warning "Is this safe to call from assembly?"
|
|
||||||
unsigned int avr32_intirqno(unsigned int level)
|
unsigned int avr32_intirqno(unsigned int level)
|
||||||
{
|
{
|
||||||
/* Get the group that caused the interrupt: "ICRn identifies the group with
|
/* Get the group that caused the interrupt: "ICRn identifies the group with
|
||||||
|
|||||||
@@ -38,16 +38,18 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
#include <arch/avr32/avr32.h>
|
#include <arch/avr32/avr32.h>
|
||||||
|
#include <arch/irq.h>
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* External Symbols
|
* External Symbols
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
.global avr32_int0irqno /* Returns the IRQ number of an INT0 interrupt */
|
.global avr32_int0irqno /* Returns IRQ number of INT0 event */
|
||||||
.global avr32_int1irqno /* Returns the IRQ number of an INT1 interrupt */
|
.global avr32_int1irqno /* Returns IRQ number of INT1 event */
|
||||||
.global avr32_int2irqno /* Returns the IRQ number of an INT2 interrupt */
|
.global avr32_int2irqno /* Returns IRQ number of INT2 event */
|
||||||
.global avr32_int3irqno /* Returns the IRQ number of an INT3 interrupt */
|
.global avr32_int3irqno /* Returns IRQ number of INT3 event */
|
||||||
.global up_doirq /* Dispatch an IRQ */
|
.global up_doirq /* Dispatch an IRQ */
|
||||||
.global up_fullcontextrestore /* Restore new task contex */
|
.global up_fullcontextrestore /* Restore new task contex */
|
||||||
|
|
||||||
@@ -55,22 +57,30 @@
|
|||||||
* Macros
|
* Macros
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#warning "Missing Logic"
|
/* Exception entry logic. On entry, thee context save area looks like: */
|
||||||
|
/* xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx SR PC */
|
||||||
|
/* ^ ^+2*4 */
|
||||||
|
/* Upon joining common logic, the context save are will look like: */
|
||||||
|
/* xx xx xx xx xx xx xx xx xx xx xx xx xx xx 10 SR PC */
|
||||||
|
/* ^ ^+3*4 */
|
||||||
|
/* and r10 will hold the exception's IRQ number */
|
||||||
|
|
||||||
.macro HANDLER, label, irqno
|
.macro HANDLER, label, irqno
|
||||||
\label:
|
\label:
|
||||||
rjmp avr32_excptcommon /* FIXME!!! Need IRQ in a register */
|
st.w --sp, r10
|
||||||
|
mov r10, \irqno
|
||||||
|
rjmp avr32_xcptcommon /* FIXME!!! Need IRQ in a register */
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Exception Vector Table
|
* Exception Vector Table
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* The Exception Vector Base Address (EVBA) register will contain "a pointer
|
/* The Exception Vector Base Address (EVBA) register will contain "a */
|
||||||
* to the exception routines. All exception routines start at this address,
|
/* pointer to the exception routines. All exception routines start at this */
|
||||||
* or at a defined offset relative to the address. Special alignment
|
/* address, or at a defined offset relative to the address. Special */
|
||||||
* requirements may apply for EVBA, depending on the implementation of the
|
/* alignment requirements may apply for EVBA, depending on the */
|
||||||
* interrupt controller."
|
/* implementation of the interrupt controller." */
|
||||||
*/
|
|
||||||
|
|
||||||
/* REVISIT: This alignment requirement may be different on other AVR32s */
|
/* REVISIT: This alignment requirement may be different on other AVR32s */
|
||||||
|
|
||||||
@@ -83,7 +93,7 @@ vectortab:
|
|||||||
lda.w pc, avr32_unrec /* EVBA+0x00 Unrecoverable exception */
|
lda.w pc, avr32_unrec /* EVBA+0x00 Unrecoverable exception */
|
||||||
lda.w pc, avr32_tlbmult /* EVBA+0x04 TLB multiple hit */
|
lda.w pc, avr32_tlbmult /* EVBA+0x04 TLB multiple hit */
|
||||||
lda.w pc, avr32_busdata /* EVBA+0x08 Bus error data fetch */
|
lda.w pc, avr32_busdata /* EVBA+0x08 Bus error data fetch */
|
||||||
lda.w pc, avr32_businst /* EVBA+0x0c Bus error instruction fetch */
|
lda.w pc, avr32_businst /* EVBA+0x0c Bus error instr fetch */
|
||||||
lda.w pc, avr32_nmi /* EVBA+0x10 NMI */
|
lda.w pc, avr32_nmi /* EVBA+0x10 NMI */
|
||||||
lda.w pc, avr32_instaddr /* EVBA+0x14 Instruction Address */
|
lda.w pc, avr32_instaddr /* EVBA+0x14 Instruction Address */
|
||||||
lda.w pc, avr32_itlbrot /* EVBA+0x18 ITLB Protection */
|
lda.w pc, avr32_itlbrot /* EVBA+0x18 ITLB Protection */
|
||||||
@@ -119,15 +129,13 @@ vectortab:
|
|||||||
* Interrupts
|
* Interrupts
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* The interrupt controller must provide an address that is relative to the
|
/* The interrupt controller must provide an address that is relative to the */
|
||||||
* the EVBA so it is natural to define these interrupt vectors just after
|
/* the EVBA so it is natural to define these interrupt vectors just after */
|
||||||
* the exception table.
|
/* the exception table. On entry to each interrupt handler, R8-R12, LR, PC */
|
||||||
* On entry to each interrupt handler, R8-R12, LR, PC and SR have already been
|
/* and SR have already been pushed onto the system stack by the MCU. */
|
||||||
* pushed onto the system stack by the MCU.
|
/* */
|
||||||
*
|
/* An interrupt may disappear while it is being fetched by the CPU and, */
|
||||||
* An interrupt may disappear while it is being fetched by the CPU and, hence,
|
/* hence spurious interrupt may result. */
|
||||||
* spurious interrupt may result.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.balign 4
|
.balign 4
|
||||||
.global avr32_int0
|
.global avr32_int0
|
||||||
@@ -156,8 +164,8 @@ avr32_int3:
|
|||||||
|
|
||||||
avr32_intcommon:
|
avr32_intcommon:
|
||||||
mcall .Lavr32_intirqno /* Get the IRQ number of the int0 event */
|
mcall .Lavr32_intirqno /* Get the IRQ number of the int0 event */
|
||||||
cp.w r12, 0 /* Negated errno returned if spurious interrupt */
|
cp.w r12, 0 /* Negative returned if spurious interrupt */
|
||||||
brge avr32_common /* Jump to the common exception handling logic */
|
brge avr32_common /* Jump to the common xcptn handling logic */
|
||||||
rete /* Ignore spurious interrupt */
|
rete /* Ignore spurious interrupt */
|
||||||
|
|
||||||
.Lavr32_intirqno:
|
.Lavr32_intirqno:
|
||||||
@@ -167,41 +175,79 @@ avr32_intcommon:
|
|||||||
* Exception Vector Handlers
|
* Exception Vector Handlers
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* Exception Handlers */
|
/* Exception Handlers: */
|
||||||
|
/* On entry to each, the context save area looks like this: */
|
||||||
|
/* xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx SR PC */
|
||||||
|
/* ^ ^+2*4 */
|
||||||
|
|
||||||
HANDLER avr32_unrec, AVR32_IRQ_UNREC /* Unrecoverable exception */
|
HANDLER avr32_unrec, AVR32_IRQ_UNREC /* Unrecoverable xcptn */
|
||||||
HANDLER avr32_tlbmult, AVR32_IRQ_TLBMULT /* TLB multiple hit */
|
HANDLER avr32_tlbmult, AVR32_IRQ_TLBMULT /* TLB multiple hit */
|
||||||
HANDLER avr32_busdata, AVR32_IRQ_BUSDATA /* Bus error data fetch */
|
HANDLER avr32_busdata, AVR32_IRQ_BUSDATA /* Bus error data fetch */
|
||||||
HANDLER avr32_businst, AVR32_IRQ_BUSINST /* Bus error instruction fetch */
|
HANDLER avr32_businst, AVR32_IRQ_BUSINST /* Bus err instr fetch */
|
||||||
HANDLER avr32_nmi, AVR32_IRQ_NMI /* NMI */
|
HANDLER avr32_nmi, AVR32_IRQ_NMI /* NMI */
|
||||||
HANDLER avr32_instaddr, AVR32_IRQ_INSTADDR /* Instruction Address */
|
HANDLER avr32_instaddr, AVR32_IRQ_INSTADDR /* Instruction Address */
|
||||||
HANDLER avr32_itlbrot, AVR32_IRQ_ITLBPROT /* ITLB Protection */
|
HANDLER avr32_itlbrot, AVR32_IRQ_ITLBPROT /* ITLB Protection */
|
||||||
HANDLER avr32_bp, AVR32_IRQ_BP /* Breakpoint */
|
HANDLER avr32_bp, AVR32_IRQ_BP /* Breakpoint */
|
||||||
HANDLER avr32_invinst, AVR32_IRQ_INVINST /* Illegal Opcode */
|
HANDLER avr32_invinst, AVR32_IRQ_INVINST /* Illegal Opcode */
|
||||||
HANDLER avr32_unimpinst, AVR32_IRQ_UNIMPINST /* Unimplemented instruction */
|
HANDLER avr32_unimpinst, AVR32_IRQ_UNIMPINST /* Unimplemented intsr */
|
||||||
HANDLER avr32_priv, AVR32_IRQ_PRIV /* Privilege violation */
|
HANDLER avr32_priv, AVR32_IRQ_PRIV /* Privilege violation */
|
||||||
HANDLER avr32_fp, AVR32_IRQ_FP /* Floating-point */
|
HANDLER avr32_fp, AVR32_IRQ_FP /* Floating-point */
|
||||||
HANDLER avr32_cop, AVR32_IRQ_COP /* Coprocessor absent */
|
HANDLER avr32_cop, AVR32_IRQ_COP /* Coprocessor absent */
|
||||||
HANDLER avr32_rddata, AVR32_IRQ_RDDATA /* Data Address (Read) */
|
HANDLER avr32_rddata, AVR32_IRQ_RDDATA /* Data Address (RD) */
|
||||||
HANDLER avr32_wrdata, AVR32_IRQ_WRDATA /* Data Address (Write) */
|
HANDLER avr32_wrdata, AVR32_IRQ_WRDATA /* Data Address (WR) */
|
||||||
HANDLER avr32_tddtlbprot, AVR32_IRQ_RDDTLBPROT /* DTLB Protection (Read) */
|
HANDLER avr32_tddtlbprot, AVR32_IRQ_RDDTLBPROT /* DTLB Protection (RD) */
|
||||||
HANDLER avr32_wrdtlbprot, AVR32_IRQ_WRDTLBPROT /* DTLB Protection (Write) */
|
HANDLER avr32_wrdtlbprot, AVR32_IRQ_WRDTLBPROT /* DTLB Protection (WR) */
|
||||||
HANDLER avr32_dltbmod, AVR32_IRQ_DLTBMOD /* DTLB Modified */
|
HANDLER avr32_dltbmod, AVR32_IRQ_DLTBMOD /* DTLB Modified */
|
||||||
HANDLER avr32_itlbmiss, AVR32_IRQ_ITLBMISS /* ITLB Miss */
|
HANDLER avr32_itlbmiss, AVR32_IRQ_ITLBMISS /* ITLB Miss */
|
||||||
HANDLER avr32_rddtlb, AVR32_IRQ_RDDTLB /* DTLB Miss (Read) */
|
HANDLER avr32_rddtlb, AVR32_IRQ_RDDTLB /* DTLB Miss (RD) */
|
||||||
HANDLER avr32_wrdtlb, AVR32_IRQ_WRDTLB /* DTLB Miss (Write) */
|
HANDLER avr32_wrdtlb, AVR32_IRQ_WRDTLB /* DTLB Miss (WR) */
|
||||||
HANDLER avr32_super, AVR32_IRQ_SUPER /* Supervisor call */
|
HANDLER avr32_super, AVR32_IRQ_SUPER /* Supervisor call */
|
||||||
HANDLER avr32_badvector, AVR32_IRQ_BADVECTOR /* No such vector */
|
HANDLER avr32_badvector, AVR32_IRQ_BADVECTOR /* No such vector */
|
||||||
|
|
||||||
/* Common exception handling logic. Unlike the interrupt handlers, the
|
/* Common exception handling logic. Unlike the interrupt handlers, the */
|
||||||
* exception handlers do not save R8-R12, and LR on the stack. Only the PC
|
/* exception handlers do not save R8-R12, and LR on the stack. Only the PC */
|
||||||
* and SR have been pushed onto the system stack by the MCU. The following
|
/* and SR have been pushed onto the system stack by the MCU. The following */
|
||||||
* loic creates a common stack frame for exception handlers prior to joining
|
/* logic creates a common stack frame for exception handlers prior to */
|
||||||
* to the common interrupt/exception logic below.
|
/* joining to the common interrupt/exception logic below. */
|
||||||
*/
|
/* */
|
||||||
|
/* The context save area looks like this on entry to the HANDLER above. */
|
||||||
|
/* xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx SR PC */
|
||||||
|
/* ^ ^+2*4 */
|
||||||
|
/* Upon joining common logic here, the context save are will loke: */
|
||||||
|
/* xx xx xx xx xx xx xx xx xx xx xx xx xx xx 10 SR PC */
|
||||||
|
/* ^ ^+3*4 */
|
||||||
|
/* and r10 will hold the exception's IRQ number */
|
||||||
|
/* */
|
||||||
|
/* either (1) non-time-critical, or (2) fatal. Obvious, that would not be */
|
||||||
|
/* the case if TLB missing handling is required. Such time-critical vector */
|
||||||
|
/* handling should be handled differently. */
|
||||||
|
|
||||||
avr32_excptcommon:
|
avr32_xcptcommon:
|
||||||
#warning "Missing Logic"
|
/* Save r10-r12, lr on the stack: */
|
||||||
|
/* xx xx xx xx xx xx xx xx xx xx xx LR 12 11 10 SR PC */
|
||||||
|
/* ^ ^+4*4 ^+6*4 */
|
||||||
|
|
||||||
|
stm --sp, r11-r12, lr
|
||||||
|
|
||||||
|
/* Move SR and PC into the expected position: */
|
||||||
|
/* xx xx xx xx xx xx xx xx xx SR PC LI 12 11 10 SR PC */
|
||||||
|
/* ^ ^+8*4 */
|
||||||
|
|
||||||
|
ld.w r11, sp[4*4]
|
||||||
|
ld.w r12, sp[5*4]
|
||||||
|
stm --sp, r11-r12
|
||||||
|
|
||||||
|
/* Save r8 and r8: */
|
||||||
|
/* xx xx xx xx xx xx xx xx xx SR PC LI 12 11 10 SR PC */
|
||||||
|
/* ^ ^+6*4 ^+8*4 */
|
||||||
|
|
||||||
|
st.w sp[6*4], r9
|
||||||
|
st.w sp[7*4], r8
|
||||||
|
|
||||||
|
/* Move the IRQ number in r12 and fall through to the common event handling */
|
||||||
|
/* logic. */
|
||||||
|
|
||||||
|
mov r12, r10
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Common Event Handling Logic
|
* Common Event Handling Logic
|
||||||
@@ -215,7 +261,7 @@ avr32_excptcommon:
|
|||||||
/* */
|
/* */
|
||||||
/* The context save area looks like this: */
|
/* The context save area looks like this: */
|
||||||
/* xx xx xx xx xx xx xx xx xx SR PC LR 12 11 10 09 08 */
|
/* xx xx xx xx xx xx xx xx xx SR PC LR 12 11 10 09 08 */
|
||||||
/* ^ +8*4 */
|
/* ^ ^+8*4 */
|
||||||
/* This function will finish construction of the register save structure */
|
/* This function will finish construction of the register save structure */
|
||||||
/* and call the IRQ dispatching logic. */
|
/* and call the IRQ dispatching logic. */
|
||||||
|
|
||||||
@@ -256,12 +302,12 @@ avr32_common:
|
|||||||
|
|
||||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||||
mov r7, sp
|
mov r7, sp
|
||||||
lddpc sp, .Lup_instackbase
|
lddpc sp, .Linstackbaseptr
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Call up_doirq with r12=IRQ number and r11=register save area */
|
/* Call up_doirq with r12=IRQ number and r11=register save area */
|
||||||
|
|
||||||
mcall .Lup_doirq
|
mcall .Ldoirqptr
|
||||||
|
|
||||||
/* Restore the user stack pointer. */
|
/* Restore the user stack pointer. */
|
||||||
/* 07 06 05 04 03 02 01 00 SP SR PC LR 12 11 10 09 08 */
|
/* 07 06 05 04 03 02 01 00 SP SR PC LR 12 11 10 09 08 */
|
||||||
@@ -296,13 +342,19 @@ avr32_common:
|
|||||||
/* the task context to restore. */
|
/* the task context to restore. */
|
||||||
|
|
||||||
1:
|
1:
|
||||||
lddpc pc, .Lup_fullcontextrestore
|
lddpc pc, .Lfullcontextrestoreptr
|
||||||
|
|
||||||
.Lup_doirq:
|
.Ldoirqptr:
|
||||||
.word up_doirq
|
.word up_doirq
|
||||||
.Lup_fullcontextrestore:
|
.Lfullcontextrestoreptr:
|
||||||
.word up_fullcontextrestore
|
.word up_fullcontextrestore
|
||||||
|
|
||||||
|
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||||
|
.Linstackbaseptr:
|
||||||
|
.word .Lintstackbase
|
||||||
|
#endif
|
||||||
|
.size vectortab, .-vectortab
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: up_interruptstack
|
* Name: up_interruptstack
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
@@ -314,11 +366,8 @@ avr32_common:
|
|||||||
.type up_interruptstack, object
|
.type up_interruptstack, object
|
||||||
up_interruptstack:
|
up_interruptstack:
|
||||||
.skip (CONFIG_ARCH_INTERRUPTSTACK & ~3)
|
.skip (CONFIG_ARCH_INTERRUPTSTACK & ~3)
|
||||||
up_intstackbase:
|
.Lintstackbase:
|
||||||
.size up_interruptstack, .-up_interruptstack
|
.size up_interruptstack, .-up_interruptstack
|
||||||
.Lup_instackbase
|
|
||||||
.word up_intstackbase
|
|
||||||
.size .Lup_instackbase, .-.Lup_instackbase
|
|
||||||
#endif
|
#endif
|
||||||
.end
|
.end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user