How to place stack at the start of RAM using Coldfire linker file.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to place stack at the start of RAM using Coldfire linker file.

1,171 Views
cstevens
Contributor I

I would like to place my stack at the bottom of RAM, before any other data segments, to protect against stack overflow problems.  How can I tell the linker to reserve some space at the beginning of RAM for my stack?  When I try as described below, the Flash programmer rejects the resulting S19 file.

 

By default, the linker file places the stack right above the data segment.  But in that situation, if the stack overflows (growing down due to nesting function calls too deeply or an unexpected worst case of many ISRs at the same time) this will lead to silently overwriting parts of the data segment.  I don't want to detect this via writing some sentinel values to the stack and occasionally checking to see if they have been overwritten.  I want to prevent my data from being (possibly undetectably) overwritten.  If the stack is located at the bottom of RAM instead of the top, then when the stack overflows below the start of physical RAM, I will get an immediate exception and hardware reset.  The fact that my processor is resetting because of a stack overflow indicates that my code still has a problem that needs to be fixed, but a hardware reset will prevent the program from silently just continuing to run after data corruption.

 

Here is an extract from my .LCF file for Codewarrior for Coldfire 7.2.2.

 

  .text :

  {

    *(.init)

    *(.text)

    *(.rodata)

  } > rom

 

  .stack :

  {

    ___SP_END = .;

    . = . + ___stack_size;

    . = ALIGN(4);

    __SP_INIT = .;

    ___SP_AFTER_RESET = __SP_INIT;

  } > ram

 

  .data : AT(___DATA_ROM)

  {

    ___DATA_RAM = .;

    *(.data)

    . = ALIGN(4);

    ___DATA_END = .;

  } >> ram

 

The .xMAP shows that the stack is located at the beginning of RAM. Yay!

 

But the resulting .S19 file is filled with records that explicitly write ___stack_size worth of 0 bytes to RAM.  That wouldn't really be a problem, but the Flash Programmer gets mad at the S19 file because it is only allows specifying Flash locations not RAM locations.  The LCF file does not use ZERO_FILL_UNINITIALIZED.  It seems to be that line ". = . + ___stack_size" that moves the location has the side effect of writing all those 0 bytes.  Here is an extract of the generated S19 file.  You've got the end of the .text segment and then all those explicit zeroes starting at RAM 0x20000000.


S325000114A04572726F723A20466C61736820636F7079206661696C6564000A3F3F3F0A446FEF

S325000114C0776E6C6F6164204661696C6564000000000001AC002020202020202020202828FE

S325000114E0282828202020202020202020202020202020202020881010101010101010101005

S325000115001010101010444444444444444444441010101010101041414141414101010101D2

S325000115200101010101010101010101010101010110101010101042424242424202020202A0

S321000115400202020202020202020202020202020210101010200000000000000008

S325200000000000000000000000000000000000000000000000000000000000000000000000BA

S3252000002000000000000000000000000000000000000000000000000000000000000000009A

S3252000004000000000000000000000000000000000000000000000000000000000000000007A

S3252000006000000000000000000000000000000000000000000000000000000000000000005A

S3252000008000000000000000000000000000000000000000000000000000000000000000003A

S325200000A000000000000000000000000000000000000000000000000000000000000000001A

S325200000C00000000000000000000000000000000000000000000000000000000000000000FA

S325200000E00000000000000000000000000000000000000000000000000000000000000000DA

S325200001000000000000000000000000000000000000000000000000000000000000000000B9

S32520000120000000000000000000000000000000000000000000000000000000000000000099

 

How do I tell the linker to reserve some space at the beginning of RAM for my stack without causing all those 0 bytes to be written to the S19 file?

Labels (1)
0 Kudos
5 Replies

688 Views
Carlos_Musich
NXP Employee
NXP Employee

Hi C Stevens,

Please note that in the project you can find references to  ___SP_INIT(3 underscores), __SP_INIT(2 underscores), _SP_INIT(1 underscores).

In startcf.c you will find the following code 

/* Pre-init SP, in case memory for stack is not valid it should be setup using

MEMORY_INIT before __initialize_hardware is called

*/

lea __SP_AFTER_RESET,a7; 

/* initialize memory */

MEMORY_INIT

/* initialize any hardware specific issues */

jsr __initialize_hardware

/* setup the stack pointer */

lea _SP_INIT,a7

Please notice that _SP_INIT(with one underscore) located in startcf.c references __SP_INIT (with 2 underscores) located in .lcf. And this is the value that the stack pointer will use as base in the rest of the application.

Hope this helps.

Carlos

0 Kudos

688 Views
cstevens
Contributor I

I was not asking how to reference the stack pointer from C.  I was asking why does Codewarrior fill up my S19 file with a bunch of explicit 0 bytes when I attempt to place the stack at the bottom of RAM instead of the top of RAM.  The 0 bytes wouldn't even be a problem to me except that the flash programmer doesn't like seeing an S19 file that references RAM.

0 Kudos

688 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello Stevens:

Did you resolve this?

I think you are correct that the address relocation (.) causes those 0's. But I do not see why you used that syntax. You can simply use symbols/tags without moving the location counter, like next:

  .stack :

  {

    ___SP_END = .;

    ___SP_INIT = ___SP_END + ___stack_size - 4;

    . = ALIGN(4);

  } > ram

  __SP_INIT = ___SP_INIT;

  .data : AT(___DATA_ROM)

  {

    ___DATA_RAM = .;

    *(.data)

    . = ALIGN(4);

    ___DATA_END = .;

  } >> ram



Regards!
Jorge Gonzalez

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

688 Views
cstevens
Contributor I

If you do that then no space is reserved for the stack.  Yes you have created a symbol __SP_INIT at . + stacksize, but you will notice that the .stack section itself is 0 bytes long and the .data section now starts at the same location at the .stack section.  You have placed your stack and your data sections in the same RAM locations at the same time -- certainly not good.  Now the stack is guaranteed to overwrite the data!

0 Kudos

688 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Actually you are correct, I did not think of that, sorry. Then the trick would be to create a new memory segment just for the stack. Something like the next: (not sure what device you have, so it is just an example):

Lets assume you will have 0x1000 of stack.

MEMORY

{

  # ... flash segments ... #

  ram      (RWX) :  ORIGIN = 0x20001400,  LENGTH = 0x00004C00  # Make sure that ram length is TOTAL RAM - STACK

  stack_ram (RWX) :  ORIGIN = 0x20000400,  LENGTH = 0x00001000  # NEW segment

}

then:

  .stack :

  {

    ___SP_END = .;

    ___SP_INIT = ___SP_END + ___stack_size - 4;

    . = ALIGN(4);

  } >> stack_ram

  __SP_INIT = ___SP_INIT;

  .data : AT(___DATA_ROM)

  {

    ___DATA_RAM = .;

    *(.data)

    . = ALIGN(4);

    ___DATA_END = .;

  } >> ram

Hope this helps!


Regards!
Jorge Gonzalez

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos