diff --git a/Documentation/guides/zerolatencyinterrupts.rst b/Documentation/guides/zerolatencyinterrupts.rst index c44a0ce23bf3d..bd0781f75fff9 100644 --- a/Documentation/guides/zerolatencyinterrupts.rst +++ b/Documentation/guides/zerolatencyinterrupts.rst @@ -1,6 +1,6 @@ -========================================= -High Performance, Zero Latency Interrupts -========================================= +===================================================================== +High Performance: Zero Latency Interrupts, Maskable nested interrupts +===================================================================== Generic Interrupt Handling ========================== @@ -111,6 +111,62 @@ between the high priority interrupt handler and *PendSV* interrupt handler. A detailed discussion of that custom logic is beyond the scope of this Wiki page. +The following table shows the priority levels of the Cortex-M family: + +.. code-block:: + + IRQ type Priority + Dataabort 0x00 + High prio IRQ1 0x20 (Zero-latency interrupt) + High prio IRQ2 0x30 (Can't call OS API in ISR) + SVC 0x70 + Disable IRQ 0x80 + (critical-section) + Low prio IRQ 0xB0 + PendSV 0xE0 + +As you can see, the priority levels of the zero-latency interrupts can +beyond the critical section and SVC. +But High prio IRQ can't call OS API. + + +Maskable Nested Interrupts +========================== + +The ARM Cortex-M family supports a feature called *BASEPRI* that can be +used to disable interrupts at a priority level below a certain level. +This feature can be used to support maskable nested interrupts. + +Maskable nested interrupts differ from zero-latency interrupts in +that they obey the interrupt masking mechanisms of the system. +For example, setting the BASEPRI register to a specific threshold will +block all interrupts of a lower or equal priority. +However, high-priority interrupts (such as Non-Maskable Interrupts +or zero-latency interrupts) are unaffected by these masks. + +This is useful when you have a high-priority interrupt that needs to +be able to interrupt the system, but you also have lower-priority +interrupts that you want to be able to mask. + +The following table shows the priority levels of the Cortex-M family: + +.. code-block:: + + IRQ type Priority + Dataabort 0x00 + SVC 0x70 + Disable IRQ 0x80 + (critical-section) + High prio IRQ1 0x90 (Maskable nested interrupt) + High prio IRQ2 0xA0 (Can call OS API in ISR) + Low prio IRQ 0xB0 + PendSV 0xE0 + +As you can see, the priority levels of the maskable nested interrupts +are between the critical section and the low-priority interrupts. +And High prio IRQ can call OS API in ISR. + + Nested Interrupt Handling ========================= diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 192edc4bb507f..4e4d50131cad1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -817,6 +817,7 @@ config ARCH_CORTEXM0 select ARM_THUMB select ARCH_ARMV6M select ARCH_HAVE_IRQPRIO + select ARCH_HAVE_IRQTRIGGER select ARCH_HAVE_RAMVECTORS select ARCH_HAVE_RESET select ARCH_HAVE_HARDFAULT_DEBUG diff --git a/arch/arm/include/armv7-m/irq.h b/arch/arm/include/armv7-m/irq.h index c387899f6053f..87cf6e0acfaf1 100644 --- a/arch/arm/include/armv7-m/irq.h +++ b/arch/arm/include/armv7-m/irq.h @@ -440,7 +440,7 @@ static inline void up_irq_enable(void) { /* In this case, we are always retaining or lowering the priority value */ - setbasepri(NVIC_SYSH_PRIORITY_MIN); + setbasepri(0); __asm__ __volatile__ ("\tcpsie i\n"); } diff --git a/arch/arm/include/armv8-m/irq.h b/arch/arm/include/armv8-m/irq.h index fb23d569b7db8..0860ae960ceda 100644 --- a/arch/arm/include/armv8-m/irq.h +++ b/arch/arm/include/armv8-m/irq.h @@ -413,7 +413,7 @@ static inline void up_irq_enable(void) { /* In this case, we are always retaining or lowering the priority value */ - setbasepri(NVIC_SYSH_PRIORITY_MIN); + setbasepri(0); __asm__ __volatile__ ("\tcpsie i\n"); } diff --git a/arch/arm/src/armv6-m/CMakeLists.txt b/arch/arm/src/armv6-m/CMakeLists.txt index deffc19040ff5..6bfb5449296a3 100644 --- a/arch/arm/src/armv6-m/CMakeLists.txt +++ b/arch/arm/src/armv6-m/CMakeLists.txt @@ -29,6 +29,7 @@ set(SRCS arm_svcall.c arm_systemreset.c arm_tcbinfo.c + arm_trigger_irq.c arm_vectors.c) if(CONFIG_DEBUG_FEATURES) diff --git a/arch/arm/src/armv6-m/Make.defs b/arch/arm/src/armv6-m/Make.defs index 669a586cef2a2..9a39ab04bfdde 100644 --- a/arch/arm/src/armv6-m/Make.defs +++ b/arch/arm/src/armv6-m/Make.defs @@ -27,6 +27,7 @@ CMN_ASRCS += arm_exception.S arm_saveusercontext.S CMN_CSRCS += arm_cpuinfo.c arm_doirq.c arm_hardfault.c arm_initialstate.c CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c arm_svcall.c CMN_CSRCS += arm_systemreset.c arm_tcbinfo.c arm_vectors.c +CMN_CSRCS += arm_trigger_irq.c ifeq ($(CONFIG_DEBUG_FEATURES),y) CMN_CSRCS += arm_dumpnvic.c diff --git a/arch/arm/src/armv6-m/arm_doirq.c b/arch/arm/src/armv6-m/arm_doirq.c index 3065a4f4dad09..fea1620bd207a 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,32 @@ 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 */ + /* Set current regs for crash dump */ + + up_set_current_regs(regs); + + if (irq == NVIC_IRQ_PENDSV) + { +#ifdef CONFIG_ARCH_HIPRI_INTERRUPT + /* Dispatch the PendSV interrupt */ + + irq_dispatch(irq, regs); +#endif - irq_dispatch(irq, regs); + up_irq_save(); + g_running_tasks[this_cpu()]->xcp.regs = regs; + } + else + { + /* Dispatch irq */ + + 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,32 +96,27 @@ 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; - } + g_running_tasks[this_cpu()] = tcb; + regs = tcb->xcp.regs; +#endif - /* Update the current_regs to NULL. */ + /* Clear current regs */ - up_set_current_regs(NULL); - } -#endif + up_set_current_regs(NULL); board_autoled_off(LED_INIRQ); + return regs; } diff --git a/arch/arm/src/armv6-m/arm_svcall.c b/arch/arm/src/armv6-m/arm_svcall.c index 62f57e302a47d..bab2404669fcf 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_trigger_irq.c b/arch/arm/src/armv6-m/arm_trigger_irq.c new file mode 100644 index 0000000000000..397a18705dd45 --- /dev/null +++ b/arch/arm/src/armv6-m/arm_trigger_irq.c @@ -0,0 +1,87 @@ +/**************************************************************************** + * arch/arm/src/armv6-m/arm_trigger_irq.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "arm_internal.h" +#include "nvic.h" + +#ifdef CONFIG_ARCH_HAVE_IRQTRIGGER + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_trigger_irq + * + * Description: + * Trigger an IRQ by software. + * + ****************************************************************************/ + +void up_trigger_irq(int irq, cpu_set_t cpuset) +{ + uint32_t pend_bit = 0; + + DEBUGASSERT(irq >= NVIC_IRQ_NMI && irq < NR_IRQS); + + if (irq >= NVIC_IRQ_FIRST) + { + putreg32(irq - NVIC_IRQ_FIRST, ARMV6M_NVIC2_BASE); + } + else + { + switch (irq) + { + case NVIC_IRQ_PENDSV: + pend_bit = SYSCON_ICSR_PENDSVSET; + break; + + case NVIC_IRQ_NMI: + pend_bit = SYSCON_ICSR_NMIPENDSET; + break; + + case NVIC_IRQ_SYSTICK: + pend_bit = SYSCON_ICSR_PENDSTSET; + break; + + default: + break; + } + + if (pend_bit) + { + modifyreg32(ARMV6M_SYSCON_ICSR, 0, pend_bit); + } + } +} + +#endif /* CONFIG_ARCH_HAVE_IRQTRIGGER */ diff --git a/arch/arm/src/armv6-m/arm_vectors.c b/arch/arm/src/armv6-m/arm_vectors.c index 8beb9443c1dfc..dbb336ae154b0 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/armv6-m/nvic.h b/arch/arm/src/armv6-m/nvic.h index 62be901b69ba2..329600688419d 100644 --- a/arch/arm/src/armv6-m/nvic.h +++ b/arch/arm/src/armv6-m/nvic.h @@ -32,6 +32,31 @@ * Pre-processor Definitions ****************************************************************************/ +/* Exception/interrupt vector numbers ***************************************/ + + /* Vector 0: Reset stack + * pointer value + */ + + /* Vector 1: Reset */ +#define NVIC_IRQ_NMI (2) /* Vector 2: Non-Maskable Interrupt (NMI) */ +#define NVIC_IRQ_HARDFAULT (3) /* Vector 3: Hard fault */ +#define NVIC_IRQ_MEMFAULT (4) /* Vector 4: Memory management (MPU) */ +#define NVIC_IRQ_BUSFAULT (5) /* Vector 5: Bus fault */ +#define NVIC_IRQ_USAGEFAULT (6) /* Vector 6: Usage fault */ + /* Vectors 7-10: Reserved */ +#define NVIC_IRQ_SVCALL (11) /* Vector 11: SVC call */ +#define NVIC_IRQ_DBGMONITOR (12) /* Vector 12: Debug Monitor */ + /* Vector 13: Reserved */ +#define NVIC_IRQ_PENDSV (14) /* Vector 14: Pendable system service request */ +#define NVIC_IRQ_SYSTICK (15) /* Vector 15: System tick */ + +/* External interrupts (vectors >= 16). + * These definitions are chip-specific + */ + +#define NVIC_IRQ_FIRST (16) /* Vector number of the first interrupt */ + /* Base addresses ***********************************************************/ #define ARMV6M_SYSCON1_BASE 0xe000e008 /* 0xe000e008-0xe000e00f System Control Block */ diff --git a/arch/arm/src/armv7-m/arm_doirq.c b/arch/arm/src/armv7-m/arm_doirq.c index 5c31de792ecf0..a14b24e6a4222 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,32 @@ 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 */ + /* Set current regs for crash dump */ + + up_set_current_regs(regs); + + if (irq == NVIC_IRQ_PENDSV) + { +#ifdef CONFIG_ARCH_HIPRI_INTERRUPT + /* Dispatch the PendSV interrupt */ + + irq_dispatch(irq, regs); +#endif - irq_dispatch(irq, regs); + up_irq_save(); + g_running_tasks[this_cpu()]->xcp.regs = regs; + } + else + { + /* Dispatch irq */ + + 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,32 +96,27 @@ 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; - } + g_running_tasks[this_cpu()] = tcb; + regs = tcb->xcp.regs; +#endif - /* Update the current_regs to NULL. */ + /* Clear current regs */ - up_set_current_regs(NULL); - } -#endif + up_set_current_regs(NULL); board_autoled_off(LED_INIRQ); + return regs; } diff --git a/arch/arm/src/armv7-m/arm_initialstate.c b/arch/arm/src/armv7-m/arm_initialstate.c index 4e6127ff812c5..4baec4aee41e0 100644 --- a/arch/arm/src/armv7-m/arm_initialstate.c +++ b/arch/arm/src/armv7-m/arm_initialstate.c @@ -163,7 +163,7 @@ void up_initial_state(struct tcb_s *tcb) #else /* CONFIG_SUPPRESS_INTERRUPTS */ #ifdef CONFIG_ARMV7M_USEBASEPRI - xcp->regs[REG_BASEPRI] = NVIC_SYSH_PRIORITY_MIN; + xcp->regs[REG_BASEPRI] = 0; #endif #endif /* CONFIG_SUPPRESS_INTERRUPTS */ diff --git a/arch/arm/src/armv7-m/arm_svcall.c b/arch/arm/src/armv7-m/arm_svcall.c index 6c6f507aeca1b..bfa2dc59f8fa2 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 c4674ab20f4ea..f007d021f0590 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 3e2fe2e961ff0..0f3fad50bbe12 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" +#include "nvic.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. - * + * Public Functions ****************************************************************************/ -static inline bool arm_from_thread(uint32_t excret) +void exception_direct(void) { - if (excret & EXC_RETURN_THREAD_MODE) - { - return true; - } + int irq = getipsr(); -#if defined(CONFIG_ARCH_TRUSTZONE_SECURE) - if (!(excret & EXC_RETURN_SECURE_STACK) && - (excret & EXC_RETURN_EXC_SECURE)) - { - return true; - } + arm_ack_irq(irq); + irq_dispatch(irq, NULL); - if (!(excret & EXC_RETURN_EXC_SECURE) && - (excret & EXC_RETURN_SECURE_STACK)) + if (g_running_tasks[this_cpu()] != this_task()) { - return true; + up_trigger_irq(NVIC_IRQ_PENDSV, 0); } -#endif - - return false; } -/**************************************************************************** - * Public Functions - ****************************************************************************/ - uint32_t *arm_doirq(int irq, uint32_t *regs) { struct tcb_s *tcb = this_task(); @@ -98,19 +63,32 @@ 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 */ + /* Set current regs for crash dump */ + + up_set_current_regs(regs); + + if (irq == NVIC_IRQ_PENDSV) + { +#ifdef CONFIG_ARCH_HIPRI_INTERRUPT + /* Dispatch the PendSV interrupt */ + + irq_dispatch(irq, regs); +#endif + + up_irq_save(); + g_running_tasks[this_cpu()]->xcp.regs = regs; + } + else + { + /* Dispatch irq */ - irq_dispatch(irq, regs); + 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,31 +96,25 @@ 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; - } + g_running_tasks[this_cpu()] = tcb; + regs = tcb->xcp.regs; +#endif - /* Update the current_regs to NULL. */ + /* Clear current regs */ - up_set_current_regs(NULL); - } -#endif + up_set_current_regs(NULL); board_autoled_off(LED_INIRQ); diff --git a/arch/arm/src/armv8-m/arm_initialstate.c b/arch/arm/src/armv8-m/arm_initialstate.c index fa2cf9671893e..4916fc36ea3df 100644 --- a/arch/arm/src/armv8-m/arm_initialstate.c +++ b/arch/arm/src/armv8-m/arm_initialstate.c @@ -169,7 +169,7 @@ void up_initial_state(struct tcb_s *tcb) #else /* CONFIG_SUPPRESS_INTERRUPTS */ #ifdef CONFIG_ARMV8M_USEBASEPRI - xcp->regs[REG_BASEPRI] = NVIC_SYSH_PRIORITY_MIN; + xcp->regs[REG_BASEPRI] = 0; #endif #endif /* CONFIG_SUPPRESS_INTERRUPTS */ diff --git a/arch/arm/src/armv8-m/arm_svcall.c b/arch/arm/src/armv8-m/arm_svcall.c index aeb427322c07d..0eef206fdf2c4 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 75308996e14df..5f83341c1b812 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 }; diff --git a/arch/arm/src/lpc17xx_40xx/lpc17_40_irq.c b/arch/arm/src/lpc17xx_40xx/lpc17_40_irq.c index d0f131656890a..7c971c81fb518 100644 --- a/arch/arm/src/lpc17xx_40xx/lpc17_40_irq.c +++ b/arch/arm/src/lpc17xx_40xx/lpc17_40_irq.c @@ -137,9 +137,11 @@ static int lpc17_40_nmi(int irq, void *context, void *arg) static int lpc17_40_pendsv(int irq, void *context, void *arg) { +#ifndef CONFIG_ARCH_HIPRI_INTERRUPT up_irq_save(); _err("PANIC!!! PendSV received\n"); PANIC(); +#endif return 0; } diff --git a/arch/arm/src/mps/mps_irq.c b/arch/arm/src/mps/mps_irq.c index 6e9af56347d73..f5a98b709a96f 100644 --- a/arch/arm/src/mps/mps_irq.c +++ b/arch/arm/src/mps/mps_irq.c @@ -61,9 +61,11 @@ static int mps_nmi(int irq, void *context, void *arg) static int mps_pendsv(int irq, void *context, void *arg) { +#ifndef CONFIG_ARCH_HIPRI_INTERRUPT up_irq_save(); _err("PANIC!!! PendSV received\n"); PANIC(); +#endif return 0; } diff --git a/arch/arm/src/nrf52/nrf52_irq.c b/arch/arm/src/nrf52/nrf52_irq.c index 7c400bbf9ca95..2e916afc72a39 100644 --- a/arch/arm/src/nrf52/nrf52_irq.c +++ b/arch/arm/src/nrf52/nrf52_irq.c @@ -143,9 +143,11 @@ static int nrf52_nmi(int irq, void *context, void *arg) static int nrf52_pendsv(int irq, void *context, void *arg) { +#ifndef CONFIG_ARCH_HIPRI_INTERRUPT up_irq_save(); _err("PANIC!!! PendSV received\n"); PANIC(); +#endif return 0; } diff --git a/arch/arm/src/stm32/stm32_irq.c b/arch/arm/src/stm32/stm32_irq.c index 99374e5db7964..7a63323a37d53 100644 --- a/arch/arm/src/stm32/stm32_irq.c +++ b/arch/arm/src/stm32/stm32_irq.c @@ -148,9 +148,11 @@ static int stm32_nmi(int irq, void *context, void *arg) static int stm32_pendsv(int irq, void *context, void *arg) { +#ifndef CONFIG_ARCH_HIPRI_INTERRUPT up_irq_save(); _err("PANIC!!! PendSV received\n"); PANIC(); +#endif return 0; } diff --git a/arch/arm/src/stm32l4/stm32l4_irq.c b/arch/arm/src/stm32l4/stm32l4_irq.c index e8c0031550c9e..8499204741b25 100644 --- a/arch/arm/src/stm32l4/stm32l4_irq.c +++ b/arch/arm/src/stm32l4/stm32l4_irq.c @@ -145,9 +145,11 @@ static int stm32l4_nmi(int irq, void *context, void *arg) static int stm32l4_pendsv(int irq, void *context, void *arg) { +#ifndef CONFIG_ARCH_HIPRI_INTERRUPT up_irq_save(); _err("PANIC!!! PendSV received\n"); PANIC(); +#endif return 0; }