This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/MSP430FR5969: increasing stack space

Part Number: MSP430FR5969

Tool/software: TI C/C++ Compiler

My application's stack is overflowing and stepping on data in the lower parts of RAM. I thought about trying to move everything except the stack out of SRAM and into FRAM but even in that case, I would only have 2k of stack space which I'm concerned might be insufficient. I therefore believe that moving the stack is the better choice. To do that I've been considering:

Moving stack into HIFRAM
This would be the ideal choice because all I would have to do is point the stack section at the top of HIFRAM and I would have plenty of room. Unfortunately, according to the related post from 2016, it seems that the stack pointer register is only 16bits. Is this still the case or has the register size been increased? If $sp is still 16 bits, is there a work around for this problem?

Moving part of ROM into HIFRAM
This option would be more difficult, but I could potentially allocate a portion of the ROM that is currently in lower memory into HIFRAM. Then I could move the stack into the available space. Does this seem like a realistic option?

  • Setting the stack pointer in HIFRAM isn't quite that easy. What happens if the compiler generates instructions that use the value in the stack pointer? Unless you have compiled with -mlarge, it isn't going to get all 20 bits.

    Moving code into HIFRAM also means compiling with -mlarge which is going to increase code size by quite a bit.

    You might want to look at why you are using so much stack space.

  • I'm already using "-mlarge" so that isn't the problem. The issue is that if $sp is constrained to a 16bit register and therefore a 16bit pointer, there is no way it can directly access the HIFRAM range which requires 20bit addressing. I'm also examining the stack, but reducing stack usage will require fairly substantial development effort. If I can create more room for the stack, that's preferable.

  • The stack pointer on the FR5969 (ancient LauncPad) I have sitting in front of me is 20 bits wide.

    0x4408:
        04408: 81 01 00 40               MOVA    #0x14000, SP
        0440c: b2 40 10 a5 40 01         MOV     #0xa510, &0x0140
        04412: b2 40 00 a5 60 01         MOV     #0xa500, &0x0160
    (mspdebug) step
        ( PC: 0440c)  ( R4: 0ffff)  ( R8: 0ffff)  (R12: 00004)  
        ( SP: 14000)  ( R5: 0ffff)  ( R9: 00112)  (R13: f2375)  
        ( SR: 00000)  ( R6: 0ffff)  (R10: 01af8)  (R14: 01a1a)  
        ( R3: 00000)  ( R7: 0a55a)  (R11: 0ffff)  (R15: 04400)  

  • update:

    I modified the linker file to point the stack at the top of HIFRAM:

    .stack (ORIGIN (HIFRAM) + LENGTH(HIFRAM)) :
    {
        PROVIDE (__stack = .);
        *(.stack)                                                                                                                             
    }
    

    The map file confirms that this worked:

    .stack          0x0000000000013fff        0x0                                                                                                                                                                         
                    0x0000000000013fff                PROVIDE (__stack, .)
    *(.stack)
    

    Unfortunately, this broke my application. Addressing appears to be quite messed too. For instance, my gdb backtrace is way outside the addressable range:

    #0 USCI_A0_ISR () at src/msp430/uart.c:54
    #1 0x015b9e00 in ?? ()
    #2 0xe6000000 in ?? ()
    #3 0x0000144d in ?? ()
    #4 0x40000000 in ?? ()
    #5 0x180000da in ?? ()
    #6 0x01009a21 in ?? ()
    #7 0x04000000 in ?? ()
    #8 0x9200001c in ?? ()
    #9 0x040000db in ?? ()
    .
    .
    .

    More strange behavior in gdb:

    rbGetElemAddr (rb=0x40ffffff, index=65535) at ../core/rb.c:160
    (gdb) p	&rb
    $9 = (const RingBuffer * const *) 0x13eed
    (gdb) p	index 
    $10 = 65535
    (gdb) p	&index 
    $11 = (const unsigned int *) 0x13eeb
    (gdb) x/24xb 0x13eeb
    0x13eeb:        0xff    0xff    0xff    0xff    0xff    0x40    0x02    0x01
    0x13ef3:        0x00    0xc4    0xb1    0x00    0x00    0x40    0x02    0x01
    0x13efb:        0x00    0x00    0x00    0x00    0x00    0xe4    0xe0    0x00
    (gdb) set *0x13eeb=0
    (gdb) x/24xb 0x13eeb
    0x13eeb:        0x00    0x00    0xff    0xff    0xff    0xff    0xff    0xff
    0x13ef3:        0xff    0xff    0xff    0xff    0xff    0xff    0xff    0xff
    0x13efb:        0xff    0xff    0xff    0xff    0xff    0xff    0xff    0xff
    

    I'm still investigating but if you have any insights I'd appreciate it.

  • I would expect things to go very badly indeed with an unaligned stack pointer.

  • Good point. I was able to fix the alignment issue, and my application now runs perfectly with stack pointed at the top of HIFRAM. I'm not sure if I solved this in the "recommended" way, but for anyone who ends up reading this, I tried the following:

    Using ALIGN(2) (does not work)

    .stack (ORIGIN (HIFRAM) + LENGTH(HIFRAM)) :
    {
        PROVIDE (__stack = .);
        . = ALIGN(2); /* this doesn't work */
        *(.stack)
    }
    

    The ALIGN(2) command increments the address to multiple of 2 boundary. The map file shows the following:

    .stack          0x0000000000013fff        0x1                                                                                                                                                                         
                    0x0000000000013fff                PROVIDE (__stack, .)
                    0x0000000000014000                . = ALIGN (0x2)
     *fill*         0x0000000000013fff        0x1
     *(.stack)
    

    Even though the top of HIFRAM (or the bottom of the stack) seemed to now be aligned to 0x14000, the stack pointer was still not aligned:

    (gdb) info registers 
    pc             0x59e2	0x59e2 <main>
    sp             0x13ffb	81915

    2. Manually aligning stack section (does work)

    .stack (ORIGIN (HIFRAM) + LENGTH(HIFRAM) - 1) :                                                                                         
    {
        PROVIDE (__stack = .);
        *(.stack)
    }
    

    Decrementing the top of HIFRAM aligns it to an even value as shown in the map file:

    .stack          0x0000000000013ffe        0x0                                                                                                                                                                         
                    0x0000000000013ffe                PROVIDE (__stack, .)
    *(.stack)
    

    In this case, aligning the top of the memory range to an even value resulted in a properly aligned stack pointer:

    Breakpoint 1, main (argc=0, argv=0x0) at src/main.c:11
    (gdb) info registers
    pc             0x59e2	0x59e2 <main>
    sp             0x13ffa	81914
    

    3. Increasing the HIFRAM memory allocation (does work)

    MEMORY {
       SFR              : ORIGIN = 0x0000, LENGTH = 0x0010 /* END=0x0010, size 16 */
       BSL              : ORIGIN = 0x1000, LENGTH = 0x0800
       RAM              : ORIGIN = 0x1C00, LENGTH = 0x0800 /* END=0x23FF, size 2048 */
       INFOMEM          : ORIGIN = 0x1800, LENGTH = 0x0200 /* END=0x19FF, size 512 as 4 128-byte segments */
       INFOA            : ORIGIN = 0x1980, LENGTH = 0x0080 /* END=0x19FF, size 128 */
       INFOB            : ORIGIN = 0x1900, LENGTH = 0x0080 /* END=0x197F, size 128 */
       INFOC            : ORIGIN = 0x1880, LENGTH = 0x0080 /* END=0x18FF, size 128 */
       INFOD            : ORIGIN = 0x1800, LENGTH = 0x0080 /* END=0x187F, size 128 */
       ROM (rx)         : ORIGIN = 0x4400, LENGTH = 0xBB80 /* END=0xFF7F, size 48000 */
       HIFRAM (rxw)     : ORIGIN = 0x00010000, LENGTH = 0x00004000                                                                             
       /* HIFRAM (rxw)     : ORIGIN = 0x00010000, LENGTH = 0x00003FFF */
    

    This aligns the top of the HIFRAM as expected:

    .stack          0x0000000000014000        0x0                                                                                                                                                                         
                    0x0000000000014000                PROVIDE (__stack, .)
    *(.stack)
    

    Even though 0x14000 is technically 1 address past the end of the memory range, the stack pointer is always decremented into an allowable and aligned value before being used:

    (gdb) info registers 
    pc             0x59e2	0x59e2 <main>
    sp             0x13ffc	81916
    

    Hope this helps.

**Attention** This is a public forum