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 144 145 146 147 148 | /* * Copyright (c) 2013-2014 Wind River Systems, Inc. * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief ARM Cortex-A and Cortex-R interrupt management * * * Interrupt management: enabling/disabling and dynamic ISR * connecting/replacing. SW_ISR_TABLE_DYNAMIC has to be enabled for * connecting ISRs at runtime. */ #include <zephyr/kernel.h> #include <zephyr/arch/cpu.h> #include <zephyr/drivers/interrupt_controller/gic.h> #include <zephyr/sys/__assert.h> #include <zephyr/sys/barrier.h> #include <zephyr/toolchain.h> #include <zephyr/linker/sections.h> #include <zephyr/sw_isr_table.h> #include <zephyr/irq.h> #include <zephyr/tracing/tracing.h> #include <zephyr/pm/pm.h> extern void z_arm_reserved(void); /* * For Cortex-A and Cortex-R cores, the default interrupt controller is the ARM * Generic Interrupt Controller (GIC) and therefore the architecture interrupt * control functions are mapped to the GIC driver interface. * * When a custom interrupt controller is used (i.e. * CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER is enabled), the architecture * interrupt control functions are mapped to the SoC layer in * `include/arch/arm/irq.h`. */ #if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) void arch_irq_enable(unsigned int irq) { arm_gic_irq_enable(irq); } void arch_irq_disable(unsigned int irq) { arm_gic_irq_disable(irq); } int arch_irq_is_enabled(unsigned int irq) { return arm_gic_irq_is_enabled(irq); } /** * @internal * * @brief Set an interrupt's priority * * The priority is verified if ASSERT_ON is enabled. The maximum number * of priority levels is a little complex, as there are some hardware * priority levels which are reserved: three for various types of exceptions, * and possibly one additional to support zero latency interrupts. */ void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags) { arm_gic_irq_set_priority(irq, prio, flags); } #endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ void z_arm_fatal_error(unsigned int reason, const struct arch_esf *esf); /** * * @brief Spurious interrupt handler * * Installed in all _sw_isr_table slots at boot time. Throws an error if * called. * */ void z_irq_spurious(const void *unused) { ARG_UNUSED(unused); z_arm_fatal_error(K_ERR_SPURIOUS_IRQ, NULL); } #ifdef CONFIG_PM void _arch_isr_direct_pm(void) { unsigned int key; /* irq_lock() does what we want for this CPU */ key = irq_lock(); if (_kernel.idle) { _kernel.idle = 0; pm_system_resume(); } irq_unlock(key); } #endif #ifdef CONFIG_DYNAMIC_INTERRUPTS #ifdef CONFIG_GEN_ISR_TABLES int arch_irq_connect_dynamic(unsigned int irq, unsigned int priority, void (*routine)(const void *parameter), const void *parameter, uint32_t flags) { z_isr_install(irq, routine, parameter); z_arm_irq_priority_set(irq, priority, flags); return irq; } #endif /* CONFIG_GEN_ISR_TABLES */ #ifdef CONFIG_DYNAMIC_DIRECT_INTERRUPTS static inline void z_arm_irq_dynamic_direct_isr_dispatch(void) { uint32_t irq = __get_IPSR() - 16; if (irq < IRQ_TABLE_SIZE) { struct _isr_table_entry *isr_entry = &_sw_isr_table[irq]; isr_entry->isr(isr_entry->arg); } } ISR_DIRECT_DECLARE(z_arm_irq_direct_dynamic_dispatch_reschedule) { z_arm_irq_dynamic_direct_isr_dispatch(); return 1; } ISR_DIRECT_DECLARE(z_arm_irq_direct_dynamic_dispatch_no_reschedule) { z_arm_irq_dynamic_direct_isr_dispatch(); return 0; } #endif /* CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ #endif /* CONFIG_DYNAMIC_INTERRUPTS */ |