| /* |
| * Copyright (c) 2013-2014 Wind River Systems, Inc. |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| /** |
| * @file |
| * @brief Exception/interrupt context helpers for Cortex-M CPUs |
| * |
| * Exception/interrupt context helpers. |
| */ |
| |
| #ifndef _ARM_CORTEXM_ISR__H_ |
| #define _ARM_CORTEXM_ISR__H_ |
| |
| #include <arch/cpu.h> |
| #include <asm_inline.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #ifdef _ASMLANGUAGE |
| |
| /* nothing */ |
| |
| #else |
| |
| #include <arch/arm/cortex_m/cmsis.h> |
| #include <irq_offload.h> |
| |
| #ifdef CONFIG_IRQ_OFFLOAD |
| extern volatile irq_offload_routine_t offload_routine; |
| #endif |
| |
| /** |
| * |
| * @brief Find out if running in an ISR context |
| * |
| * The current executing vector is found in the IPSR register. We consider the |
| * IRQs (exception 16 and up), and the PendSV and SYSTICK exceptions to be |
| * interrupts. Taking a fault within an exception is also considered in |
| * interrupt context. |
| * |
| * @return 1 if in ISR, 0 if not. |
| */ |
| static ALWAYS_INLINE int _IsInIsr(void) |
| { |
| u32_t vector = _IpsrGet(); |
| |
| /* IRQs + PendSV (14) + SYSTICK (15) are interrupts. */ |
| return (vector > 13) |
| #ifdef CONFIG_IRQ_OFFLOAD |
| /* Only non-NULL if currently running an offloaded function */ |
| || offload_routine != NULL |
| #endif |
| #if defined(CONFIG_ARMV6_M) |
| /* On ARMv6-M there is no nested execution bit, so we check |
| * exception 3, hard fault, to a detect a nested exception. |
| */ |
| || (vector == 3) |
| #elif defined(CONFIG_ARMV7_M) |
| /* If not in thread mode, and if RETTOBASE bit in ICSR is 0, |
| * then there are preempted active exceptions to execute. |
| */ |
| #ifndef CONFIG_BOARD_QEMU_CORTEX_M3 |
| /* The polarity of RETTOBASE is incorrectly flipped in |
| * all but the very latest master tip of QEMU's NVIC driver, |
| * see commit "armv7m: Rewrite NVIC to not use any GIC code". |
| * Until QEMU 2.9 is released, and the SDK is updated to |
| * include it, skip this check in QEMU. |
| */ |
| || (vector && !(SCB->ICSR & SCB_ICSR_RETTOBASE_Msk)) |
| #endif /* CONFIG_BOARD_QEMU_CORTEX_M3 */ |
| #else |
| #error Unknown ARM architecture |
| #endif /* CONFIG_ARMV6_M */ |
| ; |
| } |
| |
| #define _EXC_SVC_PRIO 0 |
| #define _EXC_FAULT_PRIO 0 |
| /** |
| * @brief Setup system exceptions |
| * |
| * Set exception priorities to conform with the BASEPRI locking mechanism. |
| * Set PendSV priority to lowest possible. |
| * |
| * Enable fault exceptions. |
| * |
| * @return N/A |
| */ |
| static ALWAYS_INLINE void _ExcSetup(void) |
| { |
| NVIC_SetPriority(PendSV_IRQn, 0xff); |
| |
| #ifdef CONFIG_CPU_CORTEX_M_HAS_BASEPRI |
| NVIC_SetPriority(SVCall_IRQn, _EXC_SVC_PRIO); |
| #endif |
| |
| #ifdef CONFIG_CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS |
| NVIC_SetPriority(MemoryManagement_IRQn, _EXC_FAULT_PRIO); |
| NVIC_SetPriority(BusFault_IRQn, _EXC_FAULT_PRIO); |
| NVIC_SetPriority(UsageFault_IRQn, _EXC_FAULT_PRIO); |
| |
| /* Enable Usage, Mem, & Bus Faults */ |
| SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_MEMFAULTENA_Msk | |
| SCB_SHCSR_BUSFAULTENA_Msk; |
| #endif |
| } |
| |
| /** |
| * @brief Clear Fault exceptions |
| * |
| * Clear out exceptions for Mem, Bus, Usage and Hard Faults |
| * |
| * @return N/A |
| */ |
| static ALWAYS_INLINE void _ClearFaults(void) |
| { |
| #if defined(CONFIG_ARMV6_M) |
| #elif defined(CONFIG_ARMV7_M) |
| /* Reset all faults */ |
| SCB->CFSR = SCB_CFSR_USGFAULTSR_Msk | |
| SCB_CFSR_MEMFAULTSR_Msk | |
| SCB_CFSR_BUSFAULTSR_Msk; |
| |
| /* Clear all Hard Faults - HFSR is write-one-to-clear */ |
| SCB->HFSR = 0xffffffff; |
| #else |
| #error Unknown ARM architecture |
| #endif /* CONFIG_ARMV6_M */ |
| } |
| |
| #endif /* _ASMLANGUAGE */ |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| |
| #endif /* _ARM_CORTEXM_ISR__H_ */ |