ARM-software / CMSIS_5

CMSIS Version 5 Development Repository
http://arm-software.github.io/CMSIS_5/index.html
Apache License 2.0
1.31k stars 1.08k forks source link

Frame pointer used in RTX SVC call gives error from GCC #118

Closed parched closed 6 years ago

parched commented 7 years ago

When compiling with GCC with frame pointers (the default without optimisation) I get the error

CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_delay.c: In function 'osDelay': CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_delay.c:78:1: error: r7 cannot be used in asm here

it's in __svcDelay which is produced from macro as

__attribute__((always_inline)) static inline osStatus_t __svcDelay (uint32_t a1) { register uint32_t __r0 __asm("r""0") = (uint32_t)a1; register uint32_t __rf __asm("r7") = (uint32_t)svcRtxDelay; __asm volatile ("svc 0" : "=r"(__r0) : "r"(__rf),"r"(__r0) : "r1"); return (osStatus_t) __r0; }

It looks like this commit @3fc10834231c1d170c2729fe8513e8c0768cdb2f introduced using the frame pointer in the SVC call which GCC doesn't like.

Produced with GCC 6.2.0, -march=armv6-m

CC: @RobertRostohar

RobertRostohar commented 7 years ago

This issue is limited to GCC without optimization and for ARMv6-M cores only. It can be simply avoided by using any other optimization (except no optimization).

It will be reviewed if another register (not R7) should be used in this case. However this might present issues with other compilers which support SVC with R7 natively for highly optimized code.

ReinhardKeil commented 7 years ago

This can be solved by setting correct compiler optimization

ilg-ul commented 7 years ago

setting correct compiler optimization

I'm afraid this is not an acceptable answer. any optimisation level accepted by the compiler is correct.

if your code does not work on certain optimisation levels, there are two possibilities: either your code has a problem or the compiler has a problem.

my suggestion is to assume the first one.

ReinhardKeil commented 7 years ago

looks like we need to review the GCC compiler.

JonatanAntoni commented 6 years ago

We have reviewed the code and all main compilers supported. Unfortunately we cannot conclude that its a "trivial" compiler issue. From my current understanding I got from lengthy discussions with some compiler experts it looks like a design clash from "different worlds".

At one hand R7 was chosen for SVC indirect calls to store the service function pointer on Armv6-M devices. Independently R7 was chosen to be used for the frame pointer (on Linux-based systems), too. Both features are not standardized in terms of the Arm ABI. As a consequence one can only use one of those features at a time.

To conclude the original issue: Yes, we do not support using frame pointers with the current implementation of RTX5. GCC with no optimization uses frame pointers by default. Hence you need to disable frame pointers manually with -fomit-frame-pointer if using -O0. Starting with optimization -O1 frame pointers are disabled by default.

@parched is it a viable solution for you to disable frame pointers? If not, may I ask you to describe your use case you'd like to use frame pointers for, please? I'd like to work out the benefits we could gain by supporting frame pointers.

ReinhardKeil commented 6 years ago

Closing as there is no further activity

troian commented 5 years ago

Seems r7 as a frame pointer might be required while trying to backtrace Is there any advice about changing it to some another one?

JonatanAntoni commented 5 years ago

Hi @troian,

What exactly do you need for backtrace? Technically you could use any register for storing the SVC indirect function pointer. Of course you need to assure the compiler doesn't make use of the register for any other purpose. If you know your compiler that should be possible. If not, generally speaking, it's a tough job. Hence we decided to keep using r7.

Cheers, Jonatan

troian commented 5 years ago

@JonatanAntoni thank you for quick reply. It's quite useful to backtrace HardFault for example while development is in progress as printing regs itself does not tell who is caller etc. I found this project which requires -fno-omit-frame-pointer so we are on GCC toolchain provided by ARM. It works fine for Cortex-M3/4 though.