Stack initialization is performed in the prologue of "main()". This
suits most cases. However, you redefine startup, and needs some space allocated on
the stack, the stack has to be explicitly initialized. For example:
#define STACKINITIALVALUE 0x0280
NAKED(_reset_vector__)
{
/* Initialise the stack */
__asm__ __volatile__("mov %0, r1"::"i" (STACKINITIALVALUE));
/* Your startup code goes here */
__asm__ __volatile__("br #main"::);
}
|
*** NOTE *** DO NOT USE the register definitions PC, SP and SR, which some
other MSP430 tools (e.g. IAR) recognise. The
as assembler in
binutils does not recognise these names. Instead use r0,
r1 and r2.
The stack finally will be initialized in main(). Normally, the initial
stack pointer address is at top of RAM. If you want to reserve some RAM space,
which is not accessible by the compiler, you may specify -mno-stack-init
flag and then define startup as follows:
#define STACKINITIALVALUE 0x0280
NAKED(_reset_vector__)
{
char a[100]; /* Will be allocated on the stack */
__asm__ __volatile__("mov #__data_start ,r1"::);
/* Your startup code goes here */
/* Initialise the stack */
__asm__ __volatile__("mov %0, r1"::"i" (STACKINITIALVALUE));
/* Jump to main */
__asm__ __volatile__("br #main"::);
}
|
If you do not make the function declaration NAKED, note that on function
exit, the frame pointer value will be added to r1. Therefore, the stack
initialisation should be as follows:
...
__asm__ __volatile__("mov %0, r1" :: "i" (STACKINITIALVLUE) );
__asm__ __volatile__("sub #.L__FrameSize__reset_vector__, r1"::);
...
|
*** NOTE *** The frame pointer register (r4) and arguments pointer register (r5)
values are compiled in a mysterious way. Use them with care.
The variable ".L__FrameSize_[function name]" is defined by the
compiler, and has a value of the stack space required by the function. For
example:
#define STACKINITIALVALUE 0x280
void set(char *a) {} // dummy
void reset(char *a) {} // dummy
void _reset_vector__()
{
__asm__ __volatile__("mov #__data_start ,r1"::);
{
char a[100];
set(a);
reset(a);
}
__asm__ __volatile__("mov %0, r1"::"i" (STACKINITIALVALUE));
__asm__ __volatile__("sub #.L__FrameSize__reset_vector__, r1"::);
__asm__ __volatile__("br #main"::);
}
int main()
{
...
}
|
compiled with
$ msp430-gcc -O m.c -mendup-at=main -mno-stack-init
|
will result in:
---
a.out: file format elf32-msp430
Disassembly of section .text:
0000fc00 <__zero_vector>:
fc00: 30 40 04 fc br #0xfc04
0000fc04 <_unexpected_>:
fc04: 00 13 reti
0000fc06 <set>:
fc06: 30 41 ret
0000fc08 <reset>:
fc08: 30 41 ret
0000fc0a <_reset_vector__>:
fc0a: 31 80 64 00 sub #100, SP ; #0x0064
fc0e: 31 40 00 02 mov #512, SP ; #0x0200
fc12: 0f 41 mov r1, r15
fc14: b0 12 06 fc call #-1018 ; #0xfc06
fc18: 0f 41 mov r1, r15
fc1a: b0 12 08 fc call #-1016 ; #0xfc08
fc1e: 31 40 80 02 mov #640, SP ; #0x0280
fc22: 30 40 30 fc br #0xfc30
fc26: 31 80 64 00 sub #100, SP ; #0x0064
fc2a: 31 50 64 00 add #100, SP ; #0x0064
fc2e: 30 41 ret
0000fc30 <main>:
fc30: 30 40 30 fc br #0xfc30
....
---
In this case, the
"RESERVE_RAM" attribute to the
"main()"
function would be a simpler way to achieve the same effect.