-
Notifications
You must be signed in to change notification settings - Fork 3k
Fix stack aligment. #812
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix stack aligment. #812
Conversation
I have been experimenting with mbed-rtos on a LPC1768 chip and have had problems getting anything to run at all. I would get HardFault crashes on bootup. Even just compiling the rtos_basic minimal example in the online compiler would crash. I finally had some time to look more closely into this. The first thing I noticed was that when compiling in debug mode the system would boot up. So it seems that unoptimized code runs fine. Then I noticed that rt_init_stack (HAL_CM.c) was passed stack pointers that were not 8 byte aligned. There is code there that is supposed to align the stack, but it is not correct. I fixed the alignment code and added alignment attributes to other stacks I could find. I can now successfully boot rtos_basic and see the leds flashing. |
If the size variable ends up being odd then won't the stack pointer become unaligned after your change? The old code used to 8-byte align the top of the stack, which is what matters since that is what SP will actually be initialized to and will then grow downwards to the bottom. |
Yes, maybe it would also be appropriate to protect agains odd stack sizes. Should absolutely everything be allowed, or should there be some expectation on what is reasonable? |
fcf3435
to
f1047f3
Compare
Isn't an attribute non generic, gcc specific ? How to reproduce the problem? Rtos basic example for lpc1768, built via tools scripts will show this behaviour? |
I was very surprised to see this problem. As I said, even rtos_basic with the online compiler will crash on my device which is a mbed LPC1768. Hence I did a local build for debugging with openocd/gdb. I have compiled with both gcc-arm-none-eabi-4_7-2012q4 and gcc-arm-none-eabi-4_9-2014q4 with the same result. |
There are some generic alignment macros in libraries/net/lwip/lwip-sys/arch/cc.h. |
I can't reproduce any problems on my mbed LPC1768 with the rtos_basic sample when using GCC_ARM or the mbed online compiler. I imported the rtos_basic sample from http://developer.mbed.org/teams/mbed/code/rtos_basic/ for my testing. I suspect that you are hitting some other issue that needs to be further investigated. The only thing that I could see really going wrong on the online compiler side is maybe somehow picking up an old version of the sample that had some other issue or picking a target other than LPC1768 when performing the build. Your stack alignment change in rt_init_stack() looks wrong to me as it now makes no attempt to align the top of the stack which is what the task's stack pointer is actually set to. There is no real reason to align the bottom of the stack. |
The odd stack happens with osTimerThread. In my build the stack as allocated by the linker is odd. The array is of type unsigned char, so I assume it is appropriate for the linker to give it an odd start So when rt_init_stack() runs Then the test ((U32)stk & 0x04) is true, but this does not help much since stk-- sets stk to 0x10000a99 which is still odd. So my conclusion is that the code expects the stack to be 4 byte aligned and only tries to adjust the stack to be 8 byte aligned in that case. If the stack passed is completely unaligned the alignment |
Thanks for the extra information. That makes things a lot clearer. As you say, the underlying problem is that rt_init_stack() expects p_TCB->stack to be 4-byte aligned. It definitely seems like the current osThreadDef() macro definition breaks that assumption. A few more comments:
diff --git a/libraries/rtos/rtx/TARGET_CORTEX_M/cmsis_os.h b/libraries/rtos/rtx/TARGET_CORTEX_M/cmsis_os.h
index f19a723..da63205 100644
--- a/libraries/rtos/rtx/TARGET_CORTEX_M/cmsis_os.h
+++ b/libraries/rtos/rtx/TARGET_CORTEX_M/cmsis_os.h
@@ -335,9 +335,9 @@ int32_t osKernelRunning(void);
extern osThreadDef_t os_thread_def_##name
#else // define the object
#define osThreadDef(name, priority, stacksz) \
-unsigned char os_thread_def_stack_##name [stacksz]; \
+unsigned int os_thread_def_stack_##name [stacksz / sizeof(unsigned int)]; \
osThreadDef_t os_thread_def_##name = \
-{ (name), (priority), (stacksz), (os_thread_def_stack_##name)}
+{ (name), (priority), (stacksz), (unsigned char*)(os_thread_def_stack_##name)}
#endif
/// Access a Thread definition. |
@perkristian ,what do you think above Adam's comments above? |
Stack should be 8 byte aligned on ARM. Fix the automatic correction of the alignment in rt_init_stack, and make sure that all stacks are aligned by the compiler.
I agree with Adam's comments. I have pushed a new commit which changes the relevant interfaces to be uint32 pointers. There is still the issue of the Thread interface, but I assume that cannot be changed since it is external. |
What issue in the interface? That Thread ctor defines stack parameter as pointer to unsigned char? |
Yes, any stack parameters pointing to unsigned char may be unaligned and we the crashes will be random depending on the build. |
The similar check you proposed in the beginning, can be applied in the ctor there, to align the stack pointer if it's not NULL. |
I like @perkristian current proposal. @0xc0170 I wonder how many people would actually be impacted if the constructor was changed to take a uint32_t* instead. I suspect most people just pass in NULL. I would think that the compiler error would be pretty clear as to what they need to change if it does impact them. |
Thanks guys. I'll merge this. |
Stack should be 8 byte aligned on ARM.
Fix the automatic correction of the alignment in rt_init_stack,
and make sure that all stacks are aligned by the compiler.