We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hallo
I wonder if there are any good methodes of calculating the stack size for ex user or IRQ stack size? Is there any "best practice"?
Or is it just add up the size of data structures and/ot ISR's??
/Thomas
Seems to be an error in that description.
The fill pattern 0xDEADDEAD is a 32-bit number, so it will consume four bytes. You should multiply with 4 and not with 8.
I think the multiply-with-8 comes from the fact that you should align and grow the stack in 8-byte steps for your ARM processor.
The number of overwritten fill patterns will indicate the high watermark of the stack usage. Note that it can be very hard to get your program to run down all alternatives, so you will either need a debugger, profiler or similar that can keep track of code coverage, or you will manually have to keep track of what input data it takes to activate different call branches.
When you have figured out the amount of stack your program is proven to _at_least_ consume, you will then have to figure out how much safety margin you will need. And depending on processor architecture or way the program is written, you may then have to add extra space for interrupt routines.
0xDEADDEAD
I commonly use 0xDEADBEAF :-)
Now we are all waiting for Cpt. Vince to inform us what constant he is using.
Based on his latest post, it would have to be 0xGOODEAD :-) :-) :-)
Hi Per,
Many thanks for your explanation.
So, if there are 50 0xDEADDEAD overwritten, then the stack space in bytes is 50*4 bytes. Am I right?
I am really confused with the stack alignment.
I had noticed that many months ago, there is a "PRESERVE8" in the older startup file of LPC23xx, and there is no "PRESERVE8" in the newer startup file of LPC23xx. And I have never rellay understand what is that, and what does that mean.
There are so many mysteries.
=> I think the multiply-with-8 comes from the fact that you should align and grow the stack in 8-byte steps for your ARM processor. <=
Is this related to LDRD and STRD instructions (double-word transfers)?
I heard that LDRD and STRD only available in ARMv5TE or newer, and LPC2378 is an ARM7TDMI-S cpu.
Why should I need that REQUIRE8 and PRESERVE8 and "align and grow the stack in 8-byte"?
And how to use REQUIRE8 and PRESERVE8 correctly?
My guess:
1. If an obj-file requires eight-byte alignment of the stack, use REQUIRE8 to inform the linker, and such an obj-file should only be called by an obj-file with PRESERVE8.
2. If an obj-file is well coded to preserve 8-byte alignment of the stack, use PRESERVE8 to inform the linker.
Am I right?
And what does "align and grow the stack in 8-byte" mean?
The stack size in bytes should be a multiple of eight?
Everything pushed/popped-up to/from the stack should be a multiple of eight? (How can I meet/do this?)
I just did some simple/stupid tests trying to understand something about "REQUIRE8 and PRESERVE8 and 'align and grow the stack in 8-byte'"
1. In the LPC2300.s, I set the IRQ_Stack_Size to 0x00000104 (260), and add a PRESERVE8 to this LPC2300.s file, it can still be compiled without any errors and warnings. So, I guess, PRESERVE8 will not do anything for the programmer (For example: check the stack/variable size).
2. I add a REQUIRE8 to the LPC2300.s, it can still be compiled, but I get some warnings:
source\LPC2300.s(887): warning: A1549W: Setting of REQUIRE8 but not PRESERVE8 is unusual
unusual???
linking... .\object\Product-01.axf: Warning: L6306W: '~PRES8' section lpc2300.o(RESET) should not use the address of 'REQ8' function Reset_Handler. .\object\Product-01.axf: Warning: L6306W: '~PRES8' section lpc2300.o(RESET) should not use the address of 'REQ8' function Undef_Handler. .\object\Product-01.axf: Warning: L6306W: '~PRES8' section lpc2300.o(RESET) should not use the address of 'REQ8' function PAbt_Handler. .\object\Product-01.axf: Warning: L6306W: '~PRES8' section lpc2300.o(RESET) should not use the address of 'REQ8' function DAbt_Handler. .\object\Product-01.axf: Warning: L6306W: '~PRES8' section lpc2300.o(RESET) should not use the address of 'REQ8' function IRQ_Handler. .\object\Product-01.axf: Warning: L6306W: '~PRES8' section lpc2300.o(RESET) should not use the address of 'REQ8' function FIQ_Handler.
So, I guess, even the KEIL's library does not align and grow the stack in 8-byte steps for the ARM processor.
From project.map:
lpc2300.o(RESET) refers to SWI_RTX.o(SWI_RTX) for SWI_Handler lpc2300.o(RESET) refers to lpc2300.o(STACK) for Stack_Top lpc2300.o(RESET) refers to __main.o(!!!main) for __main lpc2300.o(RESET) refers (Special) to stkheap2.o(.text) for __use_two_region_memory
John,
Have a look here:
"L6238E: <objname>(<secname>) contains invalid call from '<attr1>' function to '<attr2>' function <sym>. This linker error is given where a stack alignment conflict is detected in object code. The "ABI for the ARM Architecture" demands that code maintains 8-byte stack alignment at its interfaces. This allows efficient use of LDRD and STRD instructions (in ARM Architecture 5TE and later) to access 8-byte-aligned "double" and "long long" data types. Symbols like '~PRES8' and 'REQ8' are "Build Attributes" of the objects. PRES8 means the object PREServes 8-byte alignment of the stack. ~PRES8 means the object does NOT preserve 8-byte alignment of the stack (~ meaning NOT). REQ8 means the object REQuires 8-byte alignment of the stack. This link error typically occurs in two cases: 1) where assembler code (that does not preserve 8-byte stack alignment) calls compiled C/C++ code (that requires 8-byte stack alignment). 2) when attempting to link legacy objects with RVCT 3.x objects. Legacy objects that do not have these attributes are treated as '~PRES8', even if they do actually happen to preserve 8-byte alignment. For example: Error: L6238E: foo.o(.text) contains invalid call from '~PRES8' function to 'REQ8' function foobar This means that there is a function in the object foo.o (in the section named .text) that does not preserve 8-byte stack alignment, but which is trying to call function foobar that requires 8-byte stack alignment. A similar warning that may be encountered is: Warning: L6306W: '~PRES8' section foo.o(.text) should not use the address of 'REQ8' function foobar where the address of an external symbol is being referred to. There are two possible solutions to work-around this issue: 1) Rebuild all your objects/libraries using RVCT 3.x. If you have any assembler files, you will need to check that all instructions preserve 8-byte stack alignment, and if necessary, correct them. e.g. change: STMFD sp!, {r0-r3, lr} ; push an odd number of registers to STMFD sp!, {r0-r3, r12, lr} ; push an even number of registers The assembler will automatically mark the object with the PRES8 attribute if all instructions preserve 8-byte stack alignment, so it is no longer necessary to add the PRESERVE8 directive to the top of each assembler file. 2) If you have any legacy objects/libraries that cannot be rebuilt, either because you do not have the source code, or because the old objects must not be rebuilt (e.g. for qualification/certification reasons), then you must inspect the legacy objects to check whether they preserve 8-byte alignment or not. Use "fromelf -c" to disassemble the object code. C/C++ code compiled with ADS 1.1 or later will normally preserve 8-byte alignment, but assembled code will not. If your objects do indeed preserve 8-byte alignment, then the linker error L6238E can be suppressed with the use of "--diag_suppress 6238" on the linker command line. By using this, you are effectively saying "I guarantee that these objects are PRES8". The linker warning L6306W is suppressible with "--diag_suppress 6306". More information about linking with legacy objects/libraries and the "--apcs /adsabi" is given at: ">www.arm.com/.../1242.html"
The 8-byte stack alignment is required by the ARM ABI (specifically AAPCS). It originates in fact that the result of less-than-eight-byte aligned doubleword access LDRD/STRD is UNPREDICTABLE according to the ARM ARM. This does not mean that individual cores cannot deal with, say, a word aligned doubleword access -- some can in fact.
NB: Some ARM cores feature 64bit memory interfaces. These benefit from 8-byte aligned 64bit data access for performance reasons, despite the fact that most actually allow unaligned doubleword access :-)
> Why should I need that REQUIRE8 and PRESERVE8 and "align and grow > the stack in 8-byte"?
To be ABI compliant. It's a contract. Third party code (e.g. the C-library) might rely on it for various reasons.
> And how to use REQUIRE8 and PRESERVE8 correctly? > > My guess: > > 1. If an obj-file requires eight-byte alignment of the stack, use > REQUIRE8 to inform the linker, and such an obj-file should only > be called by an obj-file with PRESERVE8. > > 2. If an obj-file is well coded to preserve 8-byte alignment of the > stack, use PRESERVE8 to inform the linker. > > Am I right?
Yes.
Regards Marcus http://www.doulos.com/arm/
Hi Tamir and Marcus,
Many thanks for the information.
If I am not mistaken, the stack pointer must be 8-byte aligned when calling external functions, such as standard library functions. Between the function calls, you can push/pop in 4-byte chunks. As far as I know, the library that ships with Keil MDK does require 8-byte aligned stack (at least for some floating point operations.)
I still have some questions; this is really difficult to understand, for me.
My platform is NXP LPC2378, which is an ARM7TDMI-S CPU (ARMv4T), with a 128-bit wide memory interface and an accelerator architecture.
LDRD and STRD instructions are only available in ARM Architecture 5TE and later. So, I guess this means LDRD and STRD instructions are useless to me?
=> NB: Some ARM cores feature 64bit memory interfaces. These benefit from 8-byte aligned 64bit data access for performance reasons, despite the fact that most actually allow unaligned doubleword access :-) <=
So, does this mean, 8-byte aligned memory access still benefits performance in a LPC2378?
infocenter.arm.com/.../IHI0042C_aapcs.pdf 5.2.1.1 Universal stack constraints SP mod 4 = 0. The stack must at all times be aligned to a word boundary.
5.2.1.2 Stack constraints at a public interface SP mod 8 = 0. The stack must be double-word aligned.
Does this mean, "the stack must be double-word aligned" is not mandatory in ARM ABI?
Does REQUIRE8 mean that an obj-file certainly uses LDRD and STRD instructions? or it does not?
Even the KEIL's library does not align and grow the stack in 8-byte steps, so I guess that, To be ABI compliant is not very important?
Now I know that, for assembly code, the stack alignment has to be done by programmer. But how about C code? I guess it is done by KEIL compiler?
> I still have some questions; this is really difficult to understand, > My platform is NXP LPC2378, which is an ARM7TDMI-S CPU (ARMv4T), with > a 128-bit wide memory interface and an accelerator architecture.
That is proprietary external hardware to prefetch data from flash. Not what I was talking about. See below.
> LDRD and STRD instructions are only available in ARM Architecture 5TE > and later. So, I guess this means LDRD and STRD instructions are > useless to me?
Useless is probably the wrong word... If you use them on ARM7TDMI you'll likely get an UNDEF exeception.
> => NB: Some ARM cores feature 64bit memory interfaces. These benefit > from 8-byte aligned 64bit data access for performance reasons, despite > the fact that most actually allow unaligned doubleword access :-) <= > > So, does this mean, 8-byte aligned memory access still benefits > performance in a LPC2378?
At least not in the sense that I was referring to. My memory interface sits between core and the rest of the world as the core sees it. This is certainly not wider than 32 bits on ARM7TDMI.
> 5.2.1.1 > Universal stack constraints > SP mod 4 = 0. The stack must at all times be aligned to a word boundary. > > 5.2.1.2 > Stack constraints at a public interface > SP mod 8 = 0. The stack must be double-word aligned. > > Does this mean, "the stack must be double-word aligned" is not > mandatory in ARM ABI?
Mandatory only at "externally visible boundaries", i.e. your public API or your own references to third party code (libraries).
Example: Code calling your code might expect 8-byte aligned stack. If you violate that, things won't work. Since you can't know what someone else might expect, you have no choice but comply.
Silly example: Your function calls third party code. A strange way of saying NOP (most ARM architectures don't have an actual NOP instruction) is by saying
BIC sp, sp, #7
somewhere in the subroutine. This shouldn't have any visible effect provided that the stack was properly aligned when you where calling the subroutine. Violating the stack alignment contract would break your program.
Exceptions: Internal functions, that are not supposed to be used by anyone else and are not calling any functions themselves but your own (assuming you know what you are doing), may leave the stackpointer unaligned.
ISRs must generally not rely on an aligned stack and may have to ensure an aligned stackpointer if they are calling other functions.
> Does REQUIRE8 mean that an obj-file certainly uses LDRD and STRD > instructions? or it does not?
First of all REQUIRE8 is just a claim.
> Even the KEIL's library does not align and grow the stack in 8-byte > steps, so I guess that, To be ABI compliant is not very important?
This is not true. ABI compliance is utterly important.
Hi Marcus,
Many thanks for your explaination.
when i clean project then rebuild all then every thing were ok