From 8e10a209b0401d9393f4f6418bdf1fec4a875a24 Mon Sep 17 00:00:00 2001 From: arighi Date: Tue, 18 May 2010 12:22:06 +0000 Subject: [PATCH] ARM7TDMI: gcc stack corruption workaround. GCC corrupts the stack pointer and the frame pointer when calling functions with at least one parameter inside ISR functions, declared with __attribute__((interrupt)): http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41999 As a workaround, we redefine all the ISRs to call only a single "void isr(void)" function. In this way, inside the actual isr() we can use any function call as usual. NOTE: this is inefficient, because it forces a totally unnecessary additional function call, but it is a reliable way to avoid the propagation of this bug to any project or architecture port that defines interrupt routines. When the bug will be fixed we will add an appropriate #ifdef to apply the workaround only when old versions of gcc are used. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@3708 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/cpu/irq.h | 49 +++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/bertos/cpu/irq.h b/bertos/cpu/irq.h index f4cd21ee..40571142 100644 --- a/bertos/cpu/irq.h +++ b/bertos/cpu/irq.h @@ -340,16 +340,16 @@ * IRQs will be automatically re-enabled when restoring * the context of the user task. */ - #define DECLARE_ISR_CONTEXT_SWITCH(func) \ - void ISR_FUNC func(void); \ - static void __isr_##func(void); \ - void ISR_FUNC func(void) \ - { \ - IRQ_ENTRY(); \ - IRQ_DISABLE; \ - __isr_##func(); \ - IRQ_EXIT(); \ - } \ + #define DECLARE_ISR_CONTEXT_SWITCH(func) \ + void ISR_FUNC func(void); \ + static NOINLINE void __isr_##func(void); \ + void ISR_FUNC func(void) \ + { \ + IRQ_ENTRY(); \ + IRQ_DISABLE; \ + __isr_##func(); \ + IRQ_EXIT(); \ + } \ static void __isr_##func(void) /** * Interrupt service routine prototype: can be used for @@ -376,21 +376,36 @@ #endif /* !CONFIG_KERN_PRI */ #endif /* CONFIG_KERN_PREEMPT */ + #ifndef ISR_FUNC + #define ISR_FUNC __attribute__((interrupt)) + #endif #ifndef DECLARE_ISR #define DECLARE_ISR(func) \ - void __attribute__((interrupt)) func(void) + void ISR_FUNC func(void); \ + /* \ + * FIXME: avoid the inlining of this function. \ + * \ + * This is terribly inefficient, but it's a \ + * reliable workaround to avoid gcc blowing \ + * away the stack (see the bug below): \ + * \ + * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41999 \ + */ \ + static NOINLINE void __isr_##func(void); \ + void ISR_FUNC func(void) \ + { \ + __isr_##func(); \ + } \ + static void __isr_##func(void) #endif #ifndef DECLARE_ISR_CONTEXT_SWITCH - #define DECLARE_ISR_CONTEXT_SWITCH(func) \ - void __attribute__((interrupt)) func(void) + #define DECLARE_ISR_CONTEXT_SWITCH(func) DECLARE_ISR(func) #endif #ifndef ISR_PROTO - #define ISR_PROTO(func) \ - void __attribute__((interrupt)) func(void) + #define ISR_PROTO(func) void ISR_FUNC func(void) #endif #ifndef ISR_PROTO_CONTEXT_SWITCH - #define ISR_PROTO_CONTEXT_SWITCH(func) \ - void __attribute__((interrupt)) func(void) + #define ISR_PROTO_CONTEXT_SWITCH(func) ISR_PROTO(func) #endif #endif /* !__IAR_SYSTEMS_ICC_ */ -- 2.25.1