Skip to content

Commit d0b4fe6

Browse files
committed
arch: arm: Add Cortex-R direct interrupt service routine support.
This commit implements direct interrupt service routine support for Cortex-R. On Cortex-R, the direct ISR function must be declared 'naked' with manual context preservation due to the following reasons: 1. 'z_arm_int_exit' does not return to the caller on Cortex-R (whereas, on Cortex-M, it can either return to the caller or directly exit the IRQ mode depending on the value of LR). 2. If 'z_arm_int_exit' is called (when ISR body returns true), since this function does not return to the caller on Cortex-R, the registers pushed into stack by the compiler will not get popped. 3. The caller-saved registers must be saved into the system mode stack because a context switch can occur. Signed-off-by: Stephanos Ioannidis <[email protected]>
1 parent 7339a52 commit d0b4fe6

File tree

2 files changed

+69
-17
lines changed

2 files changed

+69
-17
lines changed

arch/arm/core/irq.c

-5
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,6 @@ void _arch_isr_direct_pm(void)
8888
}
8989
#endif
9090

91-
void z_arch_isr_direct_header(void)
92-
{
93-
sys_trace_isr_enter();
94-
}
95-
9691
#ifdef CONFIG_DYNAMIC_INTERRUPTS
9792
int z_arch_irq_connect_dynamic(unsigned int irq, unsigned int priority,
9893
void (*routine)(void *parameter), void *parameter,

include/arch/arm/irq.h

+69-12
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,22 @@
66

77
/**
88
* @file
9-
* @brief Cortex-M public interrupt handling
9+
* @brief ARM public interrupt handling
1010
*
1111
* ARM-specific kernel interrupt handling interface. Included by arm/arch.h.
1212
*/
1313

14-
#ifndef ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_M_IRQ_H_
15-
#define ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_M_IRQ_H_
14+
#ifndef ZEPHYR_INCLUDE_ARCH_ARM_IRQ_H_
15+
#define ZEPHYR_INCLUDE_ARCH_ARM_IRQ_H_
1616

1717
#include <irq.h>
1818
#include <sw_isr_table.h>
1919
#include <stdbool.h>
2020

21+
#if defined(CONFIG_CPU_CORTEX_R)
22+
#include <arch/arm/cortex_r/cpu.h>
23+
#endif
24+
2125
#ifdef __cplusplus
2226
extern "C" {
2327
#endif
@@ -34,7 +38,7 @@ extern int z_arch_irq_is_enabled(unsigned int irq);
3438

3539
extern void z_arm_int_exit(void);
3640

37-
#if defined(CONFIG_ARMV7_R)
41+
#if defined(CONFIG_CPU_CORTEX_R)
3842
static ALWAYS_INLINE void z_arm_int_lib_init(void)
3943
{
4044
}
@@ -90,6 +94,36 @@ extern void z_arm_irq_priority_set(unsigned int irq, unsigned int prio,
9094
irq_p; \
9195
})
9296

97+
#ifndef CONFIG_CPU_CORTEX_M
98+
static ALWAYS_INLINE void z_arm_isr_enter(void)
99+
{
100+
__asm volatile(
101+
"push {r4, r5};"
102+
"mov r4, r12;"
103+
"sub r5, lr, #4;"
104+
"cps #" TOSTR(MODE_SYS) ";"
105+
"stmdb sp!, {r0-r5};"
106+
"cps #" TOSTR(MODE_IRQ) ";"
107+
"pop {r4, r5};"
108+
);
109+
}
110+
111+
static ALWAYS_INLINE void z_arm_isr_exit(void)
112+
{
113+
__asm volatile(
114+
"push {r4-r6};"
115+
"mrs r6, cpsr;"
116+
"cps #" TOSTR(MODE_SYS) ";"
117+
"ldmia sp!, {r0-r5};"
118+
"msr cpsr_c, r6;"
119+
"mov r12, r4;"
120+
"mov lr, r5;"
121+
"pop {r4-r6};"
122+
"movs pc, lr;"
123+
);
124+
}
125+
#endif /* !CONFIG_CPU_CORTEX_M */
126+
93127
/* FIXME prefer these inline, but see GH-3056 */
94128
#ifdef CONFIG_SYS_POWER_MANAGEMENT
95129
extern void _arch_isr_direct_pm(void);
@@ -99,31 +133,35 @@ extern void _arch_isr_direct_pm(void);
99133
#endif
100134

101135
#define Z_ARCH_ISR_DIRECT_HEADER() z_arch_isr_direct_header()
102-
extern void z_arch_isr_direct_header(void);
136+
static ALWAYS_INLINE void z_arch_isr_direct_header(void)
137+
{
138+
#ifdef CONFIG_TRACING
139+
sys_trace_isr_enter();
140+
#endif
141+
}
103142

104143
#define Z_ARCH_ISR_DIRECT_FOOTER(swap) z_arch_isr_direct_footer(swap)
105144

106-
/* arch/arm/core/exc_exit.S */
107-
extern void z_arm_int_exit(void);
108-
109145
#ifdef CONFIG_TRACING
110146
extern void sys_trace_isr_exit(void);
111147
#endif
112148

113-
static inline void z_arch_isr_direct_footer(int maybe_swap)
149+
static ALWAYS_INLINE void z_arch_isr_direct_footer(int maybe_swap)
114150
{
115-
116151
#ifdef CONFIG_TRACING
117152
sys_trace_isr_exit();
118153
#endif
154+
119155
if (maybe_swap) {
120156
z_arm_int_exit();
121157
}
122158
}
123159

160+
#ifdef CONFIG_CPU_CORTEX_M
161+
124162
#define Z_ARCH_ISR_DIRECT_DECLARE(name) \
125163
static inline int name##_body(void); \
126-
__attribute__ ((interrupt ("IRQ"))) void name(void) \
164+
__attribute__((interrupt)) void name(void) \
127165
{ \
128166
int check_reschedule; \
129167
ISR_DIRECT_HEADER(); \
@@ -132,6 +170,25 @@ static inline void z_arch_isr_direct_footer(int maybe_swap)
132170
} \
133171
static inline int name##_body(void)
134172

173+
#else
174+
175+
#define Z_ARCH_ISR_DIRECT_DECLARE(name) \
176+
static int name##_body(void); \
177+
__attribute__((naked)) void name(void) \
178+
{ \
179+
z_arm_isr_enter(); \
180+
{ \
181+
int check_reschedule; \
182+
ISR_DIRECT_HEADER(); \
183+
check_reschedule = name##_body(); \
184+
ISR_DIRECT_FOOTER(check_reschedule); \
185+
} \
186+
z_arm_isr_exit(); \
187+
} \
188+
static __attribute__((noinline)) int name##_body(void)
189+
190+
#endif /* CONFIG_CPU_CORTEX_M */
191+
135192
/* Spurious interrupt handler. Throws an error if called */
136193
extern void z_irq_spurious(void *unused);
137194

@@ -149,4 +206,4 @@ extern void _isr_wrapper(void);
149206
}
150207
#endif
151208

152-
#endif /* ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_M_IRQ_H_ */
209+
#endif /* ZEPHYR_INCLUDE_ARCH_ARM_IRQ_H_ */

0 commit comments

Comments
 (0)