strange behavior of the scheduler on STM32F070 Topic is solved

Report here problems in any of ChibiOS components. This forum is NOT for support.
dash
Posts: 17
Joined: Thu Oct 25, 2012 10:16 pm
Has thanked: 1 time
Been thanked: 4 times

Re: strange behavior of the scheduler on STM32F070  Topic is solved

Postby dash » Mon Nov 12, 2018 7:35 pm

I figured it out.
on cortex-m0 PORT_IRQ_PROLOGE saves the LR register, which is then supplied to PORT_IRQ_EPILOGUE

Code: Select all

#define PORT_IRQ_PROLOGUE()                                                 \
  regarm_t _saved_lr = (regarm_t)__builtin_return_address(0)

#define PORT_IRQ_EPILOGUE() _port_irq_epilogue(_saved_lr)


when optimization disabled gcc compiles to following code

Code: Select all

08003810 <Vector80>:
OSAL_IRQ_HANDLER(ST_HANDLER) {
 8003810:   b580         push   {r7, lr}
 8003812:   b082         sub   sp, #8
 8003814:   af00         add   r7, sp, #0
 8003816:   4673         mov   r3, lr                     <----- save LR
  OSAL_IRQ_PROLOGUE();
 8003818:   607b         str   r3, [r7, #4]
...

 800383e:   687b         ldr   r3, [r7, #4]           <------ use LR
 8003840:   0018         movs   r0, r3
 8003842:   f7fc fd75    bl   8000330 <_port_irq_epilogue>


however, with optimization is enabled, when a macro is called, the value of the LR register is already destroyed.

Code: Select all

08003710 <Vector80>:
OSAL_IRQ_HANDLER(ST_HANDLER) {
 8003710:   b5f8         push   {r3, r4, r5, r6, r7, lr}
 8003712:   46de         mov   lr, fp
 8003714:   4657         mov   r7, sl
 8003716:   464e         mov   r6, r9
 8003718:   4645         mov   r5, r8


gcc moves FP to LR
other handlers look similar

Code: Select all

08003400 <VectorBC>:
OSAL_IRQ_HANDLER(STM32_USB1_LP_HANDLER) {
 8003400:   b5f0         push   {r4, r5, r6, r7, lr}
 8003402:   46de         mov   lr, fp
 8003404:   4657         mov   r7, sl
 8003406:   464e         mov   r6, r9
 8003408:   4645         mov   r5, r8
  OSAL_IRQ_PROLOGUE();
 800340a:   4673         mov   r3, lr        <----- LR has invalid value here


it seems to be the reason

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: strange behavior of the scheduler on STM32F070

Postby Giovanni » Mon Nov 12, 2018 7:46 pm

Seems to be a compiler problem... I will look into this. You could try a 6.x version, probably it is a regression in 7.x related to that builtin function because it has been working for years now.

In addition, it seems to be M0-specific, M3 and following do not need all that registers copying.

Moving in "bug reports" even if it is not strictly an OS bug apparently.

Giovanni

dash
Posts: 17
Joined: Thu Oct 25, 2012 10:16 pm
Has thanked: 1 time
Been thanked: 4 times

Re: strange behavior of the scheduler on STM32F070

Postby dash » Mon Nov 12, 2018 8:05 pm

I tried GCC 6.3.1 (from developer.arm.com)
It makes the exact same code with enabled optimizations

Code: Select all

08001fe0 <VectorBC>:
OSAL_IRQ_HANDLER(STM32_USB1_LP_HANDLER) {
 8001fe0:   b5f0         push   {r4, r5, r6, r7, lr}
 8001fe2:   46de         mov   lr, fp
 8001fe4:   4657         mov   r7, sl
 8001fe6:   464e         mov   r6, r9
 8001fe8:   4645         mov   r5, r8
  OSAL_IRQ_PROLOGUE();
 8001fea:   4673         mov   r3, lr


yes, the problem is M0-specific, M3 works fine.

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: strange behavior of the scheduler on STM32F070

Postby Giovanni » Mon Nov 12, 2018 8:53 pm

I searched the GCC bug tracker but nothing.

This is a minimal example of the problem:

Code: Select all


__attribute__((used))
void *retaddr;

__attribute__((noinline))
void xxxxtest(void) {
  retaddr = __builtin_return_address(0);

  asm volatile("" : : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
                        "r8", "r9", "r10", "r11", "r12");
}


The "asm volatile" is there to force the compiler to save all registers in the function, it marks those as clobbered.

The result:

Code: Select all

08001940 <xxxxtest>:

__attribute__((used))
void *retaddr;

__attribute__((noinline))
void xxxxtest(void) {
 8001940:   b5f0         push   {r4, r5, r6, r7, lr}
 8001942:   46de         mov   lr, fp
 8001944:   4657         mov   r7, sl
 8001946:   464e         mov   r6, r9
 8001948:   4645         mov   r5, r8
  retaddr = __builtin_return_address(0);
 800194a:   4672         mov   r2, lr
 800194c:   4b04         ldr   r3, [pc, #16]   ; (8001960 <xxxxtest+0x20>)
void xxxxtest(void) {
 800194e:   b5e0         push   {r5, r6, r7, lr}
  retaddr = __builtin_return_address(0);
 8001950:   601a         str   r2, [r3, #0]

  asm volatile("" : : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
                        "r8", "r9", "r10", "r11", "r12");
}
 8001952:   bc3c         pop   {r2, r3, r4, r5}
 8001954:   4690         mov   r8, r2
 8001956:   4699         mov   r9, r3
 8001958:   46a2         mov   sl, r4
 800195a:   46ab         mov   fp, r5
 800195c:   bdf0         pop   {r4, r5, r6, r7, pc}


I wonder which GCC version broke it.

Giovanni

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: strange behavior of the scheduler on STM32F070

Postby Giovanni » Tue Nov 13, 2018 6:56 am

Hi,

Update, I am modifying that code to not rely on __builtin_return_address() anymore. I have found a different method which is not dependent on this compiler feature. We could also report the bug on GCC tracker but I cannot depend on that.

Branches 17, 18 and trunk will be updated.

Thanks for finding this, it managed to stay hidden for way too long...

Giovanni

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: strange behavior of the scheduler on STM32F070

Postby Giovanni » Tue Nov 13, 2018 9:00 am

Hi,

Small update, GCC 5.4 seems to be fine, the thing broke in 6.x.

Giovanni

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: strange behavior of the scheduler on STM32F070

Postby Giovanni » Tue Nov 13, 2018 11:38 am

Added as bug #985.

I rewrote the IRQ epilogue code to not use __builtin_return_address(), incidentally the solution I found also seems to be faster in IRQ processing and uses less space.

I have not back-ported it yet to stable branches, it requires more testing, I would appreciate feedback from M0 users.

Giovanni

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: strange behavior of the scheduler on STM32F070

Postby Giovanni » Thu Nov 15, 2018 9:53 am

I removed the fix, it introduced more problems...

I opened a ticket here about GCC: https://bugs.launchpad.net/gcc-arm-embe ... ug/1803508

The recommended workaround is to use GCC 5.4.1 or earlier for Cortex-M0 devices.

Giovanni

electronic_eel
Posts: 77
Joined: Sat Mar 19, 2016 8:07 pm
Been thanked: 17 times

Re: strange behavior of the scheduler on STM32F070

Postby electronic_eel » Fri Nov 23, 2018 11:15 pm

Even when the bug is found and fixed in gcc-embedded, I guess it will take a long time till a fixed version will trickle through to the users, as most distributions, IDEs, and so on tend to do compiler upgrades very conservatively.

Would it be an option to detect an affected gcc version and Cortex-M0 with #ifdefs and then use special code to work around the problem?

One variant would be to disable optimization for this function, the other would be to replace the section with inline assembly.

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: strange behavior of the scheduler on STM32F070

Postby Giovanni » Sat Nov 24, 2018 6:33 am

I have found no clean workaround yet, the function dirties LR on entry, before you can inline assembler.

They are working on the problem already, I will add a version check in the next version.

Giovanni


Return to “Bug Reports”

Who is online

Users browsing this forum: No registered users and 8 guests