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/MSP430FR2111: Placing stack into FRAM

Part Number: MSP430FR2111


Tool/software: TI C/C++ Compiler

Hey folks,

Is it possible to put the stack in FRAM on the MSP430FR devices? There was another thread posted on this a few years ago (e2e.ti.com/support/microcontrollers/msp430/f/166/t/542727) but it was never really resolved. The last post in the thread seemed to hint they had managed to get it working, but I can't recreate it.

I've tried the obvious solution of changing the RAM setting to FRAM in the linker file (i.e. .stack : {} > FRAM), but this causes the program to get stuck in the _c_int00_noinit_noargs_noexit function. _system_pre_init is called, and then _c_int00_noinit_noargs_noexit  is immediately entered again when it returns.

What seems to be happening (as far as I understand) is that the stack is still being initialised into RAM at 0x2400 despite the linker being changed. The stack pointer however is set to the top of the FRAM (0xFF80 n the FR2111), but the value at this address is just 0xFFFF, so I presume at some point the code reads the address at the stack pointer, jumps to 0xFFFF, which is just where the reset vector is, and hence jumps back to __c_init00_noinit_noargs_noexit. This then just repeats which would explain why the code is not reaching main.

(note I posted this on the reddit MSP430 forum a few days ago but it's a bit quieter there so no answer yet)

Cheers

  • Hi Brian,
    Can you send us the code that can reproduce your issue?

    Best regards,
    Cash Hao
  • Hi Cash,

    Running any code will do it, but the simplest example I can do is to start a new empty project and just go into low power. 

    main.c

    #include <msp430.h>
    
    int main(void) {
        WDTCTL = WDTPW | WDTHOLD;
    
        __bis_SR_register(LPM3_bits | GIE);
    
        return 0;
    }
    

    lnk_msp430fr2111.cmd exactly as in the generated one, except the following lines 

    .cio        : {} > FRAM                  /* C I/O buffer                      */
    .sysmem     : {} > FRAM                  /* Dynamic memory allocation area    */
    .bss        : {} > FRAM                  /* Global & static vars              */
    .data       : {} > FRAM                  /* Global & static vars              */
    .TI.noinit  : {} > FRAM                  /* For #pragma noinit                */
    .stack      : {} > FRAM (HIGH)           /* Software system stack             */

  • Hi Brain,
    Okay. I will work on it and let's see what I can help for you.

    Best regards,
    Cash Hao
  • Hi Cash.

    I have an update on this, having come back to it after some other wok.

    The answer is quite obvious really, FRAM write protection needs to be turned off. By default the write enable flag is set, so the stack can't actually be written into FRAM. By breakpointing into the c_int00 routine and setting the register manually via the debugger, I was able to run my program normally.

    My question is now how I go about disabling the FRAM write protection in the startup routine, since I can't just edit the boot_special.c file. So am I right in thinking that I'll be able to use the linker to define a custom startup address and create my own c_init00 routine?

    Edit: So I redefined _system_pre_init to be

        int _system_pre_init(void) {
            SYSCFG0 = FRWPPW;

            return 1;
        }

    But this only works if I pause and resume the program via the debugger. Just running the program will never reach main, but after a pause and resume, it will start main. I'm wondering if this is because there needs to a delay after this. Have tried a few delays but still not resolved.



    Cheers

  • Further update:

    So I think I may have solved this.

    I changed the linker file to add a section for a custom _c_int00_noinit_noargs_noexit function.

        FRAM : origin = 0xF100, length = 0x720
        CUSTOM_C_INT : origin = 0xF820, length = 0x020
        FRAM2 : origin = 0xF840, length = 0x740

    Then after the .stack : {} > FRAM (HIGH) line, added

        .text:_isr:_c_int00_noinit_noargs_noexit : {} > CUSTOM_C_INT


    Then have a file called custom_c_int00.c where I copied the boot_special _c_int00_noinit_noargs_noexit code, and just added the FRAM write protection disable, and a location pragma


        #include "boot.h"
        
        #include "driverlib.h"
        
        
        extern int _system_pre_init(void);
        
        
        #pragma location=0xF820
        #pragma CLINK(_c_int00_noinit_noargs_noexit)
        CSTART_DECL _c_int00_noinit_noargs_noexit()
        {
            SYSCFG0 = FRWPPW;
            STACK_INIT();
            _system_pre_init();
            main(0);
            abort();
        }

    My program now runs with the stack seemingly in FRAM. I'm not going to mark this correct right now, since I would really like a TI Employee to chime in and just confirm that this is a valid method of placing FRAM into stack.

**Attention** This is a public forum