summaryrefslogtreecommitdiff
path: root/nuttx/arch/avr
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2010-10-16 16:30:47 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2010-10-16 16:30:47 +0000
commit983cbb40b9bfa02f7dcb812d4a2c4f2df6626093 (patch)
tree2bb8fcac22bde73d4df96206e43febd5fd377547 /nuttx/arch/avr
parent4be3a16c92e50578956884546c1458c9914e927e (diff)
downloadpx4-nuttx-983cbb40b9bfa02f7dcb812d4a2c4f2df6626093.tar.gz
px4-nuttx-983cbb40b9bfa02f7dcb812d4a2c4f2df6626093.tar.bz2
px4-nuttx-983cbb40b9bfa02f7dcb812d4a2c4f2df6626093.zip
Add exception handling logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3023 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/arch/avr')
-rw-r--r--nuttx/arch/avr/src/at91uc3/at91uc3_irq.c37
-rwxr-xr-xnuttx/arch/avr/src/avr32/up_exceptions.S259
2 files changed, 183 insertions, 113 deletions
diff --git a/nuttx/arch/avr/src/at91uc3/at91uc3_irq.c b/nuttx/arch/avr/src/at91uc3/at91uc3_irq.c
index 7e1204d25..c05e7496a 100644
--- a/nuttx/arch/avr/src/at91uc3/at91uc3_irq.c
+++ b/nuttx/arch/avr/src/at91uc3/at91uc3_irq.c
@@ -167,6 +167,22 @@ static int up_getgrp(unsigned int irq)
}
/****************************************************************************
+ * 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
****************************************************************************/
@@ -177,6 +193,7 @@ static int up_getgrp(unsigned int irq)
void up_irqinitialize(void)
{
int group;
+ int irq;
/* Initialize the table that provides the value of the IPR register to
* use to assign a group to different interrupt priorities.
@@ -194,9 +211,9 @@ void up_irqinitialize(void)
*/
for (group = 0; group < AVR32_IRQ_MAXGROUPS; group++)
- {
- putreg32(g_ipr[0], AVR32_INTC_IPR(group));
- }
+ {
+ putreg32(g_ipr[0], AVR32_INTC_IPR(group));
+ }
/* currents_regs is non-NULL only while processing an interrupt */
@@ -204,9 +221,10 @@ void up_irqinitialize(void)
/* Attach the exception handlers */
-#ifdef CONFIG_DEBUG
-#warning "Missing logic"
-#endif
+ for (irq = 0; irq < AVR32_IRQ_NEVENTS; irq++)
+ {
+ irq_attach(irq, avr32_xcptn);
+ }
/* And finally, enable interrupts */
@@ -246,10 +264,13 @@ int up_prioritize_irq(int irq, int priority)
* Name: avr32_intirqno
*
* 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)
{
/* Get the group that caused the interrupt: "ICRn identifies the group with
diff --git a/nuttx/arch/avr/src/avr32/up_exceptions.S b/nuttx/arch/avr/src/avr32/up_exceptions.S
index 3dbb7d68c..d7686e3d0 100755
--- a/nuttx/arch/avr/src/avr32/up_exceptions.S
+++ b/nuttx/arch/avr/src/avr32/up_exceptions.S
@@ -38,41 +38,51 @@
****************************************************************************/
#include <nuttx/config.h>
+
#include <arch/avr32/avr32.h>
+#include <arch/irq.h>
/****************************************************************************
* External Symbols
****************************************************************************/
- .global avr32_int0irqno /* Returns the IRQ number of an INT0 interrupt */
- .global avr32_int1irqno /* Returns the IRQ number of an INT1 interrupt */
- .global avr32_int2irqno /* Returns the IRQ number of an INT2 interrupt */
- .global avr32_int3irqno /* Returns the IRQ number of an INT3 interrupt */
- .global up_doirq /* Dispatch an IRQ */
- .global up_fullcontextrestore /* Restore new task contex */
+ .global avr32_int0irqno /* Returns IRQ number of INT0 event */
+ .global avr32_int1irqno /* Returns IRQ number of INT1 event */
+ .global avr32_int2irqno /* Returns IRQ number of INT2 event */
+ .global avr32_int3irqno /* Returns IRQ number of INT3 event */
+ .global up_doirq /* Dispatch an IRQ */
+ .global up_fullcontextrestore /* Restore new task contex */
/****************************************************************************
* 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
\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
/****************************************************************************
* Exception Vector Table
****************************************************************************/
-/* The Exception Vector Base Address (EVBA) register will contain "a pointer
- * to the exception routines. All exception routines start at this address,
- * or at a defined offset relative to the address. Special alignment
- * requirements may apply for EVBA, depending on the implementation of the
- * interrupt controller."
- */
+/* The Exception Vector Base Address (EVBA) register will contain "a */
+/* pointer to the exception routines. All exception routines start at this */
+/* address, or at a defined offset relative to the address. Special */
+/* alignment requirements may apply for EVBA, depending on the */
+/* 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 */
.text
.balign 0x200
@@ -80,85 +90,83 @@
.global vectortab
.type vectortab, @function
vectortab:
- lda.w pc, avr32_unrec /* EVBA+0x00 Unrecoverable exception */
- 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_businst /* EVBA+0x0c Bus error instruction fetch */
- lda.w pc, avr32_nmi /* EVBA+0x10 NMI */
- lda.w pc, avr32_instaddr /* EVBA+0x14 Instruction Address */
- lda.w pc, avr32_itlbrot /* EVBA+0x18 ITLB Protection */
- lda.w pc, avr32_bp /* EVBA+0x1c Breakpoint */
- lda.w pc, avr32_invinst /* EVBA+0x20 Illegal Opcode */
- lda.w pc, avr32_unimpinst /* EVBA+0x24 Unimplemented instruction */
- lda.w pc, avr32_priv /* EVBA+0x28 Privilege violation */
- lda.w pc, avr32_fp /* EVBA+0x2c Floating-point */
- lda.w pc, avr32_cop /* EVBA+0x30 Coprocessor absent */
- lda.w pc, avr32_rddata /* EVBA+0x34 Data Address (Read) */
- lda.w pc, avr32_wrdata /* EVBA+0x38 Data Address (Write) */
- lda.w pc, avr32_tddtlbprot /* EVBA+0x3c DTLB Protection (Read) */
- lda.w pc, avr32_wrdtlbprot /* EVBA+0x40 DTLB Protection (Write) */
- lda.w pc, avr32_dltbmod /* EVBA+0x44 DTLB Modified */
+ lda.w pc, avr32_unrec /* EVBA+0x00 Unrecoverable exception */
+ 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_businst /* EVBA+0x0c Bus error instr fetch */
+ lda.w pc, avr32_nmi /* EVBA+0x10 NMI */
+ lda.w pc, avr32_instaddr /* EVBA+0x14 Instruction Address */
+ lda.w pc, avr32_itlbrot /* EVBA+0x18 ITLB Protection */
+ lda.w pc, avr32_bp /* EVBA+0x1c Breakpoint */
+ lda.w pc, avr32_invinst /* EVBA+0x20 Illegal Opcode */
+ lda.w pc, avr32_unimpinst /* EVBA+0x24 Unimplemented instruction */
+ lda.w pc, avr32_priv /* EVBA+0x28 Privilege violation */
+ lda.w pc, avr32_fp /* EVBA+0x2c Floating-point */
+ lda.w pc, avr32_cop /* EVBA+0x30 Coprocessor absent */
+ lda.w pc, avr32_rddata /* EVBA+0x34 Data Address (Read) */
+ lda.w pc, avr32_wrdata /* EVBA+0x38 Data Address (Write) */
+ lda.w pc, avr32_tddtlbprot /* EVBA+0x3c DTLB Protection (Read) */
+ lda.w pc, avr32_wrdtlbprot /* EVBA+0x40 DTLB Protection (Write) */
+ lda.w pc, avr32_dltbmod /* EVBA+0x44 DTLB Modified */
.rept 2
- lda.w pc, avr32_badvector /* EVBA+0x48-0x4c No such vector */
+ lda.w pc, avr32_badvector /* EVBA+0x48-0x4c No such vector */
.endr
- lda.w pc, avr32_itlbmiss /* EVBA+0x50 ITLB Miss */
+ lda.w pc, avr32_itlbmiss /* EVBA+0x50 ITLB Miss */
.rept 3
- lda.w pc, avr32_badvector /* EVBA+0x54-0x5c No such vector */
+ lda.w pc, avr32_badvector /* EVBA+0x54-0x5c No such vector */
.endr
- lda.w pc, avr32_rddtlb /* EVBA+0x60 DTLB Miss (Read) */
+ lda.w pc, avr32_rddtlb /* EVBA+0x60 DTLB Miss (Read) */
.rept 3
- lda.w pc, avr32_badvector /* EVBA+0x64-0x6c No such vector */
+ lda.w pc, avr32_badvector /* EVBA+0x64-0x6c No such vector */
.endr
- lda.w pc, avr32_wrdtlb /* EVBA+0x70 DTLB Miss (Write) */
+ lda.w pc, avr32_wrdtlb /* EVBA+0x70 DTLB Miss (Write) */
.rept (3+4*8)
- lda.w pc, avr32_badvector /* EVBA+0x74-0xfc No such vector */
+ lda.w pc, avr32_badvector /* EVBA+0x74-0xfc No such vector */
.endr
- lda.w pc, avr32_super /* EVBA+0x100 Supervisor call */
+ lda.w pc, avr32_super /* EVBA+0x100 Supervisor call */
/****************************************************************************
* Interrupts
****************************************************************************/
-/* 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 exception table.
- * On entry to each interrupt handler, R8-R12, LR, PC and SR have already been
- * pushed onto the system stack by the MCU.
- *
- * An interrupt may disappear while it is being fetched by the CPU and, hence,
- * spurious interrupt may result.
- */
+/* 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 exception table. On entry to each interrupt handler, R8-R12, LR, PC */
+/* and SR have already been pushed onto the system stack by the MCU. */
+/* */
+/* An interrupt may disappear while it is being fetched by the CPU and, */
+/* hence spurious interrupt may result. */
.balign 4
.global avr32_int0
avr32_int0:
- mov r12, 0 /* r12=interrupt level 0 */
- rjmp avr32_intcommon /* Jump to common interrupt handling logic */
+ mov r12, 0 /* r12=interrupt level 0 */
+ rjmp avr32_intcommon /* Jump to common interrupt handling logic */
.balign 4
.global avr32_int1
avr32_int1:
- mov r12, 1 /* r12=interrupt level 1 */
- rjmp avr32_intcommon /* Jump to common interrupt handling logic */
+ mov r12, 1 /* r12=interrupt level 1 */
+ rjmp avr32_intcommon /* Jump to common interrupt handling logic */
.balign 4
.global avr32_int2
avr32_int2:
- mov r12, 2 /* r12=interrupt level 2 */
- rjmp avr32_intcommon /* Jump to common interrupt handling logic */
+ mov r12, 2 /* r12=interrupt level 2 */
+ rjmp avr32_intcommon /* Jump to common interrupt handling logic */
.balign 4
.global avr32_int3
avr32_int3:
- mov r12, 3 /* r12=interrupt level 3 */
+ mov r12, 3 /* r12=interrupt level 3 */
-/* Common interrupt handling logic. R12 holds the interrupt level index */
+/* Common interrupt handling logic. R12 holds the interrupt level index */
avr32_intcommon:
- mcall .Lavr32_intirqno /* Get the IRQ number of the int0 event */
- cp.w r12, 0 /* Negated errno returned if spurious interrupt */
- brge avr32_common /* Jump to the common exception handling logic */
- rete /* Ignore spurious interrupt */
+ mcall .Lavr32_intirqno /* Get the IRQ number of the int0 event */
+ cp.w r12, 0 /* Negative returned if spurious interrupt */
+ brge avr32_common /* Jump to the common xcptn handling logic */
+ rete /* Ignore spurious interrupt */
.Lavr32_intirqno:
.word avr32_intirqno
@@ -167,41 +175,79 @@ avr32_intcommon:
* 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_tlbmult, AVR32_IRQ_TLBMULT /* TLB multiple hit */
+ HANDLER avr32_unrec, AVR32_IRQ_UNREC /* Unrecoverable xcptn */
+ HANDLER avr32_tlbmult, AVR32_IRQ_TLBMULT /* TLB multiple hit */
HANDLER avr32_busdata, AVR32_IRQ_BUSDATA /* Bus error data fetch */
- HANDLER avr32_businst, AVR32_IRQ_BUSINST /* Bus error instruction fetch */
- HANDLER avr32_nmi, AVR32_IRQ_NMI /* NMI */
- HANDLER avr32_instaddr, AVR32_IRQ_INSTADDR /* Instruction Address */
- HANDLER avr32_itlbrot, AVR32_IRQ_ITLBPROT /* ITLB Protection */
- HANDLER avr32_bp, AVR32_IRQ_BP /* Breakpoint */
- HANDLER avr32_invinst, AVR32_IRQ_INVINST /* Illegal Opcode */
- HANDLER avr32_unimpinst, AVR32_IRQ_UNIMPINST /* Unimplemented instruction */
- HANDLER avr32_priv, AVR32_IRQ_PRIV /* Privilege violation */
- HANDLER avr32_fp, AVR32_IRQ_FP /* Floating-point */
- HANDLER avr32_cop, AVR32_IRQ_COP /* Coprocessor absent */
- HANDLER avr32_rddata, AVR32_IRQ_RDDATA /* Data Address (Read) */
- HANDLER avr32_wrdata, AVR32_IRQ_WRDATA /* Data Address (Write) */
- HANDLER avr32_tddtlbprot, AVR32_IRQ_RDDTLBPROT /* DTLB Protection (Read) */
- HANDLER avr32_wrdtlbprot, AVR32_IRQ_WRDTLBPROT /* DTLB Protection (Write) */
- HANDLER avr32_dltbmod, AVR32_IRQ_DLTBMOD /* DTLB Modified */
- HANDLER avr32_itlbmiss, AVR32_IRQ_ITLBMISS /* ITLB Miss */
- HANDLER avr32_rddtlb, AVR32_IRQ_RDDTLB /* DTLB Miss (Read) */
- HANDLER avr32_wrdtlb, AVR32_IRQ_WRDTLB /* DTLB Miss (Write) */
- HANDLER avr32_super, AVR32_IRQ_SUPER /* Supervisor call */
- HANDLER avr32_badvector, AVR32_IRQ_BADVECTOR /* No such vector */
-
-/* Common exception handling logic. Unlike the interrupt handlers, the
- * 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
- * loic creates a common stack frame for exception handlers prior to joining
- * to the common interrupt/exception logic below.
- */
-
-avr32_excptcommon:
-#warning "Missing Logic"
+ HANDLER avr32_businst, AVR32_IRQ_BUSINST /* Bus err instr fetch */
+ HANDLER avr32_nmi, AVR32_IRQ_NMI /* NMI */
+ HANDLER avr32_instaddr, AVR32_IRQ_INSTADDR /* Instruction Address */
+ HANDLER avr32_itlbrot, AVR32_IRQ_ITLBPROT /* ITLB Protection */
+ HANDLER avr32_bp, AVR32_IRQ_BP /* Breakpoint */
+ HANDLER avr32_invinst, AVR32_IRQ_INVINST /* Illegal Opcode */
+ HANDLER avr32_unimpinst, AVR32_IRQ_UNIMPINST /* Unimplemented intsr */
+ HANDLER avr32_priv, AVR32_IRQ_PRIV /* Privilege violation */
+ HANDLER avr32_fp, AVR32_IRQ_FP /* Floating-point */
+ HANDLER avr32_cop, AVR32_IRQ_COP /* Coprocessor absent */
+ HANDLER avr32_rddata, AVR32_IRQ_RDDATA /* Data Address (RD) */
+ HANDLER avr32_wrdata, AVR32_IRQ_WRDATA /* Data Address (WR) */
+ HANDLER avr32_tddtlbprot, AVR32_IRQ_RDDTLBPROT /* DTLB Protection (RD) */
+ HANDLER avr32_wrdtlbprot, AVR32_IRQ_WRDTLBPROT /* DTLB Protection (WR) */
+ HANDLER avr32_dltbmod, AVR32_IRQ_DLTBMOD /* DTLB Modified */
+ HANDLER avr32_itlbmiss, AVR32_IRQ_ITLBMISS /* ITLB Miss */
+ HANDLER avr32_rddtlb, AVR32_IRQ_RDDTLB /* DTLB Miss (RD) */
+ HANDLER avr32_wrdtlb, AVR32_IRQ_WRDTLB /* DTLB Miss (WR) */
+ HANDLER avr32_super, AVR32_IRQ_SUPER /* Supervisor call */
+ HANDLER avr32_badvector, AVR32_IRQ_BADVECTOR /* No such vector */
+
+/* Common exception handling logic. Unlike the interrupt handlers, the */
+/* 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 */
+/* logic creates a common stack frame for exception handlers prior to */
+/* 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_xcptcommon:
+/* 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
@@ -215,7 +261,7 @@ avr32_excptcommon:
/* */
/* The context save area looks like this: */
/* 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 */
/* and call the IRQ dispatching logic. */
@@ -256,12 +302,12 @@ avr32_common:
#if CONFIG_ARCH_INTERRUPTSTACK > 3
mov r7, sp
- lddpc sp, .Lup_instackbase
+ lddpc sp, .Linstackbaseptr
#endif
/* Call up_doirq with r12=IRQ number and r11=register save area */
- mcall .Lup_doirq
+ mcall .Ldoirqptr
/* Restore the user stack pointer. */
/* 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. */
1:
- lddpc pc, .Lup_fullcontextrestore
+ lddpc pc, .Lfullcontextrestoreptr
-.Lup_doirq:
+.Ldoirqptr:
.word up_doirq
-.Lup_fullcontextrestore:
+.Lfullcontextrestoreptr:
.word up_fullcontextrestore
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+.Linstackbaseptr:
+ .word .Lintstackbase
+#endif
+ .size vectortab, .-vectortab
+
/************************************************************************************
* Name: up_interruptstack
************************************************************************************/
@@ -314,11 +366,8 @@ avr32_common:
.type up_interruptstack, object
up_interruptstack:
.skip (CONFIG_ARCH_INTERRUPTSTACK & ~3)
-up_intstackbase:
+.Lintstackbase:
.size up_interruptstack, .-up_interruptstack
-.Lup_instackbase
- .word up_intstackbase
- .size .Lup_instackbase, .-.Lup_instackbase
#endif
.end