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.

MSP430FR5969 writing to FRAM fails to change value

Other Parts Discussed in Thread: MSP430FR5969, MSP430FR6989

I have set up variables in FRAM to store data, but when I try to write to them during runtime, the value in memory won't change. To set up the variables, I followed the steps at:

http://processors.wiki.ti.com/index.php/Creating_MSP430_FRAM_Variables_Using_CCS variables

My variable definitions looks like this:

#pragma SET_DATA_SECTION(".fram_vars")
unsigned int test;
unsigned int vals[DATA_LEN];    //array to store ADC input values
#pragma SET_DATA_SECTION()

And I've assigned data into these variables as usual, e.g.:

test = 1025;

vals[count++] = ADC12MEM0;

But when I run the program with the debugger and watch the value in the Expressions tab, it always reads as max value (65535). Why won't the value change?

  • Here are some similar E2E threads about similar issues:

    e2e.ti.com/.../436670
    e2e.ti.com/.../1095231
    e2e.ti.com/.../1032238

    Typically I just use #pragma PERSISTENT to tell the compiler/linker that this should be placed in FRAM. So your code would look as such:

    #pragma PERSISTENT (test)
    #pragma PERSISTENT (vals)
    unsigned int test;
    unsigned int vals[DATA_LEN];

    From this E2E thread: e2e.ti.com/.../1618953

    Regards,
    Ryan
  • Using #pragma PERSISTENT doesn't seem to work with my large (~2KB) arrray. CCS gives the "program will not fit into available memory" error that indicates it's trying to place the variables in RAM.

    Is there a good explanation of how the PERSISTENT and NOINIT pragmas are supposed to work? The section on them in slaa628 is rather vague, and my web searches aren't turning up anything better. A lot of the conversation seems to center around how the variables are initialized, but if that's the case, the program should be able to modify the FRAM variables while it's running, but the debugger always shows their values as all set to max value.

  • It goes without saying that a 2 KB array should easily fit in FRAM. What variable data type and compiler are you using? Is there enough FRAM memory allocated in your CMD file? My setup doesn't have any trouble initializing a 2 KB array. SLAA628 is the best resource I know of for explaining the PERSISTENT and NOINIT pragmas. Have you tried looking at your linker map file?

    e2e.ti.com/.../280162

    Regards,
    Ryan
  • Hi Ryan
    I'm using CCS v6.1.0.00104, but I'm not sure what compiler it has selected, so I guess whichever one is the default. As for the variable data type, it's just the array of unsigned int as in the original post. I tried changing the declaration as you suggested, by replacing the section from the original post (that used SET DATA SECTION) with
    #pragma PERSISTENT (vals)
    unsigned int vals[DATA_LEN];

    I checked the memory allocation pane (a new find for me, and quite handy!) and it's saying that it failed to allocate "vals" but that it's in the .bss section. From what I understand from reading the FRAM appnote, it should have attempted to allocate to one of the FRAM specific memory sections. I'm currently reading through the explanations of MPU now, as I've got a hunch that something went wrong with the write-protection. Any thoughts on that?
  • Hi,

    For future reference you can go to the CCS General window of your Project Properties to view your Compiler version, I also imagine that it is set to the default (TI v4.4.x) which should be fine. I don't think anything is wrong with the device's write protection because the error has to do with memory allocation. Can you provide your .cmd file?

    Regards,
    Ryan
  • Ryan,

    Ok, here's my CMD file. The only changes I made to it were to add in the sections mentioned in the original post, i.e. adding in the FRAM_VARS section in memory. I also notices that slaa628 mentions some failure modes with CCS builds before 6.0.0.00190, and I'm running 6.0.0.00104. Specifically, it says that the PERSISTENT and NOINIT pragmas aren't set up to allocate to FRAM sections only. I'm working on updating but it could be a while.

    The reason I'm concerned about write protection is that when I use the SET_DATA_SECTION pragma and load the program with the debugger, there aren't any errors, but all the data that I try to allocate in FRAM is just full of 1's when I check it in the Variables viewer, or the memory viewer. So it seems like something in the configuration is actively preventing that data from being changed in a normal way, but not saying anything about it.

    Cheers,

    Michael

    /* ============================================================================ */
    /* Copyright (c) 2014, Texas Instruments Incorporated                           */
    /*  All rights reserved.                                                        */
    /*                                                                              */
    /*  Redistribution and use in source and binary forms, with or without          */
    /*  modification, are permitted provided that the following conditions          */
    /*  are met:                                                                    */
    /*                                                                              */
    /*  *  Redistributions of source code must retain the above copyright           */
    /*     notice, this list of conditions and the following disclaimer.            */
    /*                                                                              */
    /*  *  Redistributions in binary form must reproduce the above copyright        */
    /*     notice, this list of conditions and the following disclaimer in the      */
    /*     documentation and/or other materials provided with the distribution.     */
    /*                                                                              */
    /*  *  Neither the name of Texas Instruments Incorporated nor the names of      */
    /*     its contributors may be used to endorse or promote products derived      */
    /*     from this software without specific prior written permission.            */
    /*                                                                              */
    /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" */
    /*  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,       */
    /*  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR      */
    /*  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR            */
    /*  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,       */
    /*  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,         */
    /*  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; */
    /*  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,    */
    /*  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR     */
    /*  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,              */
    /*  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                          */
    /* ============================================================================ */
    
    /******************************************************************************/
    /* lnk_msp430fr5969.cmd - LINKER COMMAND FILE FOR LINKING MSP430FR5969 PROGRAMS     */
    /*                                                                            */
    /*   Usage:  lnk430 <obj files...>    -o <out file> -m <map file> lnk.cmd     */
    /*           cl430  <src files...> -z -o <out file> -m <map file> lnk.cmd     */
    /*                                                                            */
    /*----------------------------------------------------------------------------*/
    /* These linker options are for command line linking only.  For IDE linking,  */
    /* you should set your linker options in Project Properties                   */
    /* -c                                               LINK USING C CONVENTIONS  */
    /* -stack  0x0100                                   SOFTWARE STACK SIZE       */
    /* -heap   0x0100                                   HEAP AREA SIZE            */
    /*                                                                            */
    /*----------------------------------------------------------------------------*/
    /* Version: 1.159                                                             */
    /*----------------------------------------------------------------------------*/
    
    /****************************************************************************/
    /* Specify the system memory map                                            */
    /****************************************************************************/
    
    MEMORY
    {
        SFR                     : origin = 0x0000, length = 0x0010
        PERIPHERALS_8BIT        : origin = 0x0010, length = 0x00F0
        PERIPHERALS_16BIT       : origin = 0x0100, length = 0x0100
        RAM                     : origin = 0x1C00, length = 0x0800
        INFOA                   : origin = 0x1980, length = 0x0080
        INFOB                   : origin = 0x1900, length = 0x0080
        INFOC                   : origin = 0x1880, length = 0x0080
        INFOD                   : origin = 0x1800, length = 0x0080
        FRAM                    : origin = 0x4400, length = 0x946F	// Shrunk original section from 0xBB80 (subtracted 0x2710)
        FRAM2                   : origin = 0x10000,length = 0x4000
        FRAM_VARS               : origin = 0xD870, length = 0x2710	// New section for FRAM Variables (10KB long = 0x2710), taken out of FRAM
        JTAGSIGNATURE           : origin = 0xFF80, length = 0x0004, fill = 0xFFFF
        BSLSIGNATURE            : origin = 0xFF84, length = 0x0004, fill = 0xFFFF
        IPESIGNATURE            : origin = 0xFF88, length = 0x0008, fill = 0xFFFF
        INT00                   : origin = 0xFF90, length = 0x0002
        INT01                   : origin = 0xFF92, length = 0x0002
        INT02                   : origin = 0xFF94, length = 0x0002
        INT03                   : origin = 0xFF96, length = 0x0002
        INT04                   : origin = 0xFF98, length = 0x0002
        INT05                   : origin = 0xFF9A, length = 0x0002
        INT06                   : origin = 0xFF9C, length = 0x0002
        INT07                   : origin = 0xFF9E, length = 0x0002
        INT08                   : origin = 0xFFA0, length = 0x0002
        INT09                   : origin = 0xFFA2, length = 0x0002
        INT10                   : origin = 0xFFA4, length = 0x0002
        INT11                   : origin = 0xFFA6, length = 0x0002
        INT12                   : origin = 0xFFA8, length = 0x0002
        INT13                   : origin = 0xFFAA, length = 0x0002
        INT14                   : origin = 0xFFAC, length = 0x0002
        INT15                   : origin = 0xFFAE, length = 0x0002
        INT16                   : origin = 0xFFB0, length = 0x0002
        INT17                   : origin = 0xFFB2, length = 0x0002
        INT18                   : origin = 0xFFB4, length = 0x0002
        INT19                   : origin = 0xFFB6, length = 0x0002
        INT20                   : origin = 0xFFB8, length = 0x0002
        INT21                   : origin = 0xFFBA, length = 0x0002
        INT22                   : origin = 0xFFBC, length = 0x0002
        INT23                   : origin = 0xFFBE, length = 0x0002
        INT24                   : origin = 0xFFC0, length = 0x0002
        INT25                   : origin = 0xFFC2, length = 0x0002
        INT26                   : origin = 0xFFC4, length = 0x0002
        INT27                   : origin = 0xFFC6, length = 0x0002
        INT28                   : origin = 0xFFC8, length = 0x0002
        INT29                   : origin = 0xFFCA, length = 0x0002
        INT30                   : origin = 0xFFCC, length = 0x0002
        INT31                   : origin = 0xFFCE, length = 0x0002
        INT32                   : origin = 0xFFD0, length = 0x0002
        INT33                   : origin = 0xFFD2, length = 0x0002
        INT34                   : origin = 0xFFD4, length = 0x0002
        INT35                   : origin = 0xFFD6, length = 0x0002
        INT36                   : origin = 0xFFD8, length = 0x0002
        INT37                   : origin = 0xFFDA, length = 0x0002
        INT38                   : origin = 0xFFDC, length = 0x0002
        INT39                   : origin = 0xFFDE, length = 0x0002
        INT40                   : origin = 0xFFE0, length = 0x0002
        INT41                   : origin = 0xFFE2, length = 0x0002
        INT42                   : origin = 0xFFE4, length = 0x0002
        INT43                   : origin = 0xFFE6, length = 0x0002
        INT44                   : origin = 0xFFE8, length = 0x0002
        INT45                   : origin = 0xFFEA, length = 0x0002
        INT46                   : origin = 0xFFEC, length = 0x0002
        INT47                   : origin = 0xFFEE, length = 0x0002
        INT48                   : origin = 0xFFF0, length = 0x0002
        INT49                   : origin = 0xFFF2, length = 0x0002
        INT50                   : origin = 0xFFF4, length = 0x0002
        INT51                   : origin = 0xFFF6, length = 0x0002
        INT52                   : origin = 0xFFF8, length = 0x0002
        INT53                   : origin = 0xFFFA, length = 0x0002
        INT54                   : origin = 0xFFFC, length = 0x0002
        RESET                   : origin = 0xFFFE, length = 0x0002
    }
    
    /****************************************************************************/
    /* Specify the sections allocation into memory                              */
    /****************************************************************************/
    
    SECTIONS
    {
        GROUP(READ_WRITE_MEMORY)
        {
           .TI.persistent : {}                  /* For #pragma persistent            */
           .cio           : {}                  /* C I/O Buffer                      */
           .sysmem        : {}                  /* Dynamic memory allocation area    */
        } PALIGN(0x0400), RUN_END(fram_rx_start) > 0x4400
    
        .cinit            : {}  > FRAM          /* Initialization tables             */
        .pinit            : {}  > FRAM          /* C++ Constructor tables            */
        .init_array       : {}  > FRAM          /* C++ Constructor tables            */
        .mspabi.exidx     : {}  > FRAM          /* C++ Constructor tables            */
        .mspabi.extab     : {}  > FRAM          /* C++ Constructor tables            */
    #ifndef __LARGE_DATA_MODEL__
        .const            : {} >> FRAM          /* Constant data                     */
    #else
        .const            : {} >> FRAM | FRAM2  /* Constant data                     */
    #endif
    
        .text:_isr        : {}  > FRAM          /* Code ISRs                         */
    #ifndef __LARGE_DATA_MODEL__
        .text             : {} >> FRAM          /* Code                              */
    #else
        .text             : {} >> FRAM2 | FRAM  /* Code                              */
    #endif
    
        GROUP(IPENCAPSULATED_MEMORY)
        {
           .ipestruct     : {}                  /* IPE Data structure             */
           .ipe           : {}                  /* IPE                            */
           .ipe:_isr      : {}                  /* IPE ISRs                       */
        } PALIGN(0x0400), RUN_START(fram_ipe_start) RUN_END(fram_ipe_end) > FRAM
    
        .jtagsignature : {} > JTAGSIGNATURE     /* JTAG Signature                    */
        .bslsignature  : {} > BSLSIGNATURE      /* BSL Signature                     */
    
        GROUP(SIGNATURE_SHAREDMEMORY)
        {
           .ipesignature   : {}                 /* IPE Signature                     */
           .jtagpassword   : {}                 /* JTAG Password                     */
        } > IPESIGNATURE
    
        .bss        : {} > RAM                  /* Global & static vars              */
        .data       : {} > RAM                  /* Global & static vars              */
        .TI.noinit  : {} > RAM                  /* For #pragma noinit                */
        .stack      : {} > RAM (HIGH)           /* Software system stack             */
    
        .infoA     : {} > INFOA              /* MSP430 INFO FRAM  Memory segments */
        .infoB     : {} > INFOB
        .infoC     : {} > INFOC
        .infoD     : {} > INFOD
    
        .fram_vars : {} > FRAM_VARS type=NOINIT		// Specifies the memory section to reside in the memory area defined by FRAM_VARS
    
        /* MSP430 Interrupt vectors          */
        .int00       : {}               > INT00
        .int01       : {}               > INT01
        .int02       : {}               > INT02
        .int03       : {}               > INT03
        .int04       : {}               > INT04
        .int05       : {}               > INT05
        .int06       : {}               > INT06
        .int07       : {}               > INT07
        .int08       : {}               > INT08
        .int09       : {}               > INT09
        .int10       : {}               > INT10
        .int11       : {}               > INT11
        .int12       : {}               > INT12
        .int13       : {}               > INT13
        .int14       : {}               > INT14
        .int15       : {}               > INT15
        .int16       : {}               > INT16
        .int17       : {}               > INT17
        .int18       : {}               > INT18
        .int19       : {}               > INT19
        .int20       : {}               > INT20
        .int21       : {}               > INT21
        .int22       : {}               > INT22
        .int23       : {}               > INT23
        .int24       : {}               > INT24
        .int25       : {}               > INT25
        .int26       : {}               > INT26
        .int27       : {}               > INT27
        .int28       : {}               > INT28
        .int29       : {}               > INT29
        AES256       : { * ( .int30 ) } > INT30 type = VECT_INIT
        RTC          : { * ( .int31 ) } > INT31 type = VECT_INIT
        PORT4        : { * ( .int32 ) } > INT32 type = VECT_INIT
        PORT3        : { * ( .int33 ) } > INT33 type = VECT_INIT
        TIMER3_A1    : { * ( .int34 ) } > INT34 type = VECT_INIT
        TIMER3_A0    : { * ( .int35 ) } > INT35 type = VECT_INIT
        PORT2        : { * ( .int36 ) } > INT36 type = VECT_INIT
        TIMER2_A1    : { * ( .int37 ) } > INT37 type = VECT_INIT
        TIMER2_A0    : { * ( .int38 ) } > INT38 type = VECT_INIT
        PORT1        : { * ( .int39 ) } > INT39 type = VECT_INIT
        TIMER1_A1    : { * ( .int40 ) } > INT40 type = VECT_INIT
        TIMER1_A0    : { * ( .int41 ) } > INT41 type = VECT_INIT
        DMA          : { * ( .int42 ) } > INT42 type = VECT_INIT
        USCI_A1      : { * ( .int43 ) } > INT43 type = VECT_INIT
        TIMER0_A1    : { * ( .int44 ) } > INT44 type = VECT_INIT
        TIMER0_A0    : { * ( .int45 ) } > INT45 type = VECT_INIT
        ADC12        : { * ( .int46 ) } > INT46 type = VECT_INIT
        USCI_B0      : { * ( .int47 ) } > INT47 type = VECT_INIT
        USCI_A0      : { * ( .int48 ) } > INT48 type = VECT_INIT
        WDT          : { * ( .int49 ) } > INT49 type = VECT_INIT
        TIMER0_B1    : { * ( .int50 ) } > INT50 type = VECT_INIT
        TIMER0_B0    : { * ( .int51 ) } > INT51 type = VECT_INIT
        COMP_E       : { * ( .int52 ) } > INT52 type = VECT_INIT
        UNMI         : { * ( .int53 ) } > INT53 type = VECT_INIT
        SYSNMI       : { * ( .int54 ) } > INT54 type = VECT_INIT
        .reset       : {}               > RESET  /* MSP430 Reset vector         */ 
    }
    
    /****************************************************************************/
    /* MPU/IPE Specific memory segment definitons                               */
    /****************************************************************************/
    
    #ifdef _IPE_ENABLE
       #define IPE_MPUIPLOCK 0x0080
       #define IPE_MPUIPENA 0x0040
       #define IPE_MPUIPPUC 0x0020
    
       // Evaluate settings for the control setting of IP Encapsulation
       #if defined(_IPE_ASSERTPUC1)
            #if defined(_IPE_LOCK ) && (_IPE_ASSERTPUC1 == 0x08))
             fram_ipe_enable_value = (IPE_MPUIPENA | IPE_MPUIPPUC |IPE_MPUIPLOCK);
            #elif defined(_IPE_LOCK )
             fram_ipe_enable_value = (IPE_MPUIPENA | IPE_MPUIPLOCK);
          #elif (_IPE_ASSERTPUC1 == 0x08)
             fram_ipe_enable_value = (IPE_MPUIPENA | IPE_MPUIPPUC);
          #else
             fram_ipe_enable_value = (IPE_MPUIPENA);
          #endif
       #else
          #if defined(_IPE_LOCK )
             fram_ipe_enable_value = (IPE_MPUIPENA | IPE_MPUIPLOCK);
          #else
             fram_ipe_enable_value = (IPE_MPUIPENA);
          #endif
       #endif
    
       // Segment definitions
       #ifdef _IPE_MANUAL                  // For custom sizes selected in the GUI
          fram_ipe_border1 = (_IPE_SEGB1>>4);
          fram_ipe_border2 = (_IPE_SEGB2>>4);
       #else                           // Automated sizes generated by the Linker
          fram_ipe_border2 = (fram_ipe_end + 0x400)>> 4;
          fram_ipe_border1 = fram_ipe_start >> 4;
       #endif
    
       fram_ipe_settings_struct_address = Ipe_settingsStruct >> 4;
       fram_ipe_checksum = ~((fram_ipe_enable_value & fram_ipe_border2 & fram_ipe_border1) | (fram_ipe_enable_value & ~fram_ipe_border2 & ~fram_ipe_border1) | (~fram_ipe_enable_value & fram_ipe_border2 & ~fram_ipe_border1) | (~fram_ipe_enable_value & ~fram_ipe_border2 & fram_ipe_border1));
    #endif
    
    #ifdef _MPU_ENABLE
       #define MPUPW (0xA500)    /* MPU Access Password */
       #define MPUENA (0x0001)   /* MPU Enable */
       #define MPULOCK (0x0002)  /* MPU Lock */
       #define MPUSEGIE (0x0010) /* MPU Enable NMI on Segment violation */
    
       __mpu_enable = 1;
       // Segment definitions
       #ifdef _MPU_MANUAL // For custom sizes selected in the GUI
          mpu_segment_border1 = _MPU_SEGB1 >> 4;
          mpu_segment_border2 = _MPU_SEGB2 >> 4;
          mpu_sam_value = (_MPU_SAM0 << 12) | (_MPU_SAM3 << 8) | (_MPU_SAM2 << 4) | _MPU_SAM1;
       #else // Automated sizes generated by Linker
          mpu_segment_border1 = fram_rx_start >> 4;
          mpu_segment_border2 = fram_rx_start >> 4;
          mpu_sam_value = 0x1513; // Info R, Seg3 RX, Seg2 R, Seg1 RW
       #endif
       #ifdef _MPU_LOCK
          #ifdef _MPU_ENABLE_NMI
             mpu_ctl0_value = MPUPW | MPUENA | MPULOCK | MPUSEGIE;
          #else
             mpu_ctl0_value = MPUPW | MPUENA | MPULOCK;
          #endif
       #else
          #ifdef _MPU_ENABLE_NMI
             mpu_ctl0_value = MPUPW | MPUENA | MPUSEGIE;
          #else
             mpu_ctl0_value = MPUPW | MPUENA;
          #endif
       #endif
    #endif
    
    /****************************************************************************/
    /* Include peripherals memory map                                           */
    /****************************************************************************/
    
    -l msp430fr5969.cmd
    
    

  • I've updated the relevant files in CCS, so the bug mentioned in slaa628 should be irrelevant.
  • Run this version and let me know if anything changes: https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/166/ctpl_5F00_lnk_5F00_msp430fr5969.cmd

    Regards, Ryan

  • Running with that CMD allows the program to change values for those variables, and it does seem to stay the same between resets as well, so this might be the fix I need. From what I can see, the only change here was removing the section I added into memory FRAM_VALS with type=NOINIT, so I'm guessing that just confused the compiler.
    Thanks for the fix, much appreciated!
  • Hi

    I want to simply write data received from UART over my msp430fr6989 controller. In FRAM space.

    from its default linker file I have took one location address . that is 0x1800 , I am receiving the first data block is a5a5.
    ( in linker file I have assigned section of 0x1800 with length of 0x0002 , for this data from info.D segment. and rest is calculated and kept and program compiled fine with out any errors)

    My instruction to write that particular block is as below.

    *(unsigned int *)0x1800 = 0xA5A5; ( I have tried this instruction and was working ,but now its not)

    - My problem is when i tried before , It was working very well.

    but now what ever I do , the value at particular location remains same 0xffff. and it won't change.

    in project properties I have setting as below :-
    1. erase option :- erase main memory only.
    2. code memory model :- small
    3. data memory model :- restricted
    4. what data must be near :- globals

    need your guidance in this matter.
  • Hinesh,

    You mentioned that you had this working before, what was the difference? The problem most likely exists inside of your linker file, it's possible that you are overlapping memory space. You should not be trying to create a new memory section when infoD is already assigned and available.

    The only reason you would want to use the information memory space is to store application-specific information such as IDs/version numbers or for executable code. The MPU can then be used to manage accessibility to these areas. Make sure that the MPUSEGIWE bit is set inside of the MPUSAM register so that writing to infoD is allowed.

    Regards,
    Ryan
  • Hi  

    There is no difference That I have made.

    I will create a new space for my data storage instead of info.D for sure. I have not even changed the linker file that was working before.

    Also the erase option and all the option were set as before. I have also tried re-write on location from 0x6400 ( FRAM section) but there also , when i check in memory browser it shows '0xFF' .

    I am confused and also bit tensed about this happening.

  • Hinesh,

    Are you not able to return to your code's working state, regardless of the section of memory you are trying to modify? It would be helpful to have more details on what has changed between the working and non-working setups.

    Regards,
    Ryan
  • ,

    I have checked all the settings that was working. And it's not change.

    The instruction also I have wrote earlier, is only I am using, to store data ( i.e. Version no).

    but It's modifying and data remains 0xFF. I am able to write directly on that location ( from memory browser in CCS debug mode) . But When I flash and run program again ( in My program first I am making that location value to 0xFF ). The value retains.

    ( in ccs , in msp430 debug option I am selecting erase main memory only.)

    I am attaching my linker file for more reference.

    /* ============================================================================ */
    /* Copyright (c) 2015, Texas Instruments Incorporated                           */
    /*  All rights reserved.                                                        */
    /*                                                                              */
    /*  Redistribution and use in source and binary forms, with or without          */
    /*  modification, are permitted provided that the following conditions          */
    /*  are met:                                                                    */
    /*                                                                              */
    /*  *  Redistributions of source code must retain the above copyright           */
    /*     notice, this list of conditions and the following disclaimer.            */
    /*                                                                              */
    /*  *  Redistributions in binary form must reproduce the above copyright        */
    /*     notice, this list of conditions and the following disclaimer in the      */
    /*     documentation and/or other materials provided with the distribution.     */
    /*                                                                              */
    /*  *  Neither the name of Texas Instruments Incorporated nor the names of      */
    /*     its contributors may be used to endorse or promote products derived      */
    /*     from this software without specific prior written permission.            */
    /*                                                                              */
    /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" */
    /*  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,       */
    /*  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR      */
    /*  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR            */
    /*  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,       */
    /*  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,         */
    /*  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; */
    /*  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,    */
    /*  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR     */
    /*  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,              */
    /*  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                          */
    /* ============================================================================ */
    
    /******************************************************************************/
    /* lnk_msp430fr6989.cmd - LINKER COMMAND FILE FOR LINKING MSP430FR6989 PROGRAMS     */
    /*                                                                            */
    /*   Usage:  lnk430 <obj files...>    -o <out file> -m <map file> lnk.cmd     */
    /*           cl430  <src files...> -z -o <out file> -m <map file> lnk.cmd     */
    /*                                                                            */
    /*----------------------------------------------------------------------------*/
    /* These linker options are for command line linking only.  For IDE linking,  */
    /* you should set your linker options in Project Properties                   */
    /* -c                                               LINK USING C CONVENTIONS  */
    /* -stack  0x0100                                   SOFTWARE STACK SIZE       */
    /* -heap   0x0100                                   HEAP AREA SIZE            */
    /*                                                                            */
    /*----------------------------------------------------------------------------*/
    /* Version: 1.173                                                             */
    /*----------------------------------------------------------------------------*/
    
    /****************************************************************************/
    /* Specify the system memory map                                            */
    /****************************************************************************/
    
    
        MEMORY
    {
        TINYRAM                 : origin = 0x0006, length = 0x001A
        PERIPHERALS_8BIT        : origin = 0x0020, length = 0x00E0
        PERIPHERALS_16BIT       : origin = 0x0100, length = 0x0100
        RAM                     : origin = 0x1C00, length = 0x0800
        INFOA                   : origin = 0x1980, length = 0x0080
        INFOB                   : origin = 0x1900, length = 0x0080
        INFOC                   : origin = 0x1880, length = 0x0080
        //INFOD                   : origin = 0x1800, length = 0x0080
        INFOD                   : origin = 0x1804, length = 0x007C
        INFOJ                   : origin = 0x1802, length = 0x0002
        INFOS                   : origin = 0x1800, length = 0x0002
        FRAM                    : origin = 0x4400, length = 0xBB80
      //  FRAM2                   : origin = 0x10000,length = 0x14000
        JTAGSIGNATURE           : origin = 0xFF80, length = 0x0004, fill = 0xFFFF
        BSLSIGNATURE            : origin = 0xFF84, length = 0x0004, fill = 0xFFFF
        IPESIGNATURE            : origin = 0xFF88, length = 0x0008, fill = 0xFFFF
        RESET                   : origin = 0xFFFE, length = 0x0002
    }
    
    /****************************************************************************/
    /* Specify the sections allocation into memory                              */
    /****************************************************************************/
    
    SECTIONS
    {
        GROUP(READ_WRITE_MEMORY)
        {
           .TI.persistent : {}                  /* For #pragma persistent            */
           .cio           : {}                  /* C I/O Buffer                      */
           .sysmem        : {}                  /* Dynamic memory allocation area    */
        } PALIGN(0x0400), RUN_END(fram_rx_start) > 0x4400
    
        .cinit            : {}  > FRAM          /* Initialization tables             */
        .pinit            : {}  > FRAM          /* C++ Constructor tables            */
        .init_array       : {}  > FRAM          /* C++ Constructor tables            */
        .mspabi.exidx     : {}  > FRAM          /* C++ Constructor tables            */
        .mspabi.extab     : {}  > FRAM          /* C++ Constructor tables            */
    #ifndef __LARGE_DATA_MODEL__
        .const            : {} >> FRAM          /* Constant data                     */
    #else
        .const            : {} >> FRAM | //FRAM2  /* Constant data                     */
    #endif
    
        .text:_isr        : {}  > FRAM          /* Code ISRs                         */
    #ifndef __LARGE_DATA_MODEL__
        .text             : {} >> FRAM          /* Code                              */
    #else
        .text             : {} >> FRAM//| FRAM2  /* Code                              */
    #endif
    
        GROUP(IPENCAPSULATED_MEMORY)
        {
           .ipestruct     : {}                  /* IPE Data structure             */
           .ipe           : {}                  /* IPE                            */
           .ipe:_isr      : {}                  /* IPE ISRs                       */
           .ipe_vars      : type = NOINIT{}     /* IPE variables                  */
        } PALIGN(0x0400), RUN_START(fram_ipe_start) RUN_END(fram_ipe_end) > FRAM
    
        .jtagsignature : {} > JTAGSIGNATURE     /* JTAG Signature                    */
        .bslsignature  : {} > BSLSIGNATURE      /* BSL Signature                     */
    
        GROUP(SIGNATURE_SHAREDMEMORY)
        {
           .ipesignature   : {}                 /* IPE Signature                     */
           .jtagpassword   : {}                 /* JTAG Password                     */
        } > IPESIGNATURE
    
        .bss        : {} > RAM                  /* Global & static vars              */
        .data       : {} > RAM                  /* Global & static vars              */
        .TI.noinit  : {} > RAM                  /* For #pragma noinit                */
        .stack      : {} > RAM (HIGH)           /* Software system stack             */
        .tinyram    : {} > TINYRAM              /* Tiny RAM                          */
    
    	.infoJ		: {} > INFOJ				/* Jump Address of main FW */
    	.infoS		: {} > INFOS				/* FW Signature */
        .infoA     : {} > INFOA              /* MSP430 INFO FRAM  Memory segments */
        .infoB     : {} > INFOB
        .infoC     : {} > INFOC
        .infoD     : {} > INFOD
    
        /* MSP430 Interrupt vectors          */
        .reset       : {}               > RESET  /* MSP430 Reset vector         */
    }
    
    
    /****************************************************************************/
    /* MPU/IPE Specific memory segment definitons                               */
    /****************************************************************************/
    
    #ifdef _IPE_ENABLE
       #define IPE_MPUIPLOCK 0x0080
       #define IPE_MPUIPENA 0x0040
       #define IPE_MPUIPPUC 0x0020
    
       // Evaluate settings for the control setting of IP Encapsulation
       #if defined(_IPE_ASSERTPUC1)
            #if defined(_IPE_LOCK ) && (_IPE_ASSERTPUC1 == 0x08))
             fram_ipe_enable_value = (IPE_MPUIPENA | IPE_MPUIPPUC |IPE_MPUIPLOCK);
            #elif defined(_IPE_LOCK )
             fram_ipe_enable_value = (IPE_MPUIPENA | IPE_MPUIPLOCK);
          #elif (_IPE_ASSERTPUC1 == 0x08)
             fram_ipe_enable_value = (IPE_MPUIPENA | IPE_MPUIPPUC);
          #else
             fram_ipe_enable_value = (IPE_MPUIPENA);
          #endif
       #else
          #if defined(_IPE_LOCK )
             fram_ipe_enable_value = (IPE_MPUIPENA | IPE_MPUIPLOCK);
          #else
             fram_ipe_enable_value = (IPE_MPUIPENA);
          #endif
       #endif
    
       // Segment definitions
       #ifdef _IPE_MANUAL                  // For custom sizes selected in the GUI
          fram_ipe_border1 = (_IPE_SEGB1>>4);
          fram_ipe_border2 = (_IPE_SEGB2>>4);
       #else                           // Automated sizes generated by the Linker
          fram_ipe_border2 = (fram_ipe_end + 0x400)>> 4;
          fram_ipe_border1 = fram_ipe_start >> 4;
       #endif
    
       fram_ipe_settings_struct_address = Ipe_settingsStruct >> 4;
       fram_ipe_checksum = ~((fram_ipe_enable_value & fram_ipe_border2 & fram_ipe_border1) | (fram_ipe_enable_value & ~fram_ipe_border2 & ~fram_ipe_border1) | (~fram_ipe_enable_value & fram_ipe_border2 & ~fram_ipe_border1) | (~fram_ipe_enable_value & ~fram_ipe_border2 & fram_ipe_border1));
    #endif
    
    #ifdef _MPU_ENABLE
       #define MPUPW (0xA500)    /* MPU Access Password */
       #define MPUENA (0x0001)   /* MPU Enable */
       #define MPULOCK (0x0002)  /* MPU Lock */
       #define MPUSEGIE (0x0010) /* MPU Enable NMI on Segment violation */
    
       __mpu_enable = 1;
       // Segment definitions
       #ifdef _MPU_MANUAL // For custom sizes selected in the GUI
          mpu_segment_border1 = _MPU_SEGB1 >> 4;
          mpu_segment_border2 = _MPU_SEGB2 >> 4;
          mpu_sam_value = (_MPU_SAM0 << 12) | (_MPU_SAM3 << 8) | (_MPU_SAM2 << 4) | _MPU_SAM1;
       #else // Automated sizes generated by Linker
          mpu_segment_border1 = fram_rx_start >> 4;
          mpu_segment_border2 = fram_rx_start >> 4;
          mpu_sam_value = 0x1513; // Info R, Seg3 RX, Seg2 R, Seg1 RW
       #endif
       #ifdef _MPU_LOCK
          #ifdef _MPU_ENABLE_NMI
             mpu_ctl0_value = MPUPW | MPUENA | MPULOCK | MPUSEGIE;
          #else
             mpu_ctl0_value = MPUPW | MPUENA | MPULOCK;
          #endif
       #else
          #ifdef _MPU_ENABLE_NMI
             mpu_ctl0_value = MPUPW | MPUENA | MPUSEGIE;
          #else
             mpu_ctl0_value = MPUPW | MPUENA;
          #endif
       #endif
    #endif
    
    /****************************************************************************/
    /* Include peripherals memory map                                           */
    /****************************************************************************/
    
    -l msp430fr6989.cmd
    
    

  • Hinesh,

    You can use infoD in its default linker file configuration, do not separate it into infoD and infoS.  Provided is example code showing a test variable properly stored in infoD (using the default linker file):

    #include <msp430.h> 
    
    #pragma SET_DATA_SECTION(".infoD")
    unsigned int test;
    #pragma SET_DATA_SECTION()
    
    /*
     * main.c
     */
    int main(void) {
        WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    
        PM5CTL0 &= ~LOCKLPM5;           // Disable the GPIO power-on default high-impedance mode
                                        // to activate previously configured port settings
    
        // Configure MPU
        MPUCTL0 = MPUPW;                          // Write PWD to access MPU registers
        MPUSAM |= MPUSEGIWE;                      // Writes to user information memory are allowed
        MPUCTL0 = MPUPW | MPUENA;      			  // Enable MPU protection
                                                  // MPU registers locked until BOR
    
        test = 0xA5;
    
        while(1) __no_operation();
    	
    }

    Regards, Ryan

  • Hi  

    Thank you for the Guidance.

    I have another question. That If I am storing a No. I.E Version No In FRAM Location (Say In linker I define Location as VER_NO: origin : 0x8400  , Length 0x0010)

    Will it be erased every time I read back. ? How can I retain That No. From Accidental Removal or while Dumping Program with JTAG.?

    As I wanted to retain that No. Until I changed It.

    I have used #pragma RETAIN and Also I have defined above section as #pragma LOCATION (VER_NO, 0x8400).
    but I am not able retain the data. ( and I am not deleting the data from anywhere in my program for sure.)

    Thanks,

  • Hinesh,

    Assuming the value you are inquiring about is correctly stored in information memory: under Project properties -> Debug -> MSP430 Properties -> Erase Options make sure that you are set to only erase main memory.  Alternatively use a flash tool like MSP-430Flasher or FET-Pro430 to erase/write only the main memory, leaving the information memory intact.

    Regards,
    Ryan

  • Hi ,


    I will using that option that in properties to flash my code in controller for sure.

    and can I lock my specific memory location so that accidentally It should not get erased. ?

    Thanks,

  • No, you cannot lock a specific memory location using firmware. The program tool determines what is retained and what is erased/overwritten.

    Regards,
    Ryan
  • You can use the MPU to restrict write/erase access to a segment of your memory from within your application - that can prevent your application code from accidentally erasing/overwriting an area when it is running. But when you use a programming tool with SBW or JTAG, the MPU setting will not have any effect (this is necessary so that you can still reprogram a different piece of code into your part later if needed). You can restrict all access to the part from JTAG/SBW, but that will lock your entire device permanently and should only done when you have a completed product that you are producing to be sent out and used in the field, not during development of your design/code.
  • Hi ,

    Thank you for the answer.

    yes, Katie I don't want to lock whole device while still I am in development phase. But I wanted to restrict Particular part of memory location so That It should not be even accidental erase. Yes I am aware that JTAG/SBW will erase ( good feature from TI) Locations in order to change setting during development. 

    But locking a section will give me relief that It will not get erased/modified.

    I have gone through the document.,

    But Not Got clear Idea to lock a particular section for MPULOCK.


    Can you describe here .

    thanks,

  • Hinesh Gohel said:

    But Not Got clear Idea to lock a particular section for MPULOCK.

    The MPULOCK is like the "lock-box" that a realtor hangs on the door-handle of a house for sale. Lock-box does not lock the house, it locks the keys of the house.

    The document you cited says:

    MPU Lock. If this bit is set, access to all MPU Registers except MPUCTL1,
    MPUIPC0, and MPUIPSEGx are locked and they are read only until a BOR
    occurs. BOR sets MPULOCK to 0.
    0b = Open
    1b = Locked

    I think that statement is perfectly clear except for the reader trying to understand it until a cup of black coffee is consumed.

    I need Black coffee!

  • old_cow_yellow said:

    I think that statement is perfectly clear except for the reader trying to understand it until a cup of black coffee is consumed.

    I need Black coffee!

    Now, I also Need a cup of coffee. :-)

    BTW, Thanks for Reply.

  • Could you tell me which part of the FRAM (address range) you want to restrict access?

    And what kind of access is allowed? (a) Read-only. (b) Read/Write but don't Execute, (c) Read/Execute but don't Write.

    Perhaps I could do that for you.
  • Hi,

    Starting from 0x8400 to 10 bytes of memory locations.

    1. I would wanted that section to be read only.(for whole application)

    2. only If I specifically wanted to change. , I Should Get Access for once. After setting It should be read only.

  • The granularity of Memory Protection is 1KB. It is not possible to restrict only 10 bytes of FRAM. The following fragment of code tries to restrict 1KB from 0x8400 to 0x87FF for read only.

      MPUCTL0_H = MPUPW_H;
      MPUSEGB1 = 0X0840;
      MPUSEGB2 = 0x0880;
      MPUSAM = 0x7717;
      MPUCTL0_L = MPULOCK|MPUENA;
      MPUCTL0_H = 0;

    Please note the following:

    (1) The existence of the code does not have the desired effect. It is the execution of this code that may achieve the effect.

    (2) If the MPULOCK bit is already set before this code is executed, this code cannot achieve the effect.

    (3) A subsequent BOR will reset the MPU and all restrictions are removed.

  • To add to old_cow_yellow's comment, if you use the latest versions of CCS you can use the MPU tool built-in to generate this MPU setup for you - when enabled, the compiler will generate and run this MPU setup code before main for you so you wouldn't have to add any code like this to your project. Go to Project > Properties >General and select the tab "MSP430 MPU". There, you can select "Enable Memory Protection Unit".

    Usually I recommend that people select "Let compiler handle memory partitioning" but that would be if you were ok with the default MPU setup (which will group FRAM variables together for R + W access, and set the rest of memory as R + X only access).

    If you want a setup like old_cow_yellow explained above where you can control addresses and access rights by hand, simply select "Manually specify memory segment boundaries and access rights". With the manual setup, you will fill in the boxes for your segment boundaries to be 0x8400 and 0x8800 (since as he mentioned, the MPU granularity is 1kB or 0x400 bytes). Then you would select Segment 2 to have R only checked (meaning only read access). For the other two segments - if you have only code and constants everywhere else (no FRAM variables) I'd recommend setting both to R + X. (This is all assuming you want that area to be read-only access, not having variables in these FRAM addresses, but rather constants).

    Now, there is one more thing you need to consider with either old_cow_yellow's code above, or when manually setting up MPU using the tool in CCS. And that is that you need to take care in your linker file to ensure that your code or constants that you are trying to protect are placed in the correct areas. So if you have things that you are going to place explicitly at 0x8400, you should modify the linker file to set aside a section of FRAM for this purpose, so that the linker doesn't place any other code there and cause a conflict.

    Regards,
    Katie
  • Thaks For comment., ( actually expecting One :- )   ) .

    Yes, I have took care to portioned memory in linker and Defined very well my section for Version No. In FRAM. Thanks for informing that CCS will have tool for MSP430 MPU.

    I also know its a good to Let compiler do the memory allocation, But There is one need in project So for that I have to Go for Section.

    Thanks.,   

  • Thank you for the Reply Old_yellow_cow,
    I will take care of Granularity is of ( good you advised. :-) ) 1 KB.

    I will not run any other lock bits before this code. and Will run ( and Execute ) this code as First Code To make sure I have the MPU Enable.

**Attention** This is a public forum