diff --git a/arch/arm/src/armv6-m/arm_doirq.c b/arch/arm/src/armv6-m/arm_doirq.c index 3065a4f4da..93703b4512 100644 --- a/arch/arm/src/armv6-m/arm_doirq.c +++ b/arch/arm/src/armv6-m/arm_doirq.c @@ -35,11 +35,25 @@ #include "arm_internal.h" #include "exc_return.h" +#include "nvic.h" /**************************************************************************** * Public Functions ****************************************************************************/ +void exception_direct(void) +{ + int irq = getipsr(); + + arm_ack_irq(irq); + irq_dispatch(irq, NULL); + + if (g_running_tasks[this_cpu()] != this_task()) + { + up_trigger_irq(NVIC_IRQ_PENDSV, 0); + } +} + uint32_t *arm_doirq(int irq, uint32_t *regs) { struct tcb_s *tcb = this_task(); @@ -49,19 +63,20 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) PANIC(); #else - if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE) - { - tcb->xcp.regs = regs; - up_set_current_regs(regs); - } - /* Acknowledge the interrupt */ arm_ack_irq(irq); - /* Deliver the IRQ */ - - irq_dispatch(irq, regs); + if (irq == NVIC_IRQ_PENDSV) + { + up_irq_save(); + g_running_tasks[this_cpu()]->xcp.regs = regs; + } + else + { + tcb->xcp.regs = regs; + irq_dispatch(irq, regs); + } /* If a context switch occurred while processing the interrupt then * current_regs may have change value. If we return any value different @@ -69,30 +84,20 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) * switch occurred during interrupt processing. */ - if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE) - { - tcb = this_task(); + tcb = this_task(); - if (regs != tcb->xcp.regs) - { - /* Update scheduler parameters */ + /* Update scheduler parameters */ - nxsched_suspend_scheduler(g_running_tasks[this_cpu()]); - nxsched_resume_scheduler(tcb); + nxsched_suspend_scheduler(g_running_tasks[this_cpu()]); + nxsched_resume_scheduler(tcb); - /* Record the new "running" task when context switch occurred. - * g_running_tasks[] is only used by assertion logic for reporting - * crashes. - */ + /* Record the new "running" task when context switch occurred. + * g_running_tasks[] is only used by assertion logic for reporting + * crashes. + */ - g_running_tasks[this_cpu()] = tcb; - regs = tcb->xcp.regs; - } - - /* Update the current_regs to NULL. */ - - up_set_current_regs(NULL); - } + g_running_tasks[this_cpu()] = tcb; + regs = tcb->xcp.regs; #endif board_autoled_off(LED_INIRQ); diff --git a/arch/arm/src/armv6-m/arm_svcall.c b/arch/arm/src/armv6-m/arm_svcall.c index 62f57e302a..bab2404669 100644 --- a/arch/arm/src/armv6-m/arm_svcall.c +++ b/arch/arm/src/armv6-m/arm_svcall.c @@ -121,7 +121,6 @@ int arm_svcall(int irq, void *context, void *arg) uint32_t *regs = (uint32_t *)context; uint32_t cmd; - DEBUGASSERT(regs && regs == up_current_regs()); cmd = regs[REG_R0]; /* The SVCall software interrupt is called with R0 = system call command diff --git a/arch/arm/src/armv6-m/arm_vectors.c b/arch/arm/src/armv6-m/arm_vectors.c index 8beb9443c1..dbb336ae15 100644 --- a/arch/arm/src/armv6-m/arm_vectors.c +++ b/arch/arm/src/armv6-m/arm_vectors.c @@ -45,6 +45,8 @@ #include "chip.h" #include "arm_internal.h" +#include "ram_vectors.h" +#include "nvic.h" /**************************************************************************** * Pre-processor Definitions @@ -81,6 +83,7 @@ static void start(void) /* Common exception entrypoint */ extern void exception_common(void); +extern void exception_direct(void); /**************************************************************************** * Public data @@ -92,7 +95,7 @@ extern void exception_common(void); * As all exceptions (interrupts) are routed via exception_common, we just * need to fill this array with pointers to it. * - * Note that the [ ... ] designated initialiser is a GCC extension. + * Note that the [ ... ] designated initializer is a GCC extension. */ const void * const _vectors[] locate_data(".vectors") = @@ -107,5 +110,7 @@ const void * const _vectors[] locate_data(".vectors") = /* Vectors 2 - n point directly at the generic handler */ - [2 ... (15 + ARMV6M_PERIPHERAL_INTERRUPTS)] = exception_common + [2 ... NVIC_IRQ_PENDSV] = &exception_common, + [(NVIC_IRQ_PENDSV + 1) ... (15 + ARMV6M_PERIPHERAL_INTERRUPTS)] + = &exception_direct }; diff --git a/arch/arm/src/armv7-m/arm_doirq.c b/arch/arm/src/armv7-m/arm_doirq.c index 5c31de792e..b74414c59a 100644 --- a/arch/arm/src/armv7-m/arm_doirq.c +++ b/arch/arm/src/armv7-m/arm_doirq.c @@ -35,11 +35,25 @@ #include "arm_internal.h" #include "exc_return.h" +#include "nvic.h" /**************************************************************************** * Public Functions ****************************************************************************/ +void exception_direct(void) +{ + int irq = getipsr(); + + arm_ack_irq(irq); + irq_dispatch(irq, NULL); + + if (g_running_tasks[this_cpu()] != this_task()) + { + up_trigger_irq(NVIC_IRQ_PENDSV, 0); + } +} + uint32_t *arm_doirq(int irq, uint32_t *regs) { struct tcb_s *tcb = this_task(); @@ -49,19 +63,20 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) PANIC(); #else - if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE) - { - tcb->xcp.regs = regs; - up_set_current_regs(regs); - } - /* Acknowledge the interrupt */ arm_ack_irq(irq); - /* Deliver the IRQ */ - - irq_dispatch(irq, regs); + if (irq == NVIC_IRQ_PENDSV) + { + up_irq_save(); + g_running_tasks[this_cpu()]->xcp.regs = regs; + } + else + { + tcb->xcp.regs = regs; + irq_dispatch(irq, regs); + } /* If a context switch occurred while processing the interrupt then * current_regs may have change value. If we return any value different @@ -69,30 +84,20 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) * switch occurred during interrupt processing. */ - if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE) - { - tcb = this_task(); + tcb = this_task(); - if (regs != tcb->xcp.regs) - { - /* Update scheduler parameters */ + /* Update scheduler parameters */ - nxsched_suspend_scheduler(g_running_tasks[this_cpu()]); - nxsched_resume_scheduler(tcb); + nxsched_suspend_scheduler(g_running_tasks[this_cpu()]); + nxsched_resume_scheduler(tcb); - /* Record the new "running" task when context switch occurred. - * g_running_tasks[] is only used by assertion logic for reporting - * crashes. - */ + /* Record the new "running" task when context switch occurred. + * g_running_tasks[] is only used by assertion logic for reporting + * crashes. + */ - g_running_tasks[this_cpu()] = tcb; - regs = tcb->xcp.regs; - } - - /* Update the current_regs to NULL. */ - - up_set_current_regs(NULL); - } + g_running_tasks[this_cpu()] = tcb; + regs = tcb->xcp.regs; #endif board_autoled_off(LED_INIRQ); diff --git a/arch/arm/src/armv7-m/arm_svcall.c b/arch/arm/src/armv7-m/arm_svcall.c index 6c6f507aec..bfa2dc59f8 100644 --- a/arch/arm/src/armv7-m/arm_svcall.c +++ b/arch/arm/src/armv7-m/arm_svcall.c @@ -129,7 +129,6 @@ int arm_svcall(int irq, void *context, void *arg) uint32_t *regs = (uint32_t *)context; uint32_t cmd; - DEBUGASSERT(regs && regs == up_current_regs()); cmd = regs[REG_R0]; /* The SVCall software interrupt is called with R0 = system call command @@ -299,8 +298,9 @@ int arm_svcall(int irq, void *context, void *arg) * At this point, the following values are saved in context: * * R0 = SYS_pthread_start - * R1 = entrypt - * R2 = arg + * R1 = startup (trampoline) + * R2 = entrypt + * R3 = arg */ #if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD) diff --git a/arch/arm/src/armv7-m/arm_vectors.c b/arch/arm/src/armv7-m/arm_vectors.c index c4674ab20f..f007d021f0 100644 --- a/arch/arm/src/armv7-m/arm_vectors.c +++ b/arch/arm/src/armv7-m/arm_vectors.c @@ -41,6 +41,7 @@ #include "chip.h" #include "arm_internal.h" #include "ram_vectors.h" +#include "nvic.h" /**************************************************************************** * Pre-processor Definitions @@ -71,6 +72,7 @@ static void start(void) /* Common exception entrypoint */ extern void exception_common(void); +extern void exception_direct(void); /**************************************************************************** * Public data @@ -98,5 +100,7 @@ const void * const _vectors[] locate_data(".vectors") /* Vectors 2 - n point directly at the generic handler */ - [2 ... (15 + ARMV7M_PERIPHERAL_INTERRUPTS)] = exception_common + [2 ... NVIC_IRQ_PENDSV] = &exception_common, + [(NVIC_IRQ_PENDSV + 1) ... (15 + ARMV7M_PERIPHERAL_INTERRUPTS)] + = &exception_direct }; diff --git a/arch/arm/src/armv8-m/arm_doirq.c b/arch/arm/src/armv8-m/arm_doirq.c index 3e2fe2e961..536d7c4e75 100644 --- a/arch/arm/src/armv8-m/arm_doirq.c +++ b/arch/arm/src/armv8-m/arm_doirq.c @@ -35,60 +35,25 @@ #include "arm_internal.h" #include "exc_return.h" - -/**************************************************************************** - * Inline Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: arm_from_thread - * - * Description: - * If not defined CONFIG_ARCH_HAVE_TRUSTZONE - * Return true if interrupt return to thread mode, false otherwise. - * - * If defined CONFIG_ARCH_HAVE_TRUSTZONE - * Return true if interrupt return to thread mode, or if it is the first - * interrupt from TEE to REE, or REE to TEE, false otherwise. - * - * Interrupt nesting between TEE and REE can be determined based - * on the S and ES bits of EXC_RETURN - * If TEE interrupts REE, then EXC_RETURN.S=0, EXC_RETURN.ES=1; - * Conversely, EXC_RETURN.S=1, EXC_RETURN.ES=0. - * - * But only one level nesting between TEE and REE is supported, and - * recursive nesting between TEE and REE is not supported. - * - ****************************************************************************/ - -static inline bool arm_from_thread(uint32_t excret) -{ - if (excret & EXC_RETURN_THREAD_MODE) - { - return true; - } - -#if defined(CONFIG_ARCH_TRUSTZONE_SECURE) - if (!(excret & EXC_RETURN_SECURE_STACK) && - (excret & EXC_RETURN_EXC_SECURE)) - { - return true; - } - - if (!(excret & EXC_RETURN_EXC_SECURE) && - (excret & EXC_RETURN_SECURE_STACK)) - { - return true; - } -#endif - - return false; -} +#include "nvic.h" /**************************************************************************** * Public Functions ****************************************************************************/ +void exception_direct(void) +{ + int irq = getipsr(); + + arm_ack_irq(irq); + irq_dispatch(irq, NULL); + + if (g_running_tasks[this_cpu()] != this_task()) + { + up_trigger_irq(NVIC_IRQ_PENDSV, 0); + } +} + uint32_t *arm_doirq(int irq, uint32_t *regs) { struct tcb_s *tcb = this_task(); @@ -98,19 +63,20 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) PANIC(); #else - if (arm_from_thread(regs[REG_EXC_RETURN])) - { - tcb->xcp.regs = regs; - up_set_current_regs(regs); - } - /* Acknowledge the interrupt */ arm_ack_irq(irq); - /* Deliver the IRQ */ - - irq_dispatch(irq, regs); + if (irq == NVIC_IRQ_PENDSV) + { + up_irq_save(); + g_running_tasks[this_cpu()]->xcp.regs = regs; + } + else + { + tcb->xcp.regs = regs; + irq_dispatch(irq, regs); + } /* If a context switch occurred while processing the interrupt then * current_regs may have change value. If we return any value different @@ -118,30 +84,20 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) * switch occurred during interrupt processing. */ - if (arm_from_thread(regs[REG_EXC_RETURN])) - { - tcb = this_task(); + tcb = this_task(); - if (regs != tcb->xcp.regs) - { - /* Update scheduler parameters */ + /* Update scheduler parameters */ - nxsched_suspend_scheduler(g_running_tasks[this_cpu()]); - nxsched_resume_scheduler(tcb); + nxsched_suspend_scheduler(g_running_tasks[this_cpu()]); + nxsched_resume_scheduler(tcb); - /* Record the new "running" task when context switch occurred. - * g_running_tasks[] is only used by assertion logic for reporting - * crashes. - */ + /* Record the new "running" task when context switch occurred. + * g_running_tasks[] is only used by assertion logic for reporting + * crashes. + */ - g_running_tasks[this_cpu()] = tcb; - regs = tcb->xcp.regs; - } - - /* Update the current_regs to NULL. */ - - up_set_current_regs(NULL); - } + g_running_tasks[this_cpu()] = tcb; + regs = tcb->xcp.regs; #endif board_autoled_off(LED_INIRQ); diff --git a/arch/arm/src/armv8-m/arm_svcall.c b/arch/arm/src/armv8-m/arm_svcall.c index aeb427322c..0eef206fdf 100644 --- a/arch/arm/src/armv8-m/arm_svcall.c +++ b/arch/arm/src/armv8-m/arm_svcall.c @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -128,7 +129,6 @@ int arm_svcall(int irq, void *context, void *arg) uint32_t *regs = (uint32_t *)context; uint32_t cmd; - DEBUGASSERT(regs && regs == up_current_regs()); cmd = regs[REG_R0]; /* The SVCall software interrupt is called with R0 = system call command @@ -398,7 +398,6 @@ int arm_svcall(int irq, void *context, void *arg) /* Return privileged mode */ regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; - rtcb->xcp.sigreturn = 0; } break; @@ -447,7 +446,7 @@ int arm_svcall(int irq, void *context, void *arg) rtcb->flags |= TCB_FLAG_SYSCALL; #else - svcerr("ERROR: Bad SYS call: %d\n", (int)regs[REG_R0]); + svcerr("ERROR: Bad SYS call: %" PRId32 "\n", regs[REG_R0]); #endif } break; diff --git a/arch/arm/src/armv8-m/arm_vectors.c b/arch/arm/src/armv8-m/arm_vectors.c index 75308996e1..5f83341c1b 100644 --- a/arch/arm/src/armv8-m/arm_vectors.c +++ b/arch/arm/src/armv8-m/arm_vectors.c @@ -40,6 +40,8 @@ #include "chip.h" #include "arm_internal.h" +#include "ram_vectors.h" +#include "nvic.h" /**************************************************************************** * Pre-processor Definitions @@ -74,12 +76,13 @@ static void start(void) /* Common exception entrypoint */ extern void exception_common(void); +extern void exception_direct(void); /**************************************************************************** * Public data ****************************************************************************/ -/* The v7m vector table consists of an array of function pointers, with the +/* The v8m vector table consists of an array of function pointers, with the * first slot (vector zero) used to hold the initial stack pointer. * * As all exceptions (interrupts) are routed via exception_common, we just @@ -100,5 +103,7 @@ const void * const _vectors[] locate_data(".vectors") = /* Vectors 2 - n point directly at the generic handler */ - [2 ... (15 + ARMV8M_PERIPHERAL_INTERRUPTS)] = &exception_common + [2 ... NVIC_IRQ_PENDSV] = &exception_common, + [(NVIC_IRQ_PENDSV + 1) ... (15 + ARMV8M_PERIPHERAL_INTERRUPTS)] + = &exception_direct };