Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | /* * 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_ */ |