1st cut at lm3s6918 interrupt handling
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1776 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
0df1e24cc9
commit
2827157b5f
@ -48,7 +48,7 @@
|
|||||||
#include <arch/chip/irq.h>
|
#include <arch/chip/irq.h>
|
||||||
|
|
||||||
#ifdef __thumb2__
|
#ifdef __thumb2__
|
||||||
# include <arch/irq_thumb2.h>
|
# include <arch/irq_cortexm3.h>
|
||||||
#else
|
#else
|
||||||
# include <arch/irq_arm.h>
|
# include <arch/irq_arm.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* arch/arm/include/irq_thumb2.h
|
* arch/arm/include/irq_cortexm3.h
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2009 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||||
@ -57,14 +57,14 @@
|
|||||||
* registers on the stack in this (address) order:
|
* registers on the stack in this (address) order:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define REG_XPSR (16) /* xPSR */
|
#define REG_XPSR (17) /* xPSR */
|
||||||
#define REG_R15 (15) /* R15 = PC */
|
#define REG_R15 (16) /* R15 = PC */
|
||||||
#define REG_R14 (14) /* R14 = LR */
|
#define REG_R14 (15) /* R14 = LR */
|
||||||
#define REG_R12 (13) /* R12 */
|
#define REG_R12 (14) /* R12 */
|
||||||
#define REG_R3 (12) /* R3 */
|
#define REG_R3 (13) /* R3 */
|
||||||
#define REG_R2 (11) /* R2 */
|
#define REG_R2 (12) /* R2 */
|
||||||
#define REG_R1 (10) /* R1 */
|
#define REG_R1 (11) /* R1 */
|
||||||
#define REG_R0 (9) /* R0 */
|
#define REG_R0 (10) /* R0 */
|
||||||
|
|
||||||
#define HW_XCPT_REGS (8)
|
#define HW_XCPT_REGS (8)
|
||||||
#define HW_XCPT_SIZE (4 * HW_XCPT_REGS)
|
#define HW_XCPT_SIZE (4 * HW_XCPT_REGS)
|
||||||
@ -73,18 +73,22 @@
|
|||||||
* logic.
|
* logic.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define REG_R13 (8) /* R13 = SP at time of interrupt */
|
#define REG_R11 (9) /* R11 */
|
||||||
#define REG_R11 (7) /* R11 */
|
#define REG_R10 (8) /* R10 */
|
||||||
#define REG_R10 (6) /* R10 */
|
#define REG_R9 (7) /* R9 */
|
||||||
#define REG_R9 (5) /* R9 */
|
#define REG_R8 (6) /* R8 */
|
||||||
#define REG_R8 (4) /* R8 */
|
#define REG_R7 (5) /* R7 */
|
||||||
#define REG_R7 (3) /* R7 */
|
#define REG_R6 (4) /* R6 */
|
||||||
#define REG_R6 (2) /* R6 */
|
#define REG_R5 (3) /* R5 */
|
||||||
#define REG_R5 (1) /* R5 */
|
#define REG_R4 (2) /* R4 */
|
||||||
#define REG_R4 (0) /* R4 */
|
#define REG_PRIMASK (1) /* PRIMASK */
|
||||||
|
#define REG_R13 (0) /* R13 = SP at time of interrupt */
|
||||||
|
|
||||||
#define XCPTCONTEXT_REGS (17)
|
#define SW_XCPT_REGS (10)
|
||||||
#define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS)
|
#define SW_XCPT_SIZE (4 * SW_XCPT_REGS)
|
||||||
|
|
||||||
|
#define XCPTCONTEXT_REGS (HW_XCPT_REGS + SW_XCPT_REGS)
|
||||||
|
#define XCPTCONTEXT_SIZE (HW_XCPT_SIZE + SW_XCPT_SIZE)
|
||||||
|
|
||||||
#define REG_A1 REG_R0
|
#define REG_A1 REG_R0
|
||||||
#define REG_A2 REG_R1
|
#define REG_A2 REG_R1
|
||||||
@ -123,11 +127,12 @@ struct xcptcontext
|
|||||||
#ifndef CONFIG_DISABLE_SIGNALS
|
#ifndef CONFIG_DISABLE_SIGNALS
|
||||||
void *sigdeliver; /* Actual type is sig_deliver_t */
|
void *sigdeliver; /* Actual type is sig_deliver_t */
|
||||||
|
|
||||||
/* These are saved copies of LR and CPSR used during
|
/* These are saved copies of LR, PRIMASK, and xPSR used during
|
||||||
* signal processing.
|
* signal processing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uint32 saved_pc;
|
uint32 saved_pc;
|
||||||
|
uint32 saved_primask;
|
||||||
uint32 saved_xpsr;
|
uint32 saved_xpsr;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -134,7 +134,8 @@ static inline void up_registerdump(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __thumb2__
|
#ifdef __thumb2__
|
||||||
lldbg("xPSR: %08x\n", current_regs[REG_XPSR]);
|
lldbg("xPSR: %08x PRIMASK: %08x\n",
|
||||||
|
current_regs[REG_XPSR], current_regs[REG_PRIMASK]);
|
||||||
#else
|
#else
|
||||||
lldbg("CPSR: %08x\n", current_regs[REG_CPSR]);
|
lldbg("CPSR: %08x\n", current_regs[REG_CPSR]);
|
||||||
#endif
|
#endif
|
||||||
|
@ -81,11 +81,18 @@ void up_initial_state(_TCB *tcb)
|
|||||||
/* Initialize the initial exception register context structure */
|
/* Initialize the initial exception register context structure */
|
||||||
|
|
||||||
memset(xcp, 0, sizeof(struct xcptcontext));
|
memset(xcp, 0, sizeof(struct xcptcontext));
|
||||||
xcp->regs[REG_SP] = (uint32)tcb->adj_stack_ptr;
|
xcp->regs[REG_SP] = (uint32)tcb->adj_stack_ptr;
|
||||||
xcp->regs[REG_PC] = (uint32)tcb->start;
|
xcp->regs[REG_PC] = (uint32)tcb->start;
|
||||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
|
||||||
xcp->regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT;
|
#ifdef __thumb2__
|
||||||
|
# ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||||
|
xcp->regs[REG_PRIMASK] = 1;
|
||||||
|
# endif
|
||||||
#else
|
#else
|
||||||
xcp->regs[REG_CPSR] = SVC_MODE | PSR_F_BIT;
|
# ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||||
|
xcp->regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT;
|
||||||
|
# else
|
||||||
|
xcp->regs[REG_CPSR] = SVC_MODE | PSR_F_BIT;
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -146,16 +146,26 @@ void up_schedule_sigaction(_TCB *tcb, sig_deliver_t sigdeliver)
|
|||||||
* the signals have been delivered.
|
* the signals have been delivered.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tcb->xcp.sigdeliver = sigdeliver;
|
tcb->xcp.sigdeliver = sigdeliver;
|
||||||
tcb->xcp.saved_pc = current_regs[REG_PC];
|
tcb->xcp.saved_pc = current_regs[REG_PC];
|
||||||
tcb->xcp.saved_cpsr = current_regs[REG_CPSR];
|
#ifdef __thumb2__
|
||||||
|
tcb->xcp.saved_primask = current_regs[REG_PRIMASK];
|
||||||
|
tcb->xcp.saved_xpsr = current_regs[REG_XPSR];
|
||||||
|
#else
|
||||||
|
tcb->xcp.saved_cpsr = current_regs[REG_CPSR];
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Then set up to vector to the trampoline with interrupts
|
/* Then set up to vector to the trampoline with interrupts
|
||||||
* disabled
|
* disabled
|
||||||
*/
|
*/
|
||||||
|
|
||||||
current_regs[REG_PC] = (uint32)up_sigdeliver;
|
current_regs[REG_PC] = (uint32)up_sigdeliver;
|
||||||
current_regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT;
|
#ifdef __thumb2__
|
||||||
|
current_regs[REG_PRIMASK] = 1;
|
||||||
|
current_regs[REG_XPSR] = 0;
|
||||||
|
#else
|
||||||
|
current_regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* And make sure that the saved context in the TCB
|
/* And make sure that the saved context in the TCB
|
||||||
* is the same as the interrupt return context.
|
* is the same as the interrupt return context.
|
||||||
@ -178,16 +188,26 @@ void up_schedule_sigaction(_TCB *tcb, sig_deliver_t sigdeliver)
|
|||||||
* the signals have been delivered.
|
* the signals have been delivered.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tcb->xcp.sigdeliver = sigdeliver;
|
tcb->xcp.sigdeliver = sigdeliver;
|
||||||
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
|
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
|
||||||
tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR];
|
#ifdef __thumb2__
|
||||||
|
tcb->xcp.saved_primask = tcb->xcp.regs[REG_PRIMASK];
|
||||||
|
tcb->xcp.saved_xpsr = tcb->xcp.regs[REG_XPSR];
|
||||||
|
#else
|
||||||
|
tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR];
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Then set up to vector to the trampoline with interrupts
|
/* Then set up to vector to the trampoline with interrupts
|
||||||
* disabled
|
* disabled
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tcb->xcp.regs[REG_PC] = (uint32)up_sigdeliver;
|
tcb->xcp.regs[REG_PC] = (uint32)up_sigdeliver;
|
||||||
tcb->xcp.regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT;
|
#ifdef __thumb2__
|
||||||
|
tcb->xcp.regs[REG_PRIMASK] = 1;
|
||||||
|
tcb->xcp.regs[REG_XPSR] = 0;
|
||||||
|
#else
|
||||||
|
tcb->xcp.regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
irqrestore(flags);
|
irqrestore(flags);
|
||||||
|
@ -102,9 +102,13 @@ void up_sigdeliver(void)
|
|||||||
/* Save the real return state on the stack. */
|
/* Save the real return state on the stack. */
|
||||||
|
|
||||||
up_copystate(regs, rtcb->xcp.regs);
|
up_copystate(regs, rtcb->xcp.regs);
|
||||||
regs[REG_PC] = rtcb->xcp.saved_pc;
|
regs[REG_PC] = rtcb->xcp.saved_pc;
|
||||||
regs[REG_CPSR] = rtcb->xcp.saved_cpsr;
|
#ifdef __thumb2__
|
||||||
|
regs[REG_PRIMASK] = rtcb->xcp.saved_primask;
|
||||||
|
regs[REG_XPSR] = rtcb->xcp.saved_xpsr;
|
||||||
|
#else
|
||||||
|
regs[REG_CPSR] = rtcb->xcp.saved_cpsr;
|
||||||
|
#endif
|
||||||
/* Get a local copy of the sigdeliver function pointer.
|
/* Get a local copy of the sigdeliver function pointer.
|
||||||
* we do this so that we can nullify the sigdeliver
|
* we do this so that we can nullify the sigdeliver
|
||||||
* function point in the TCB and accept more signal
|
* function point in the TCB and accept more signal
|
||||||
@ -117,7 +121,11 @@ void up_sigdeliver(void)
|
|||||||
|
|
||||||
/* Then restore the task interrupt statat. */
|
/* Then restore the task interrupt statat. */
|
||||||
|
|
||||||
|
#ifdef __thumb2__
|
||||||
|
irqrestore((uint16)regs[REG_PRIMASK]);
|
||||||
|
#else
|
||||||
irqrestore(regs[REG_CPSR]);
|
irqrestore(regs[REG_CPSR]);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Deliver the signals */
|
/* Deliver the signals */
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
#include <arch/irq.h>
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Preprocessor Definitions
|
* Preprocessor Definitions
|
||||||
@ -64,6 +65,10 @@
|
|||||||
|
|
||||||
.globl dispach_irq
|
.globl dispach_irq
|
||||||
|
|
||||||
|
.syntax unified
|
||||||
|
.thumb
|
||||||
|
.file "lm3s_vectors.S"
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Macros
|
* Macros
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
@ -76,8 +81,8 @@
|
|||||||
|
|
||||||
.macro HANDLER, label, irqno
|
.macro HANDLER, label, irqno
|
||||||
\label:
|
\label:
|
||||||
mov r0, \irqno
|
mov r0, #\irqno
|
||||||
br lm3s_irqcommon
|
b lm3s_irqcommon
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
@ -86,7 +91,7 @@
|
|||||||
|
|
||||||
.section .vectors, "ax"
|
.section .vectors, "ax"
|
||||||
.code 16
|
.code 16
|
||||||
.align 0
|
.align 2
|
||||||
.globl lm3s_vectors
|
.globl lm3s_vectors
|
||||||
.type lm3s_vectors, function
|
.type lm3s_vectors, function
|
||||||
|
|
||||||
@ -177,7 +182,6 @@ lm3s_vectors:
|
|||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
.text
|
.text
|
||||||
.thumb_func
|
|
||||||
.type handlers, function
|
.type handlers, function
|
||||||
handlers:
|
handlers:
|
||||||
HANDLER lm3s_reserved, LMSB_IRQ_RESERVED /* Unexpected/reserved vector */
|
HANDLER lm3s_reserved, LMSB_IRQ_RESERVED /* Unexpected/reserved vector */
|
||||||
@ -194,8 +198,8 @@ handlers:
|
|||||||
#ifdef CONFIG_ARCH_CHIP_LM3S6918
|
#ifdef CONFIG_ARCH_CHIP_LM3S6918
|
||||||
HANDLER lm3s_gpioa, LM3S_IRQ_GPIOA /* Vector 16: GPIO Port A */
|
HANDLER lm3s_gpioa, LM3S_IRQ_GPIOA /* Vector 16: GPIO Port A */
|
||||||
HANDLER lm3s_gpiob, LM3S_IRQ_GPIOB /* Vector 17: GPIO Port B */
|
HANDLER lm3s_gpiob, LM3S_IRQ_GPIOB /* Vector 17: GPIO Port B */
|
||||||
HANDLER lm3s_gpiod, LM3S_IRQ_GPIOC /* Vector 18: GPIO Port C */
|
HANDLER lm3s_gpioc, LM3S_IRQ_GPIOC /* Vector 18: GPIO Port C */
|
||||||
HANDLER lm3s_gpioe, LM3S_IRQ_GPIOD /* Vector 19: GPIO Port D */
|
HANDLER lm3s_gpiod, LM3S_IRQ_GPIOD /* Vector 19: GPIO Port D */
|
||||||
HANDLER lm3s_gpioe, LM3S_IRQ_GPIOE /* Vector 20: GPIO Port E */
|
HANDLER lm3s_gpioe, LM3S_IRQ_GPIOE /* Vector 20: GPIO Port E */
|
||||||
HANDLER lm3s_uart0, LM3S_IRQ_UART0 /* Vector 21: UART 0 */
|
HANDLER lm3s_uart0, LM3S_IRQ_UART0 /* Vector 21: UART 0 */
|
||||||
HANDLER lm3s_uart1, LM3S_IRQ_UART1 /* Vector 22: UART 1 */
|
HANDLER lm3s_uart1, LM3S_IRQ_UART1 /* Vector 22: UART 1 */
|
||||||
@ -248,9 +252,10 @@ lm3s_irqcommon:
|
|||||||
/* Complete the context save */
|
/* Complete the context save */
|
||||||
|
|
||||||
mrs r1, psp /* R1=The process stack pointer */
|
mrs r1, psp /* R1=The process stack pointer */
|
||||||
mov r3, r1 /* R3=Copy of the process stack pointer */
|
mov r2, r1 /* R2=Copy of the process stack pointer */
|
||||||
add r3, #HW_XCPT_SIZE /* R3=PSP before the interrupt was taken */
|
add r2, #HW_XCPT_SIZE /* R2=PSP before the interrupt was taken */
|
||||||
stmdb r1!, {r3-r11} /* Save the remaining registers plus the SP value */
|
mrs r3, primask /* R3=Current PRIMASK setting */
|
||||||
|
stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */
|
||||||
|
|
||||||
/* Disable interrupts, select the stack to use for interrupt handling
|
/* Disable interrupts, select the stack to use for interrupt handling
|
||||||
* and call up_doirq to handle the interrupt
|
* and call up_doirq to handle the interrupt
|
||||||
@ -286,15 +291,21 @@ lm3s_irqcommon:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
add r1, r0, #(XCPTCONTEXT_SIZE-4) /* r2=offset HW save area */
|
add r1, r0, #(XCPTCONTEXT_SIZE-4) /* r2=offset HW save area */
|
||||||
ldmia r1, {r4, r11} /* Eight registers in HW save area */
|
ldmia r1, {r4-r11} /* Eight registers in HW save area */
|
||||||
ldr r1, [r0, #(4*REG_SP)] /* R1=Value of SP before interrupt */
|
ldr r1, [r0, #(4*REG_SP)] /* R1=Value of SP before interrupt */
|
||||||
stmdb r1!, {r4, r11} /* Eight registers in HW save area */
|
stmdb r1!, {r4-r11} /* Eight registers in HW save area */
|
||||||
mov psp, r1 /* New PSP */
|
msr psp, r1 /* New PSP */
|
||||||
|
|
||||||
/* We simply need to "unwind" the same stack frame that we created */
|
/* We simply need to "unwind" the same stack frame that we created */
|
||||||
1:
|
1:
|
||||||
|
stmdb r0!, {r2-r11} /* Recover R4-R11 + 2 temp values */
|
||||||
|
|
||||||
|
/* Do we need to restore interrupts? */
|
||||||
|
|
||||||
|
tst r3, #1 /* PRIMASK it 1=1 means that interrupts are masked */
|
||||||
|
bne 2f
|
||||||
cpsie i /* Restore interrupts */
|
cpsie i /* Restore interrupts */
|
||||||
stmdb r0!, {r3-r11} /* Recover R4-R11 (R3 does not have the correct value yet) * the remaining registers plus the SP value */
|
2:
|
||||||
bx r14 /* And return */
|
bx r14 /* And return */
|
||||||
.size handler, .-handlers
|
.size handler, .-handlers
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user