Shop OBEX P1 Docs P2 Docs Learn Events
Need to leave space for stack? — Parallax Forums

Need to leave space for stack?

RaymanRayman Posts: 14,670
edited 2012-09-15 19:01 in Propeller 1
In C++ mode is the stack the same as in Spin, starting right after program memory?

Do I need to leave some amount of space for the stack?

Or, is the stack inside the LMM interpreter cog?

Comments

  • Dave HeinDave Hein Posts: 6,347
    edited 2012-09-14 12:17
    Yes, you need to leave space for the stack and the heap if you do any dynamic memory allocation. The C/C++ stack starts from the high end of memory and grows toward lower memory, which is opposite of the Spin stack. However, the heap does start immediately after the code space. You can check how much space you have left by writing a function that compares the address of a local stack variable to the address you get when you malloc a small amount of memory.
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-09-14 12:54
    Here's a function that I have used to check for remaining heap/stack space.
    void CheckStack(void)
    {
        char *ptr = malloc(1);
        printf("%8.8x %8.8x %d\n", ptr, &ptr, ((int)&ptr) - (int)ptr);
        free(ptr);
    }
    
    note: if there is a hole in the heap space from a previous malloc and free this will not give the correct answer. You would need to malloc a larger chunk to avoid the holes and then add that chunk size to the amount printed. This version should work fine if free has never been called before calling CheckStack.
  • RaymanRayman Posts: 14,670
    edited 2012-09-14 13:45
    Ok, thanks, that's important to know...

    Do you happen to know.... If I run a program through Spin2Cpp and the run with PropGCC, does it use any heap? Or, just stack?
  • Heater.Heater. Posts: 21,230
    edited 2012-09-14 14:05
    I would put my bets on spin2cpp not generating code that needs any heap. After all Soin does not have any dynamic memory allocation featues, everything is statically declared at compile time, so why should the C/C++ equivalent need it.

    To be sure just search the C/C++ output for any occurance of "malloc" or the C++ "new" operator.
  • Heater.Heater. Posts: 21,230
    edited 2012-09-14 14:07
    Dave,

    I can't help thinking that there must a symbol existing for the beginning of heap space. Just have a feeling I've seen it but can't remeber what it might be.
  • RaymanRayman Posts: 14,670
    edited 2012-09-14 14:09
    This is all good to know because it definitely changes my plans for trying to convert Graphics_Demo to C++...
    That code is rigged to use the upper part of RAM as buffer.
    But it now appears that that is where C++ is going to start it's stack...
  • TorTor Posts: 2,010
    edited 2012-09-15 01:20
    Dave Hein wrote: »
    Here's a function that I have used to check for remaining heap/stack space.[..]
    I ran it on my Linux desktop (obviously using long instead of int, but otherwise the same), and it tells me I have 128TB to work with, which is nice to know! :)

    -Tor
  • Heater.Heater. Posts: 21,230
    edited 2012-09-15 03:12
    Rayman,

    I was thinking...

    The initial C/C++ on the Prop will have it's stack pointer at the top of memory and the stack grows down. Thus writing over where you want your buffer.

    But any other C/C++ tasks started in other COGs will use a stack space that is defined by your main line and is in low memory, probably an array mixed in with all your other data.

    So what about this, write a tiny initial man line that starts up your real code in another COG, your real program is then using a stack defined by you. Then have the initial main line code kill itself (cogstop). BINGO all your code is now using stacks away from the top of memory and you can use that for your buffer.
  • David BetzDavid Betz Posts: 14,516
    edited 2012-09-15 03:20
    Heater. wrote: »
    Dave,

    I can't help thinking that there must a symbol existing for the beginning of heap space. Just have a feeling I've seen it but can't remeber what it might be.

    Heap space starts at ___heap_start (__heap_start from C).
  • ersmithersmith Posts: 6,054
    edited 2012-09-15 05:30
    Heater. wrote: »
    So what about this, write a tiny initial man line that starts up your real code in another COG, your real program is then using a stack defined by you. Then have the initial main line code kill itself (cogstop). BINGO all your code is now using stacks away from the top of memory and you can use that for your buffer.

    That's a clever solution. A simpler one though is to do something like:
    long stack[STACKSIZE];
    extern void realmain(void);
    
    _NAKED void main(void)
    {
      __asm__ ( " mov sp, %0\n"  : /* outputs */  : /* inputs */ "r"(&stack[STACKSIZE])  : /* clobbers */  "sp");
      /* now do your main() stuff... but do not try to return!!! */
      realmain();
    }
    

    The asm statement will set sp to &stack[STACKSIZE]. Obviously this will trash any local variables and anything stored on the stack, which is why I would suggest putting the "real" main into a separate function realmain(). You could get fancy and save the stack pointer and restore it later if you do want to try to return, but it's probably more trouble than it's worth :-).
  • Heater.Heater. Posts: 21,230
    edited 2012-09-15 05:55
    Eric,

    My solution is not so clever but it would read like poetry compared to yours, which looks like the baud rate is wrong on my serial port:)

    Yours is of course a lot more efficient in saving code space.

    Hmm.. actually if you are never planning to return from main(), which is the normal case in an MCU app, and you get no parameters for it there is no need for realmain(); Just put that in line assembler at the beginning of you existing main(). It just shifts the stack pointer and everything can proceed as normal after that.
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-09-15 09:50
    I think there is also a way to define the stack starting address at link time or maybe at load time. We had a discussion about this in the PropGCC forum, and I'm pretty sure there is a symbol defined at $8000 that can be overriden to another value. This way you can reserve space at the high end of memory. Eric or David, do you remember how this works?
  • ersmithersmith Posts: 6,054
    edited 2012-09-15 19:01
    Dave Hein wrote: »
    I think there is also a way to define the stack starting address at link time or maybe at load time. We had a discussion about this in the PropGCC forum, and I'm pretty sure there is a symbol defined at $8000 that can be overriden to another value. This way you can reserve space at the high end of memory. Eric or David, do you remember how this works?

    Good point, Dave -- that's an even easier way to change the stack. There's a symbol __stack_end that's used in the initial Spin boot code to set the PAR register, which in turn ends up determining the stack.

    I think defining __stack_end has to be done in assembler or in the linker. You can just add something like:
      __asm__( "  .global __stack_end\n  .equ __stack_end, 0x3000\n");
    
    to one of your C files to set the top of stack to 0x3000 (or whatever you want).

    This feature hasn't been tested much, though, so it'd be good to get some feedback on how well it works. I'm also not sure if it's supported in the XMM modes.
Sign In or Register to comment.