6

I have created a section called .co_stack in my C file and have an array called pulStack to define the area.

#define STACK_SIZE       0x00003000      /*!< Stack size (in Words)           */
__attribute__ ((section(".co_stack")))
unsigned long pulStack[STACK_SIZE];

My gcc linker script defining the stack section looks like this

.co_stack : {
    _fstackptr = ORIGIN(ram) + LENGTH(ram) - 4;
    _fstacksize = 0x00003000 * 4;       
    . = (_fstackptr - _fstacksize);
    *(.co_stack .co_stack.*)
}

As you can see I end up defining the stack size in 2 places. One as STACK_SIZE in my .c file and _fstacksize in my .ld file.

How can I define this in just one place?

For e.g. I want to create a variable pulStackSize as follows.

const unsigned long pulStackSize = sizeof(pulStack);

I want to define _fstacksize in .ld file as

_fstacksize = STACK_SIZE * 4;

If I do this, I get an error saying stack overflowed by 48K bytes.

How can I import a symbol from .c to my .ld file ?

Vishal Sagar
  • 498
  • 2
  • 4
  • 13
  • STACK_SIZE does not have a symbol, it is a MACRO. You can import into ld file using EXTERN – joy Jun 07 '13 at 14:49

1 Answers1

12

Some solutions (to the more general question "how to share values between C and LD script?"):

1) (NOTE: for this solution I'll assume that you are using a recent version of GNU ld, docs here : http://www.math.utah.edu/docs/info/ld_3.html)

You can associate an absolute value to a symbol inside the script by defining it outside the section compounds (e.g. at the very begin of the script). Than you can import the symbol in C by defining it as extern. Beware that the value you need in C is the ADDRESS of the symbol:

Script:

StackSize = 0x00003000 * 4; /* the size */
.co_stack : {  
    _fstackptr = ORIGIN(ram) + LENGTH(ram) - 4;
    _fstacksize = StackSize;       
    . = (_fstackptr - _fstacksize);
    *(.co_stack .co_stack.*)
}

C:

extern long StackSize;
#define STACK_SIZE (((size_t)&StackSize)/sizeof(long))

This solution may impose restrictions in the use of the value obtained, e.g. most compilers will not accept a line like this:

long my_stack[STACK_SIZE];

but you don't need it anymore, since you can define the symbol "my_stack" inside the script and import it as "extern long my_stack[];". I think that it's an acceptable limitation anyway.

2) Another way is to define in the script two symbols located at the start and at the and of the section and import them as "extern char" in C. The size of the section in bytes is the difference of their two addresses. This solution has the same limitation of (1)

3) If your linker is not smart enough, you can use the C preprocessor to produce a suitable script at compilation time by expanding the macro STACK_SIZE as in C. You have to

a) create the file "stacksize.h" containing

#define STACK_SIZE 0x3000

b) Add the line #include "stacksize.h" at the beginning of the script and use STACK_SIZE whenever you need. Save the script as "ldscript.c".

c) in your makefile (or equivalent compilation procedure) invoke the preprocessor. If you have GCC the command is:

gcc -P -E ldscript.c -o ldscript.ld

Please note that some gcc versions give a special meaning to the input file's extension. So I suggest to use ".c", it's the safest way.

d) Use the file "ldscript.ld" produced by the C preprocessor as link script

Nic Dahlquist
  • 1,005
  • 12
  • 15
Giuseppe Guerrini
  • 4,274
  • 17
  • 32
  • Thanks for the answers. (1) and (2) are not applicable because I need to define the stack's last address in my vector table. I can't do this for the reasons you mentioned in (2). I tried doing (3) but no ldscript.ld is generated. Instead a message "arm-none-eabi-gcc.exe: warning: ldsource.script: linker input file unused because linking not done". Hence (3) is also not helpful. Finally (4) seemed to be right. But I see ". = _fstackptr - SIZEOF(.co_stack);" doesn't work as SIZEOF() is applicable to OUTPUT section only whereas I need size of input section. – Vishal Sagar Jun 12 '13 at 07:56
  • @dexkid Uhm, tried (3) with some different input file extensions. All worked, except ".ld" (as INPUT). Your gcc version probably interprets the ".source" extension as ld script! Mine indeed uses ".src" and ".ld". I suggest you to choose a different extension for the input file (e.g. ".c", although it's quite weird). Please let me know if you got any success. – Giuseppe Guerrini Jun 12 '13 at 11:06
  • 1
    (3) worked for me with a .c extension instead of .src. Thanks for the guidance. – Vishal Sagar Jun 12 '13 at 13:45
  • Ok, I'll change the file extension in my answer. Thank you. – Giuseppe Guerrini Jun 12 '13 at 14:01