diff --git a/arch/arm/include/irq.h b/arch/arm/include/irq.h index 1d2c3e1225..dabd35f418 100644 --- a/arch/arm/include/irq.h +++ b/arch/arm/include/irq.h @@ -48,7 +48,7 @@ #include #ifdef __thumb2__ -# include +# include #else # include #endif diff --git a/arch/arm/include/irq_thumb2.h b/arch/arm/include/irq_cortexm3.h similarity index 83% rename from arch/arm/include/irq_thumb2.h rename to arch/arm/include/irq_cortexm3.h index e138c157a0..a6c235811d 100644 --- a/arch/arm/include/irq_thumb2.h +++ b/arch/arm/include/irq_cortexm3.h @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/arm/include/irq_thumb2.h + * arch/arm/include/irq_cortexm3.h * * Copyright (C) 2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt @@ -57,14 +57,14 @@ * registers on the stack in this (address) order: */ -#define REG_XPSR (16) /* xPSR */ -#define REG_R15 (15) /* R15 = PC */ -#define REG_R14 (14) /* R14 = LR */ -#define REG_R12 (13) /* R12 */ -#define REG_R3 (12) /* R3 */ -#define REG_R2 (11) /* R2 */ -#define REG_R1 (10) /* R1 */ -#define REG_R0 (9) /* R0 */ +#define REG_XPSR (17) /* xPSR */ +#define REG_R15 (16) /* R15 = PC */ +#define REG_R14 (15) /* R14 = LR */ +#define REG_R12 (14) /* R12 */ +#define REG_R3 (13) /* R3 */ +#define REG_R2 (12) /* R2 */ +#define REG_R1 (11) /* R1 */ +#define REG_R0 (10) /* R0 */ #define HW_XCPT_REGS (8) #define HW_XCPT_SIZE (4 * HW_XCPT_REGS) @@ -73,18 +73,22 @@ * logic. */ -#define REG_R13 (8) /* R13 = SP at time of interrupt */ -#define REG_R11 (7) /* R11 */ -#define REG_R10 (6) /* R10 */ -#define REG_R9 (5) /* R9 */ -#define REG_R8 (4) /* R8 */ -#define REG_R7 (3) /* R7 */ -#define REG_R6 (2) /* R6 */ -#define REG_R5 (1) /* R5 */ -#define REG_R4 (0) /* R4 */ +#define REG_R11 (9) /* R11 */ +#define REG_R10 (8) /* R10 */ +#define REG_R9 (7) /* R9 */ +#define REG_R8 (6) /* R8 */ +#define REG_R7 (5) /* R7 */ +#define REG_R6 (4) /* R6 */ +#define REG_R5 (3) /* R5 */ +#define REG_R4 (2) /* R4 */ +#define REG_PRIMASK (1) /* PRIMASK */ +#define REG_R13 (0) /* R13 = SP at time of interrupt */ -#define XCPTCONTEXT_REGS (17) -#define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS) +#define SW_XCPT_REGS (10) +#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_A2 REG_R1 @@ -123,11 +127,12 @@ struct xcptcontext #ifndef CONFIG_DISABLE_SIGNALS 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. */ uint32 saved_pc; + uint32 saved_primask; uint32 saved_xpsr; #endif diff --git a/arch/arm/src/common/up_assert.c b/arch/arm/src/common/up_assert.c index 8460c6b713..88dd0bd498 100644 --- a/arch/arm/src/common/up_assert.c +++ b/arch/arm/src/common/up_assert.c @@ -134,7 +134,8 @@ static inline void up_registerdump(void) } #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 lldbg("CPSR: %08x\n", current_regs[REG_CPSR]); #endif diff --git a/arch/arm/src/common/up_initialstate.c b/arch/arm/src/common/up_initialstate.c index 2dd1695ba4..a945b4c518 100644 --- a/arch/arm/src/common/up_initialstate.c +++ b/arch/arm/src/common/up_initialstate.c @@ -81,11 +81,18 @@ void up_initial_state(_TCB *tcb) /* Initialize the initial exception register context structure */ memset(xcp, 0, sizeof(struct xcptcontext)); - xcp->regs[REG_SP] = (uint32)tcb->adj_stack_ptr; - xcp->regs[REG_PC] = (uint32)tcb->start; -#ifdef CONFIG_SUPPRESS_INTERRUPTS - xcp->regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT; + xcp->regs[REG_SP] = (uint32)tcb->adj_stack_ptr; + xcp->regs[REG_PC] = (uint32)tcb->start; + +#ifdef __thumb2__ +# ifdef CONFIG_SUPPRESS_INTERRUPTS + xcp->regs[REG_PRIMASK] = 1; +# endif #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 } diff --git a/arch/arm/src/common/up_schedulesigaction.c b/arch/arm/src/common/up_schedulesigaction.c index 36be3eb244..fb6798468e 100644 --- a/arch/arm/src/common/up_schedulesigaction.c +++ b/arch/arm/src/common/up_schedulesigaction.c @@ -146,16 +146,26 @@ void up_schedule_sigaction(_TCB *tcb, sig_deliver_t sigdeliver) * the signals have been delivered. */ - tcb->xcp.sigdeliver = sigdeliver; - tcb->xcp.saved_pc = current_regs[REG_PC]; - tcb->xcp.saved_cpsr = current_regs[REG_CPSR]; + tcb->xcp.sigdeliver = sigdeliver; + tcb->xcp.saved_pc = current_regs[REG_PC]; +#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 * disabled */ - current_regs[REG_PC] = (uint32)up_sigdeliver; - current_regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT; + current_regs[REG_PC] = (uint32)up_sigdeliver; +#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 * 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. */ - tcb->xcp.sigdeliver = sigdeliver; - tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; - tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR]; + tcb->xcp.sigdeliver = sigdeliver; + tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; +#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 * disabled */ - tcb->xcp.regs[REG_PC] = (uint32)up_sigdeliver; - tcb->xcp.regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT; + tcb->xcp.regs[REG_PC] = (uint32)up_sigdeliver; +#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); diff --git a/arch/arm/src/common/up_sigdeliver.c b/arch/arm/src/common/up_sigdeliver.c index 16227ae21b..bf56616961 100644 --- a/arch/arm/src/common/up_sigdeliver.c +++ b/arch/arm/src/common/up_sigdeliver.c @@ -102,9 +102,13 @@ void up_sigdeliver(void) /* Save the real return state on the stack. */ up_copystate(regs, rtcb->xcp.regs); - regs[REG_PC] = rtcb->xcp.saved_pc; - regs[REG_CPSR] = rtcb->xcp.saved_cpsr; - + regs[REG_PC] = rtcb->xcp.saved_pc; +#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. * we do this so that we can nullify the sigdeliver * function point in the TCB and accept more signal @@ -117,7 +121,11 @@ void up_sigdeliver(void) /* Then restore the task interrupt statat. */ +#ifdef __thumb2__ + irqrestore((uint16)regs[REG_PRIMASK]); +#else irqrestore(regs[REG_CPSR]); +#endif /* Deliver the signals */ diff --git a/arch/arm/src/lm3s/lm3s_vectors.S b/arch/arm/src/lm3s/lm3s_vectors.S index 3f196ae921..c17a387ae6 100644 --- a/arch/arm/src/lm3s/lm3s_vectors.S +++ b/arch/arm/src/lm3s/lm3s_vectors.S @@ -38,6 +38,7 @@ ************************************************************************************/ #include +#include /************************************************************************************ * Preprocessor Definitions @@ -64,6 +65,10 @@ .globl dispach_irq + .syntax unified + .thumb + .file "lm3s_vectors.S" + /************************************************************************************ * Macros ************************************************************************************/ @@ -76,8 +81,8 @@ .macro HANDLER, label, irqno \label: - mov r0, \irqno - br lm3s_irqcommon + mov r0, #\irqno + b lm3s_irqcommon .endm /************************************************************************************ @@ -86,7 +91,7 @@ .section .vectors, "ax" .code 16 - .align 0 + .align 2 .globl lm3s_vectors .type lm3s_vectors, function @@ -177,7 +182,6 @@ lm3s_vectors: ************************************************************************************/ .text - .thumb_func .type handlers, function handlers: HANDLER lm3s_reserved, LMSB_IRQ_RESERVED /* Unexpected/reserved vector */ @@ -194,8 +198,8 @@ handlers: #ifdef CONFIG_ARCH_CHIP_LM3S6918 HANDLER lm3s_gpioa, LM3S_IRQ_GPIOA /* Vector 16: GPIO Port A */ HANDLER lm3s_gpiob, LM3S_IRQ_GPIOB /* Vector 17: GPIO Port B */ - HANDLER lm3s_gpiod, LM3S_IRQ_GPIOC /* Vector 18: GPIO Port C */ - HANDLER lm3s_gpioe, LM3S_IRQ_GPIOD /* Vector 19: GPIO Port D */ + HANDLER lm3s_gpioc, LM3S_IRQ_GPIOC /* Vector 18: GPIO Port C */ + HANDLER lm3s_gpiod, LM3S_IRQ_GPIOD /* Vector 19: GPIO Port D */ HANDLER lm3s_gpioe, LM3S_IRQ_GPIOE /* Vector 20: GPIO Port E */ HANDLER lm3s_uart0, LM3S_IRQ_UART0 /* Vector 21: UART 0 */ HANDLER lm3s_uart1, LM3S_IRQ_UART1 /* Vector 22: UART 1 */ @@ -248,9 +252,10 @@ lm3s_irqcommon: /* Complete the context save */ mrs r1, psp /* R1=The process stack pointer */ - mov r3, r1 /* R3=Copy of the process stack pointer */ - add r3, #HW_XCPT_SIZE /* R3=PSP before the interrupt was taken */ - stmdb r1!, {r3-r11} /* Save the remaining registers plus the SP value */ + mov r2, r1 /* R2=Copy of the process stack pointer */ + add r2, #HW_XCPT_SIZE /* R2=PSP before the interrupt was taken */ + 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 * 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 */ - 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 */ - stmdb r1!, {r4, r11} /* Eight registers in HW save area */ - mov psp, r1 /* New PSP */ + stmdb r1!, {r4-r11} /* Eight registers in HW save area */ + msr psp, r1 /* New PSP */ /* We simply need to "unwind" the same stack frame that we created */ 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 */ - 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 */ .size handler, .-handlers