automatically relocating the Stack pointer

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi guys:

I've been on the issue of relocating the stack pointer at program startup and searched the entire forum for some clue. I've found some posts on the issue of relocating stack, but manually:

in this post
https://www.avrfreaks.net/index.p...

this way is suggested

-Wl,--defsym=__stack=(stack address)

in this other post
https://www.avrfreaks.net/index.p...

this way is suggested

#include 

#define NAKED  __attribute__((naked))
#define USED __attribute__((used))
#define INIT2 __attribute__((section(".init2")))

static void myInitSP(void) NAKED USED INIT2;
static void myInitSP(void)
{
  SP = (stack address);
} 

I need a way to automatically position the SP just below the .data section.
I'm using an ATXmega128A1 with 64K external SRAM and since I'm going to use Freertos on this system, the RAMEND provided setup for the Xmega128A1 is somewhat "wasteful" in the sense that I left almost 8K of internal SRAM for the stack. Since Freertos manages it's stack in a per task basis, I don't see the point in left an 8K of sram chunk sitting idle (add to this the chunk of external SRAM that isn't accessible).

The solution I can imagine is something like this (a mix of two solutions)

Having passed to the linker the command

-Wl,--section-start,.data=0x802300,--defsym=__heap_end=0x80ffff

I've try this

#define NAKED  __attribute__((naked))
#define USED __attribute__((used))
#define INIT2 __attribute__((section(".init2")))

static void myInitSP(void) NAKED USED INIT2;
static void myInitSP(void)
{
  SP = .data - 1;
} 

But the compiler (or actually the linker I suppose) didn't liked it. I think is a syntactical problem. I don't know what is the syntaxis for this kind of symbol referencing. In fact I don't know if this is possible at all.

Anyways, could you here suggest a way to achieve this? My goal is to put this kind of modifications in a "startup file" that is easy to be #included at the beginning of the main file (after the library includes) avoiding to write command line switches as I've been doing with EBI and port initialization.

Tks in advance
Nachus

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

nachus001 wrote:

#define NAKED  __attribute__((naked))
#define USED __attribute__((used))
#define INIT2 __attribute__((section(".init2")))

static void myInitSP(void) NAKED USED INIT2;
static void myInitSP(void)
{
  SP = .data - 1;
} 

The compiler definitely won't like that.
Dot is a binary operator.
Also, a section named .data does not necessarily produce a symbol with that name.
I think the default linker script provides a symbol for what you want,
but I don't remember it.

Iluvatar is the better part of Valar.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

-Wl,--section-start,.data=0x802300,--defsym=__heap_end=0x80ffff,--defsym=__stack=0x8022ff

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok:

That's what I did, and it worked!

extern uint8_t __data_start; // declare the symbol as extern, so we can catch it

#define NAKED  __attribute__((naked))
#define USED __attribute__((used))
#define INIT2 __attribute__((section(".init2")))

static void myInitSP(void) NAKED USED INIT2;
static void myInitSP(void)
{
  SP = (uint16_t)((&__data_start) -1);
} 

When I load the program The SP gets initialized to .data-1, The X register gets initialized to the last allocated sram address and the Z register gets initialized with 0x0366 (dunno what's up with that value) but the Y register (frame pointer), still gets initialized to 3FFF (the RAMEND) I think I should change that register to hold the same value as the SP.. Is this right?

Cheers
Nachus

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why that complicated? If you already know the .data start address from
the beginning (since you manually assign it on the commandline), why
don't you simply set the top of stack in the same step, as I suggested?

Btw., the various attributes can be combined:

static void foo(void) __attribute__((naked, used, section(".init2")));

Note that even-numbered .initN and .finiN sections are reserved for the
library. Users should stick to using odd-numbered sections.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Note that even-numbered .initN and .finiN sections are reserved for the
library. Users should stick to using odd-numbered sections.

I never knew that! Does it actually say that on this page in the manual?:

http://www.nongnu.org/avr-libc/u...

(it seems to say "User definable" on some that are both odd and even?)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dl8dtl wrote:
Why that complicated? If you already know the .data start address from
the beginning (since you manually assign it on the commandline), why
don't you simply set the top of stack in the same step, as I suggested?

Hi Joerg, I do this because I need to ease the system init and config to the guys that do software dev here (my work is hardware dev and driver implementation for that hardware). I did this way before, but I got many questions for "system non working", "drivers with erratic operation", and all of that was commandline switch problems. I'm trying to put all the setup --as far as possible-- in a single init file to be #included after the library #includes at top of main.c

Quote:

Btw., the various attributes can be combined:

static void foo(void) __attribute__((naked, used, section(".init2")));

Note that even-numbered .initN and .finiN sections are reserved for the
library. Users should stick to using odd-numbered sections.

I did my example in a hurry by copypasting, but your code is clever. I didn't knew that issue on the sections !! Should I move my setup to the .init3 ?
What are the potential problems that would arise from letting my setup sitting in .init2 ?

On the other hand, I added code to change the Y register to the SP set value and not the Xmega RAMEND
I have to see yet what happens when calling functions.

Thank you
Nachus

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> I do this because I need to ease the system init and config to
> the guys that do software dev here

Well, all that commandline switch business can be automated using
a Makefile. I agree that subtracting 1 from the .data start address
is unfortunately a little more work if you want to do it in a
Makefile. I assumed your addresses are fixed anyway (once they
initially settled).

> I didn't knew that issue on the sections !!

As Cliff pointed out, the avr-libc manual is more accurate than my
simple even/odd rule of thumb.

> Should I move my setup to the .init3 ?

Yes, I think so.

> What are the potential problems that would arise from letting my
> setup sitting in .init2 ?

You depend on the linker about which of the stack initializations
will be arranged first: the one from the library startup code, or
your own one. I'm pretty sure you'd like to get your own one
*past* the librarie's one ...

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.