Comment 2 for bug 1379236

Revision history for this message
Terry Guo (terry.guo) wrote :

This bug is caused by using r7 register through below inline assembly code in file rtx/rt_CMSIS.c:

#if (defined (__CORTEX_M0)) || defined (__CORTEX_M0PLUS)
#define SVC_Call(f) \
  __asm volatile \
  ( \
    "ldr r7,="#f"\n\t" \
    "mov r12,r7\n\t" \
    "svc 0" \
    : "=r" (__r0), "=r" (__r1), "=r" (__r2), "=r" (__r3) \
    : "r" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) \
    : "r7", "r12", "lr", "cc" \
  );
#else

The r7 is used as frame pointer register for thumb1 target cortex-m0. It is not allowed to be changed like above ldr instruction when the frame register is actually needed.

Above inline assembly code is used in below function:

// Thread Public API

/// Create a thread and add it to Active Threads and set it to state READY
osThreadId osThreadCreate (osThreadDef_t *thread_def, void *argument) {
  if (__get_IPSR() != 0) return NULL; // Not allowed in ISR
  if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) {
    // Privileged and not running
    return svcThreadCreate(thread_def, argument);
  } else {
    return __svcThreadCreate(thread_def, argument);
  }
}

When lto is disabled, this function is pretty simple and won't use stack, so frame pointer register isn't going to be needed. Everything is fine. It's allowed to use r7 as above ldr instruction.

When lto is enabled, the function svcThreadCreate will be inlined into function osThreadCreate by lto. The stack will be used and then the frame pointer register will be used for accessing stack like [r7, #4]. It's not allowed to change r7 now like above ldr instruction. The error message is generated. This makes sense.

I think the correct way to avoid such error is avoiding use r7 in this inline assembly code.

A workaround is to use option -fomit-frame-pointer, but it will lead to another bug which I am looking into.