Zephyr Project API 3.7.0
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
interrupt_util.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#ifndef INTERRUPT_UTIL_H_
8#define INTERRUPT_UTIL_H_
9
10#define MS_TO_US(ms) (ms * USEC_PER_MSEC)
11
12#if defined(CONFIG_CPU_CORTEX_M)
13#include <cmsis_core.h>
14
15static inline uint32_t get_available_nvic_line(uint32_t initial_offset)
16{
17 int i;
18
19 for (i = initial_offset - 1; i >= 0; i--) {
20
21 if (NVIC_GetEnableIRQ(i) == 0) {
22 /*
23 * Interrupts configured statically with IRQ_CONNECT(.)
24 * are automatically enabled. NVIC_GetEnableIRQ()
25 * returning false, here, implies that the IRQ line is
26 * either not implemented or it is not enabled, thus,
27 * currently not in use by Zephyr.
28 */
29
30 /* Set the NVIC line to pending. */
31 NVIC_SetPendingIRQ(i);
32
33 if (NVIC_GetPendingIRQ(i)) {
34 /*
35 * If the NVIC line is pending, it is
36 * guaranteed that it is implemented; clear the
37 * line.
38 */
39 NVIC_ClearPendingIRQ(i);
40
41 if (!NVIC_GetPendingIRQ(i)) {
42 /*
43 * If the NVIC line can be successfully
44 * un-pended, it is guaranteed that it
45 * can be used for software interrupt
46 * triggering. Return the NVIC line
47 * number.
48 */
49 break;
50 }
51 }
52 }
53 }
54
55 zassert_true(i >= 0, "No available IRQ line\n");
56
57 return i;
58}
59
60static inline void trigger_irq(int irq)
61{
62 printk("Triggering irq : %d\n", irq);
63#if defined(CONFIG_SOC_TI_LM3S6965_QEMU) || defined(CONFIG_CPU_CORTEX_M0) \
64 || defined(CONFIG_CPU_CORTEX_M0PLUS) || defined(CONFIG_CPU_CORTEX_M1)\
65 || defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
66 /* QEMU does not simulate the STIR register: this is a workaround */
67 NVIC_SetPendingIRQ(irq);
68#else
69 NVIC->STIR = irq;
70#endif
71}
72
73#elif defined(CONFIG_GIC)
76
77static inline void trigger_irq(int irq)
78{
79 printk("Triggering irq : %d\n", irq);
80
81 /* Ensure that the specified IRQ number is a valid SGI interrupt ID */
82 zassert_true(irq <= 15, "%u is not a valid SGI interrupt ID", irq);
83
84 /*
85 * Generate a software generated interrupt and forward it to the
86 * requesting CPU.
87 */
88#if CONFIG_GIC_VER <= 2
90 GICD_SGIR);
91#else
92 uint64_t mpidr = GET_MPIDR();
93 uint8_t aff0 = MPIDR_AFFLVL(mpidr, 0);
94
95 gic_raise_sgi(irq, mpidr, BIT(aff0));
96#endif
97}
98
99#elif defined(CONFIG_ARC)
100static inline void trigger_irq(int irq)
101{
102 printk("Triggering irq : %d\n", irq);
103 z_arc_v2_aux_reg_write(_ARC_V2_AUX_IRQ_HINT, irq);
104}
105
106#elif defined(CONFIG_X86)
107
108#ifdef CONFIG_X2APIC
110#define VECTOR_MASK 0xFF
111#else
113#define LOAPIC_ICR_IPI_TEST 0x00004000U
114#endif
115
116/*
117 * We can emulate the interrupt by sending the IPI to
118 * core itself by the LOAPIC for x86 platform.
119 *
120 * In APIC mode, Write LOAPIC's ICR to trigger IPI,
121 * the LOAPIC_ICR_IPI_TEST 0x00004000U means:
122 * Delivery Mode: Fixed
123 * Destination Mode: Physical
124 * Level: Assert
125 * Trigger Mode: Edge
126 * Destination Shorthand: No Shorthand
127 * Destination: depends on cpu_id
128 *
129 * In X2APIC mode, this no longer works. We emulate the
130 * interrupt by writing the IA32_X2APIC_SELF_IPI MSR
131 * to send IPI to the core itself via LOAPIC also.
132 * According to SDM vol.3 chapter 10.12.11, the bit[7:0]
133 * for setting the vector is only needed.
134 */
135static inline void trigger_irq(int vector)
136{
137 uint8_t i;
138
139#ifdef CONFIG_X2APIC
140 x86_write_x2apic(LOAPIC_SELF_IPI, ((VECTOR_MASK & vector)));
141#else
142
143#ifdef CONFIG_SMP
144 int cpu_id = arch_curr_cpu()->id;
145#else
146 int cpu_id = 0;
147#endif
148 z_loapic_ipi(cpu_id, LOAPIC_ICR_IPI_TEST, vector);
149#endif /* CONFIG_X2APIC */
150
151 /*
152 * add some nop operations here to cost some cycles to make sure
153 * the IPI interrupt is handled before do our check.
154 */
155 for (i = 0; i < 10; i++) {
156 arch_nop();
157 }
158}
159
160#elif defined(CONFIG_ARCH_POSIX)
162
163static inline void trigger_irq(int irq)
164{
166}
167
168#elif defined(CONFIG_RISCV)
169#if defined(CONFIG_NUCLEI_ECLIC) || defined(CONFIG_NRFX_CLIC)
170void riscv_clic_irq_set_pending(uint32_t irq);
171static inline void trigger_irq(int irq)
172{
173 riscv_clic_irq_set_pending(irq);
174}
175#else
176static inline void trigger_irq(int irq)
177{
178 uint32_t mip;
179
180 __asm__ volatile ("csrrs %0, mip, %1\n"
181 : "=r" (mip)
182 : "r" (1 << irq));
183}
184#endif
185#elif defined(CONFIG_XTENSA)
186static inline void trigger_irq(int irq)
187{
188 z_xt_set_intset(BIT((unsigned int)irq));
189}
190
191#elif defined(CONFIG_SPARC)
192extern void z_sparc_enter_irq(int);
193
194static inline void trigger_irq(int irq)
195{
196 z_sparc_enter_irq(irq);
197}
198
199#elif defined(CONFIG_MIPS)
200extern void z_mips_enter_irq(int);
201
202static inline void trigger_irq(int irq)
203{
204 z_mips_enter_irq(irq);
205}
206
207#elif defined(CONFIG_CPU_CORTEX_R5) && defined(CONFIG_VIM)
208
209extern void z_vim_arm_enter_irq(int);
210
211static inline void trigger_irq(int irq)
212{
213 z_vim_arm_enter_irq(irq);
214}
215
216#else
217/* So far, Nios II does not support this */
218#define NO_TRIGGER_FROM_SW
219#endif
220
221#endif /* INTERRUPT_UTIL_H_ */
static ALWAYS_INLINE _cpu_t * arch_curr_cpu(void)
Definition arch_inlines.h:17
#define MPIDR_AFFLVL(mpidr, aff_level)
Definition cpu.h:94
#define GET_MPIDR()
Definition cpu.h:97
Driver for ARM Generic Interrupt Controller.
void gic_raise_sgi(unsigned int sgi_id, uint64_t target_aff, uint16_t target_list)
raise SGI to target cores
#define GICD_SGIR
Definition gic.h:127
#define GICD_SGIR_SGIINTID(x)
Definition gic.h:207
#define GICD_SGIR_TGTFILT_REQONLY
Definition gic.h:199
static void arch_nop(void)
Do nothing and return.
#define BIT(n)
Unsigned integer with bit position n set (signed in assembly language).
Definition util_macro.h:44
#define zassert_true(cond,...)
Assert that cond is true.
Definition ztest_assert.h:269
static void x86_write_x2apic(unsigned int reg, uint64_t val)
Write 64-bit value to the local APIC in x2APIC mode.
Definition loapic.h:117
#define LOAPIC_SELF_IPI
Definition loapic.h:42
void posix_sw_set_pending_IRQ(unsigned int IRQn)
static void printk(const char *fmt,...)
Print kernel debugging message.
Definition printk.h:51
__UINT32_TYPE__ uint32_t
Definition stdint.h:90
__UINT64_TYPE__ uint64_t
Definition stdint.h:91
__UINT8_TYPE__ uint8_t
Definition stdint.h:88
static ALWAYS_INLINE void sys_write32(uint32_t data, mem_addr_t addr)
Definition sys-io-common.h:70