Hello-
This is a warning kind of post with an explanation and a work around
proposal(sorry for making it a bit long :-)).
I have posted it also on ARM User group.
When optimization is not used (often the case when we just start development)GCC
4.1.1 compiler generates function prologue/epilogue
which is not pre-emption safe that may cause hard to debug
application crashes (for example uCOS-II GCC port crash during
interrupt from time to time).
When functions of type void Function(void) without local parameters
are compiled below stack frame prologue/epilogue is generated (when
optimization is not used):
void Function(void)
{
@Function prologue
5094: b580 push {r7, lr}
5096: af02 add r7, sp, #8
FUNCTION BODY...
}
@Function epilogue
509e: 46bd mov sp, r7
50a0: b082 sub sp, #8
50a2: bc80 pop {r7}
50a4: bc01 pop {r0}
50a6: 4700 bx r0
(for arm-elf-gcc -c -mthumb -mcpu=arm7tdmi-s -mthumb-interwork -O0,
addresses shown only for further references)
When an interrupt is generated at address 509e i.e. when mov sp,r7 is
executed, and when application is written in that way that
interrupted function context is preserved on the application's stack
(task's stack)(very often the case in real time operating systems
like for example in uCOS-II) just saved context overwrites r7 and lr
pushed on the stack on function entry. Next after a return from
interrupt wrong r7 and r0 values are popped on function epilogue
(because they were overwritten) and return from the function with bx
r0 instruction switches application to the wrong and not intended
program address (and possibly to ARM processor instruction set).
Following Dave Hawkins suggestions (thanks Dave) I have checked
GNUARM GCC 3.4.3 and for the same case pre-emption safe code is
generated (!) as shown below:
void Function(void)
{
@Function prologue
505c: b580 push {r7, lr}
505e: 466f mov r7, sp
FUNCTION BODY...
}
@Function epilogue
5066: 46bd mov sp, r7
5068: bc80 pop {r7}
506a: bc01 pop {r0}
506c: 4700 bx r0
In GCC 3.4.3 there are not pre-emption unsafe stack instruction
generated (no instruction add r7, sp, #8 on entry and no
instruction sub sp, #8 on exit).
In GCC 4.1.1 as a work around you can use -fomit-frame-pointer flag
or optimization turned on (like –O1 flag which is also turning on
–fomit-frame-pointer flag) this solves the problem making compiled
functions pre-emption safe.
Bogdan