Reputation: 165
I am working on an ARM Cortex-M4 processor using IAR Embedded Workbench. When the main stack overflows I get a bus fault. I have therefore written a small function in assembly to check if the bus fault was caused by a stack overflow, set the stack pointer and call a dedicated stack overflow handler.
The following code shows the function and it works fine. My problem is that I had to subtract 1 from the labels in the two LDR instructions and I don't understand why.
StackBegin: DC32 SFB(CSTACK) ; Start of main stack
StackEnd: DC32 SFE(CSTACK) ; End of main stack
BusFault_Handler:
LDR R0, StackBegin-1 ; No idea why we need to subtract 1
CMP SP, R0
IT GT
BGT BusFault_Post_Handler ; Call if SP is OK
LDR SP, StackEnd-1 ; On stack overflow, set SP to top of main stack; No idea why we need to subtract 1
B MainStackOverflow_Handler
If I don't subtract 1, the LDR instructions load data one byte after the label. StackEnd contains the value 0x20000400, but SP is loaded with 0x5F200004 unless I subtract 1 from the label. The 0x5F is the first byte in BusFault_Handler.
Can anyone explain why I need to subtract 1. Have I configured something wrong. I have checked that the data is word (4 byte) aligned.
Upvotes: 3
Views: 554
Reputation: 3881
When the calculating the address for a label defined when in thumb-mode the assembler will automatically set the least significant bit since it assumes that code labels are branch-targets and nothing else. Thus, when the StackBegin
and StackEnd
labels are defined as part of the code, they will have the LSB set.
To avoid this problem make sure that the assembler is in data-mode when the StackBegin
and StackEnd
labels are defined.
THUMB
BusFault_Handler:
LDR R0, StackBegin
CMP SP, R0
IT GT
BGT BusFault_Post_Handler ; Call if SP is OK
LDR SP, StackEnd ; On stack overflow, set SP to top of main stack;
B MainStackOverflow_Handler
DATA
StackBegin: DC32 SFB(CSTACK) ; Start of main stack
StackEnd: DC32 SFE(CSTACK) ; End of main stack
THUMB
Upvotes: 6