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.

MSP430FR5994: Writable Memory Above 64k

Part Number: MSP430FR5994
Other Parts Discussed in Thread: MSP430F6659, , TEST2, MSP430WARE

Hi team,

We are looking at the MSP430FR59xx devices that have 128k and 256k FRAM. On page 123 of the MSP430 Optimizing C/C++ Compiler v16.12.0.STS User's Guide (http://www.ti.com/lit/ug/slau132n/slau132n.pdf) it says "All current MSP430X devices do not have any writeable memory above the 64K boundary." I imagine this has to do with the 16-bit nature of the MSP device.

Does this mean that we cannot use the whole memory space for variables or buffers?

Thank you,

Akash Patel

  • Hi Akash,

    I'm looking into this - I don't think this note can be correct and suspect that it is a holdover from older versions of the guide, likely before FRAM parts were released and even before large RAM devices like MSP430F6659 were released. I'm still working to get you full confirmation - I'm going to run a test first to show that you can use the upper FRAM for data, and then also I will reach out to the compiler team about what this note is really supposed to mean and which devices it is supposed to apply to. But you can already tell that it does not apply to all MSP430X devices because MSP430F6659 for example has a high RAM that starts at 0xF0000, above the 64k boundary. So I suspect we need to update the note to make it clearer.

    I'll reply again soon.

    Regards,
    Katie
  • Hi Akash,

    So I can definitely confirm that you can write to upper FRAM on the MSP430FR5994, just as expected. I will next work to get that note clarified in the compiler guide to prevent future confusion.

    You should be able to use any part of FRAM to store variables or buffers just like RAM - it is flexible and can be partitioned however you would like. Please see www.ti.com/.../slaa628 MSP430 FRAM How To and Best Practices. One of the main considerations however is that FRAM is very easy to write to, so you would want to enable the MPU or Memory Protection Unit when you use FRAM - that helps protect you from accidentally writing off the end of a data array and overwriting some of your code. The MPU allows you to segment your FRAM in up to 3 segments and apply different read, write, execute permissions to each segment.
    Therefore, you want to group all of your data together and all of your code together. The MPU can be enabled in CCS from the project properties, or from user code. Usually we recommend to use the PERSISTENT pragma to place variables in FRAM and then allow the linker + compiler automatically configure the MPU segments. This is the easiest method because it is all done for you, but the default is to have the persistent data placed in the lower FRAM.

    If the customer is storing so much data that it won't all fit in the lower FRAM, the linker file can be modified to help better enable MPU configuration for this case - I will also point out that accessing data in upper FRAM will require 20 bit accesses which means you have to use the intrinsics like __data20_read_char() described in the compiler guide table 6-5, so that is another advantage of putting most variables in lower FRAM. Let me know if you need some help modifying the linker file if you want to use upper FRAM for variables.

    Regards,
    Katie
  • Akash Patel said:

    We are looking at the MSP430FR59xx devices that have 128k and 256k FRAM. On page 123 of the MSP430 Optimizing C/C++ Compiler v16.12.0.STS User's Guide (http://www.ti.com/lit/ug/slau132n/slau132n.pdf) it says "All current MSP430X devices do not have any writeable memory above the 64K boundary." I imagine this has to do with the 16-bit nature of the MSP device.

    All FRAM devices are with CPUXv2 and 20-bit registers with covered 1 MByte address space.

  • Hi Katie,

    Thanks very much for answering this question quickly.

    In our application we would like to use the majority of the FRAM as data buffers, hence I would like to ability to be able to use FRAM space above 64K for variables.

    I have attempted to modify the .cmd file to accomodate this but am still getting compiler errors.

    In the default file, "lnk_msp430fr5994.cmd" I have changed/added the following lines:

    Was:
    FRAM2 : origin = 0x10000,length = 0x34000
    Is now:
    FRAM2 : origin = 0x10000,length = 0x14000
    FRAM3 : origin = 0x24000,length = 0x20000

    I did this because I am developing on a 5994 launchpad but eventually plan on using the 5962 with 128K of memory and want to ensure everything is placed in either FRAM or FRAM2 (nothing in FRAM3).

    Next, I added the following line right above the .cinit, .binit, .pinit (etc.) allocation section:

    .TI.noinit : {} > FRAM | FRAM2 /* For #pragma NOINIT */

    I did this because I was trying to use the #pragma NOINIT function. So, in a source file, I created two test variables this way:

    #pragma NOINIT(Test1)
    unsigned int Test1[10];

    #pragma NOINIT(Test2)
    unsigned int Test2[10];

    This compiles fine until the size of the "Test" variables increases to point where FRAM is full. Checking the .map file, availabe space in FRAM decreases as the test variable array size increases but FRAM2 available space does not change, even when the variables overflow the size of FRAM. The reason I tested with two variables was to see if the compiler would move one of the variables to FRAM2 once they overflowed the size of FRAM. Instead I get the following error on compilation:

    "... error #10099-D: program will not fit into available memory. placement with alignment fails for section ".cinit" size 0x12 . ..."

    For reference, at the bottom of this message I will paste in the entire .cmd file I am using.

    Thanks for the help!

    _________________________________________________________________________________________________________

    /******************************************************************************
    *
    * Copyright (C) 2012 - 2016 Texas Instruments Incorporated - http://www.ti.com/
    *
    * 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.
    *
    * Default linker command file for Texas Instruments MSP430FR5994
    *
    *****************************************************************************/

    /******************************************************************************/
    /* */
    /* 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.192 */
    /*----------------------------------------------------------------------------*/

    /****************************************************************************/
    /* SPECIFY THE SYSTEM MEMORY MAP */
    /****************************************************************************/

    MEMORY
    {
    TINYRAM : origin = 0xA, length = 0x16
    BSL : origin = 0x1000, length = 0x800
    INFOD : origin = 0x1800, length = 0x80
    INFOC : origin = 0x1880, length = 0x80
    INFOB : origin = 0x1900, length = 0x80
    INFOA : origin = 0x1980, length = 0x80
    RAM : origin = 0x1C00, length = 0x1000
    FRAM : origin = 0x4000, length = 0xBF80
    FRAM2 : origin = 0x10000,length = 0x14000
    FRAM3 : origin = 0x24000,length = 0x20000
    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 LEA memory map */
    /****************************************************************************/

    #define LEASTACK_SIZE 0x138

    MEMORY
    {
    LEARAM : origin = 0x2C00, length = 0x1000 - LEASTACK_SIZE
    LEASTACK : origin = 0x3C00 - LEASTACK_SIZE, length = LEASTACK_SIZE
    }

    /****************************************************************************/
    /* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY */
    /****************************************************************************/

    SECTIONS
    {
    GROUP(RW_IPE)
    {

    GROUP(READ_WRITE_MEMORY)
    {
    .TI.persistent : {} /* For #pragma persistent */
    .cio : {} /* C I/O Buffer */
    .sysmem : {} /* Dynamic memory allocation area */
    } PALIGN(0x0400), RUN_START(fram_rw_start)

    GROUP(IPENCAPSULATED_MEMORY)
    {

    .ipestruct : {} /* IPE Data structure */
    .ipe : {} /* IPE */
    .ipe_const : {} /* IPE Protected constants */
    .ipe:_isr : {} /* IPE ISRs */
    } PALIGN(0x0400), RUN_START(fram_ipe_start) RUN_END(fram_ipe_end) RUN_END(fram_rx_start)

    } > 0x4000

    .TI.noinit : {} > FRAM | FRAM2 /* For #pragma NOINIT */
    .cinit : {} > FRAM /* Initialization tables */
    .binit : {} > FRAM /* Boot-time 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 */
    .text:_isr : {} > FRAM /* Code ISRs */

    #ifndef __LARGE_DATA_MODEL__
    .const : {} > FRAM /* Constant data */
    #else
    .const : {} >> FRAM | FRAM2 /* Constant data */
    #endif

    #ifndef __LARGE_DATA_MODEL__
    .text : {} > FRAM /* Code */
    #else
    .text : {} >> FRAM2 | FRAM /* Code */
    #endif

    #ifdef __TI_COMPILER_VERSION__
    #if __TI_COMPILER_VERSION__ >= 15009000
    #ifndef __LARGE_DATA_MODEL__
    .TI.ramfunc : {} load=FRAM, run=RAM, table(BINIT)
    #else
    .TI.ramfunc : {} load=FRAM | FRAM2, run=RAM, table(BINIT)
    #endif
    #endif
    #endif

    .jtagsignature : {} > JTAGSIGNATURE
    .bslsignature : {} > BSLSIGNATURE

    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 */

    /* MSP430 INFO memory segments */
    .infoA : {} > INFOA
    .infoB : {} > INFOB
    .infoC : {} > INFOC
    .infoD : {} > INFOD


    .leaRAM : {} > LEARAM /* LEA RAM */
    .leaStack : {} > LEASTACK (HIGH) /* LEA STACK */

    /* 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
    LEA_SC : { * ( .int18 ) } > INT18 type = VECT_INIT
    PORT8 : { * ( .int19 ) } > INT19 type = VECT_INIT
    PORT7 : { * ( .int20 ) } > INT20 type = VECT_INIT
    EUSCI_B3 : { * ( .int21 ) } > INT21 type = VECT_INIT
    EUSCI_B2 : { * ( .int22 ) } > INT22 type = VECT_INIT
    EUSCI_B1 : { * ( .int23 ) } > INT23 type = VECT_INIT
    EUSCI_A3 : { * ( .int24 ) } > INT24 type = VECT_INIT
    EUSCI_A2 : { * ( .int25 ) } > INT25 type = VECT_INIT
    PORT6 : { * ( .int26 ) } > INT26 type = VECT_INIT
    PORT5 : { * ( .int27 ) } > INT27 type = VECT_INIT
    TIMER4_A1 : { * ( .int28 ) } > INT28 type = VECT_INIT
    TIMER4_A0 : { * ( .int29 ) } > INT29 type = VECT_INIT
    AES256 : { * ( .int30 ) } > INT30 type = VECT_INIT
    RTC_C : { * ( .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
    EUSCI_A1 : { * ( .int43 ) } > INT43 type = VECT_INIT
    TIMER0_A1 : { * ( .int44 ) } > INT44 type = VECT_INIT
    TIMER0_A0 : { * ( .int45 ) } > INT45 type = VECT_INIT
    ADC12_B : { * ( .int46 ) } > INT46 type = VECT_INIT
    EUSCI_B0 : { * ( .int47 ) } > INT47 type = VECT_INIT
    EUSCI_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 >> 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
    #ifdef _IPE_ENABLE //if IPE is used in project too
    //seg1 = any read + write persistent variables
    //seg2 = ipe = read + write + execute access
    //seg3 = code, read + execute only
    mpu_segment_border1 = fram_ipe_start >> 4;
    mpu_segment_border2 = fram_rx_start >> 4;
    mpu_sam_value = 0x1573; // Info R, Seg3 RX, Seg2 RWX, Seg1 RW
    #else
    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
    #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 msp430fr5994.cmd
  • Also, in case this information helps:

    CCS version 6.2.0.00050

    Compiler: TI v15.12.3.LTS

    In compiler settings, Silicon version = mspx

    Data memory model = restricted

    code memory model = large

    Compiler settings:

    -vmspx --data_model=restricted --use_hw_mpy=F5 --include_path="C:/ti/ccsv6/ccs_base/msp430/include" --include_path=".../driverlib/MSP430FR5xx_6xx" --include_path="C:/ti/ccsv6/tools/compiler/msp430_15.12.3.LTS/include" --advice:hw_config=all -g --define=DEPRECATED --define=__MSP430FR5994__ --define=_MPU_ENABLE --display_error_number --diag_warning=225 --diag_wrap=off --silicon_errata=CPU21 --silicon_errata=CPU22 --silicon_errata=CPU40 --printf_support=minimal --c_src_interlist
  • Hi Matt,

    The error message that it's giving you isn't actually complaining about placement of either of your arrays - rather it is saying it has no more room for .cinit, which contains the c-startup code that will set up the device (set up the stack pointer etc) and initialize all of your other variables before main runs. .cinit has to be in lower FRAM below the 64K boundary, because it is what the reset vector points to and the reset vector (and all other interrupt vectors) can only contain a 16-bit address - therefore it has to go in lower memory. You could try rearranging the linker to allocate a place for .noinit after allocating space for all the things that have to be in lower FRAM (like .cinit, .text:_isr, etc) instead of before, which is where you have it now. You could also try increasing the size of one of the variables but not the other and see if that makes one of them jump over - you can also view the .map file to see where things are being placed and what is in each section, and how much space .cinit needs (under the Debug folder in your workspace). Another thing to keep in mind is that it won't split up an array - so in some instances it can make sense to make more smaller arrays so that they can be placed part in lower and part in upper FRAM. I hope this helps to provide some pointers to get things working for you.

    Regards,
    Katie
  • Akash,

    For the note in the C Compiler guide, I created a post in the (DO NOT USE) TI C/C++ Compiler - Forum and they confirmed that the first sentence you mentioned out-of-date here: e2e.ti.com/.../2056451

    Regards,
    Katie
  • Thank you. After reviewing the Compiler Guide and Assembly Language Tool Guide, I've come up with something "good enough" for now:

    I modified the linker command file MEMORY and SECTIONS to have PFRAM (program FRAM) in lowest 16K, B1FRAM (buffer 1 FRAM) filling the remainder of lower 64K but ending before interrupt vectors and B2FRAM (upper 64K FRAM) for additional variables.

    Also your earlier comment about needing to use compiler intrinsic like "__data20_write_char(*MainBufLoc_l, 0x01);" to write and read to variables above 64K solved another compiler error I was getting even when the variables were correctly allocated to that space.

    Posting the linker file below for others benefit:

    /******************************************************************************
    *
    * Copyright (C) 2012 - 2016 Texas Instruments Incorporated - http://www.ti.com/
    *
    * 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.
    *
    * Default linker command file for Texas Instruments MSP430FR5994
    *
    *****************************************************************************/

    /******************************************************************************/
    /* */
    /* 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.192 */
    /*----------------------------------------------------------------------------*/

    /****************************************************************************/
    /* SPECIFY THE SYSTEM MEMORY MAP */
    /****************************************************************************/

    MEMORY
    {
    TINYRAM : origin = 0xA, length = 0x16
    BSL : origin = 0x1000, length = 0x800
    INFOD : origin = 0x1800, length = 0x80
    INFOC : origin = 0x1880, length = 0x80
    INFOB : origin = 0x1900, length = 0x80
    INFOA : origin = 0x1980, length = 0x80
    RAM : origin = 0x1C00, length = 0x1000
    PROG_FRAM : origin = 0x4000, length = 0x4000 /*ALMOST 48K long*/
    BUF1_FRAM : origin = 0x8000, length = 0x7F80 /*Ends at 0xFF80 where JTAG/INT Vectors begin*/
    BUF2_FRAM : origin = 0x10000,length = 0x14000 /*64K + 16K long*/
    /* FRAM3 (RWXI) : origin = 0x20000,length = 0x24000 */
    FRAM3 : origin = 0x24000,length = 0x20000 /*128K long*/
    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 LEA memory map */
    /****************************************************************************/

    #define LEASTACK_SIZE 0x138

    MEMORY
    {
    LEARAM : origin = 0x2C00, length = 0x1000 - LEASTACK_SIZE
    LEASTACK : origin = 0x3C00 - LEASTACK_SIZE, length = LEASTACK_SIZE
    }

    /****************************************************************************/
    /* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY */
    /****************************************************************************/

    SECTIONS
    {
    GROUP(RW_IPE)
    {

    GROUP(READ_WRITE_MEMORY)
    {
    .TI.persistent : {} /* For #pragma persistent */
    .cio : {} /* C I/O Buffer */
    .sysmem : {} /* Dynamic memory allocation area */
    } PALIGN(0x0400), RUN_START(fram_rw_start)

    GROUP(IPENCAPSULATED_MEMORY)
    {

    .ipestruct : {} /* IPE Data structure */
    .ipe : {} /* IPE */
    .ipe_const : {} /* IPE Protected constants */
    .ipe:_isr : {} /* IPE ISRs */
    } PALIGN(0x0400), RUN_START(fram_ipe_start) RUN_END(fram_ipe_end) RUN_END(fram_rx_start)

    } > 0x4000

    .cinit : {} > PROG_FRAM /* Initialization tables */
    .binit : {} > PROG_FRAM /* Boot-time Initialization tables */
    .pinit : {} > PROG_FRAM /* C++ Constructor tables */
    .init_array : {} > PROG_FRAM /* C++ Constructor tables */
    .mspabi.exidx : {} > PROG_FRAM /* C++ Constructor tables */
    .mspabi.extab : {} > PROG_FRAM /* C++ Constructor tables */
    .text:_isr : {} > PROG_FRAM /* Code ISRs */

    sec1 : {} > BUF1_FRAM, type = NOINIT
    sec2 : {} > BUF2_FRAM, type = NOINIT

    #ifndef __LARGE_DATA_MODEL__
    .const : {} > PROG_FRAM /* Constant data */
    #else
    .const : {} > PROG_FRAM /* Constant data */
    #endif

    #ifndef __LARGE_DATA_MODEL__
    .text : {} > PROG_FRAM /* Code */
    #else
    .text : {} > PROG_FRAM /* Code */
    #endif

    #ifdef __TI_COMPILER_VERSION__
    #if __TI_COMPILER_VERSION__ >= 15009000
    #ifndef __LARGE_DATA_MODEL__
    .TI.ramfunc : {} load=PROG_FRAM, run=RAM, table(BINIT)
    #else
    .TI.ramfunc : {} load=PROG_FRAM, run=RAM, table(BINIT)
    #endif
    #endif
    #endif

    .jtagsignature : {} > JTAGSIGNATURE
    .bslsignature : {} > BSLSIGNATURE

    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 */

    /* MSP430 INFO memory segments */
    .infoA : {} > INFOA
    .infoB : {} > INFOB
    .infoC : {} > INFOC
    .infoD : {} > INFOD


    .leaRAM : {} > LEARAM /* LEA RAM */
    .leaStack : {} > LEASTACK (HIGH) /* LEA STACK */

    /* 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
    LEA_SC : { * ( .int18 ) } > INT18 type = VECT_INIT
    PORT8 : { * ( .int19 ) } > INT19 type = VECT_INIT
    PORT7 : { * ( .int20 ) } > INT20 type = VECT_INIT
    EUSCI_B3 : { * ( .int21 ) } > INT21 type = VECT_INIT
    EUSCI_B2 : { * ( .int22 ) } > INT22 type = VECT_INIT
    EUSCI_B1 : { * ( .int23 ) } > INT23 type = VECT_INIT
    EUSCI_A3 : { * ( .int24 ) } > INT24 type = VECT_INIT
    EUSCI_A2 : { * ( .int25 ) } > INT25 type = VECT_INIT
    PORT6 : { * ( .int26 ) } > INT26 type = VECT_INIT
    PORT5 : { * ( .int27 ) } > INT27 type = VECT_INIT
    TIMER4_A1 : { * ( .int28 ) } > INT28 type = VECT_INIT
    TIMER4_A0 : { * ( .int29 ) } > INT29 type = VECT_INIT
    AES256 : { * ( .int30 ) } > INT30 type = VECT_INIT
    RTC_C : { * ( .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
    EUSCI_A1 : { * ( .int43 ) } > INT43 type = VECT_INIT
    TIMER0_A1 : { * ( .int44 ) } > INT44 type = VECT_INIT
    TIMER0_A0 : { * ( .int45 ) } > INT45 type = VECT_INIT
    ADC12_B : { * ( .int46 ) } > INT46 type = VECT_INIT
    EUSCI_B0 : { * ( .int47 ) } > INT47 type = VECT_INIT
    EUSCI_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 >> 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
    #ifdef _IPE_ENABLE //if IPE is used in project too
    //seg1 = any read + write persistent variables
    //seg2 = ipe = read + write + execute access
    //seg3 = code, read + execute only
    mpu_segment_border1 = fram_ipe_start >> 4;
    mpu_segment_border2 = fram_rx_start >> 4;
    mpu_sam_value = 0x1573; // Info R, Seg3 RX, Seg2 RWX, Seg1 RW
    #else
    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
    #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 msp430fr5994.cmd
  • Hi Matt,

    I'm glad we were able to help with a couple of your problems at once. Thanks for sharing your modifications for others as well. Please feel free to let us know if you need any more help with details of this implementation.

    Regards,
    Katie
  • Hi Matt,

    One other thing - we also include examples of LZ4 compression as part of our FRAM Utilities included in MSP430Ware: dev.ti.com/.../ This could let you compress data and store that in FRAM if that makes sense for your application (since it sounds like you need so much storage).

    Regards,
    Katie

**Attention** This is a public forum