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/MSP430FR5959: MPU no standart configure section

Part Number: MSP430FR5959

Tool/software: TI C/C++ Compiler

Why configure not standart section order in FRAM?

Need

//seg1 = const, read only
//seg2 = code = read + execute access
//seg3 = any read + write persistent variables

In this CMD not effects in automatic calculate

SECTIONS
{
    .TI.noinit  : {} > RAM        /* For #pragma noinit                */
    .bss        : {} > RAM        /* Global & static vars              */
    .data       : {} > RAM        /* Global & static vars              */
    .stack      : {} > RAM (HIGH) /* Software system stack             */

    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

    GROUP(READ_ONLY_MEMORY)
    {
       .cinit         : {}        /* Initialization tables             */
       .pinit         : {}        /* C++ Constructor tables            */
       .init_array    : {}        /* C++ Constructor tables            */
       .mspabi.exidx  : {}        /* C++ Constructor tables            */
       .mspabi.extab  : {}        /* C++ Constructor tables            */
       .const         : {}        /* Constant data                     */
    } PALIGN(0x0400), RUN_END(fram_rx_start) > FRAM

    GROUP(EXECUTABLE_MEMORY)
    {
       .text:_isr     : {}        /* Code ISRs                         */
       .text          : {}        /* Code                              */
    } PALIGN(0x0400), RUN_END(fram_rw_start) > FRAM

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

    logger_buff       : {} > DATA2 type=NOINIT

    .jtagsignature : {} > JTAGSIGNATURE     /* JTAG Signature                    */
    .bslsignature  : {} > BSLSIGNATURE      /* BSL Signature                     */

    GROUP(SIGNATURE_SHAREDMEMORY)
    {
       .ipesignature   : {}       /* IPE Signature                     */
       .jtagpassword   : {}       /* JTAG Password                     */
    } > IPESIGNATURE

    .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                               */
/****************************************************************************/
.....
   // 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
         //seg1 = const, read only
         //seg2 = code = read + execute access
         //seg3 = any read + write persistent variables
      mpu_segment_border1 = fram_rx_start >> 4;
      mpu_segment_border2 = fram_rw_start >> 4;
      mpu_sam_value = 0x1531; // Info R, Seg3 RW, Seg2 RX, Seg1 R 
   #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

result map:

  • Hi Alexander,

    Thanks for posting. I'm going to look into this but I want to make sure I understand your question. It looks like you have modified the linker file to change the order of the MPU sections to be read only, then read + execute, then read + write. Are you having problems getting that configuration to work? Or are you asking why this order is not used as the default linker configuration that we provide for the device?

    Regards,
    Katie
  • Problem in my config.
    MPU - only 3 section
    I use FRAM2 (rename to DATA2) for unsend packet buffer - RW area, in default use for const and read-only.
    Function __data20_write_char() not write to this area.
    If disable MPU - function work - ok, i think change section order - remove RW section to end and make FRAM2 to RW
    My idea order section:
    1 section - RO: const (FRAM)
    2 section - RX: code (FRAM)
    3 section - RW: data (FRAM) and big array (FRAM2)
    1 variant - manual selection in GUI borders - no automatic recalculate :(((
    2 variant - cut FRAM to 2 area and move RO to first piece and other to other- no automatic recalculate :(((
    3 variant - change linker CMD - good idea if work possible - automatic recalculator
    I read all link in internet for examle, not need for me :(((
    Write many variants CMD and not remove const section to beigin FRAM
    const section in all variants CMD move to end of FRAM and ignore CMD
    help me for commands to need order section/
    Thanks.
  • 2 variant is not workin
    cut FRAM
    FRAMRO : origin = 0x4400, length = 0x1000
    FRAM: origin = 0x5400, length = 0xAB80
    and move GROUP(READ_ONLY_MEMORY) to FRAMRO
    result - no link, no complile
  • .const : {} > FRAM /* Constant data */
    .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 */

    not like if this section move to any group

    decision one - disable MPU future if use read/write to FRAM2 ?
  • Hi Alexander,

    I made some modifications to the linker file myself and came up with the attached file - please try this.

    https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/166/lnk_5F00_msp430fr5959_5F00_mod.cmd

    Assumptions:

    1. I don't think you need IPE so I took it out
    2. all of FRAM2 0x10000+ is for read+write memory
    3. nothing below 0x10000 will be needed for read + write memory

    Let me know if any of these assumptions are incorrect for your use-case and I can help adjust the linker file further.

    A few notes on what I had to change vs your version in first post:

    1. changed MPUSAM value to 0x1351 to correctly set segment 3 to read + write access and segment 2 to read + execute access
    2. placed GROUP(READ_WRITE_MEMORY) in FRAM2, not FRAM so it will put .persistent in the upper memory

    In your code you would place your buffer in the read write area using something like this:

    #pragma PERSISTENT(rx_buffer)
    unsigned char rx_buffer[16000] = {0};

    Then in the MPU tool in CCS simply set it to use the automatic configuration - with this linker file it should give you the correct boundaries.

    Please let me know if this works for you or if there is more I can do to help!

    Regards,

    Katie

  • I select other way

    Load old linker comman file and enable MPU

    in function to write FRAM2 I disable MPU, write to array, enable MPU

    /*** Read record to far buffer ***/
    void writePacketBuff(unsigned int num, unsigned char* buf){
    	unsigned int block=(PACKET_LEN>>2)-1;
    	unsigned int i=block;
    	unsigned int k=0;
    	unsigned char mpu_on=FALSE;
    	if(MPUCTL0 & MPUENA){
    		mpu_on=TRUE;
    		MPUCTL0=MPUPW;
    	}
    	do{
    		k=(block-i)*4;
    		__data20_write_long((unsigned long int)packetBUFF+num*PACKET_LEN+k,*(unsigned long*)&buf[k]);
    	}while(i--);
    	if(mpu_on) MPUCTL0=MPUPW | MPUENA;
    }
    

    Your variant test next day and ansver your.

    Big Thanks.

  • Hi Alexander,

    Thanks for your reply. One concern I have with your alternate method is that this totally disables the MPU for the time period where you are writing your data, and that can be risky in that if somehow the pointer was wrong, something unexpected happens that jumps you out of this routine, etc. - during this time your code is completely unprotected and you could end up overwriting your application code which could break your functionality. Hopefully if you are able to try the linker file I've provided it will help you to get around the issue so you won't have to do it this way.

    Regards,
    Katie
  • 104 errors with your configuration

    I use FRAM2 for only packet buffer (size of buffer 100% FRAM2)

    other RW value in FRAM (include .persistent)

    Problems - 3 section avaiable

    Need RW data in last section for increase size RW data area

    but const and other R/O data compiler place to end of FRAM and make unavaiable create big RW area

  • Hi Alexander,

    Are you saying that you have other data in .persistent and so you need RW access in both FRAM2 and part of lower FRAM as well? I think I understand now - that would explain why my first version would not work.

    Have you considered using the 3 segments instead such that you have 2 R+W segments (one for all of FRAM2, and one at the beginning of lower FRAM), and then 1 segment of Read + execute memory (place the consts and code together)? The consts will still be write protected in this configuration, which is the most important.

    0x13FFF--------------------------------------------------
    receive Buffer area, R + W
    0x10000 -------------------------------------------------
    Code + consts, R + X
    0x4800 ---------------------------------------------------
    Other FRAM data (.persistent), R + W
    0x4400 ---------------------------------------------------

    It is good to keep the addresses just before and including 0xFFFF as not-writeable because the Interrupt vector table, JTAG signatures, and reset vector are located there and have to be there (fixed addresses) - an erroneous write to the reset vector for example could make your code non-functional.
     
    Regards,
    Katie

  • it is variant - append code and constants to one area
  • Hi Alexander,

    I modified the linker file to match this variant (use the MPU tool set to let compiler and linker handle it). Here it is attached:

    https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/166/5340.lnk_5F00_msp430fr5959_5F00_mod.cmd

    Here is what was in the c-code for testing and showing how to place data. PERSISTENT is placed in the lower RW area, whereas .receiveData is the name I gave to the section for FRAM2 for your receive buffer.

    const unsigned char const_data[40000] = {0xAA};
    
    #pragma DATA_SECTION(receiveBuffer, ".receiveData")
    unsigned char receiveBuffer[16000] = {0};
    
    #pragma PERSISTENT(otherData)
    unsigned char otherData[1000] = {0};

    Regards,

    Katie

**Attention** This is a public forum