CCS #pragma PERSISTENT 命令问题

进士 2075 points

在CCS7.3中开发MSP430程序, 在link .cmd文件中添加了命令:.TI.persistent : {} > FRAM

然后使用定义变量 x 到FRAM中, 在程序中让 x 自加,发现 x 的值不能改变,为什么 ?

#pragma PERSISTENT(x)
unsigned int x = 5;

MG

  • 回复 m:

    可以在CMD文件中直接指定一个地址给一个变量例如:  PassWd = 0x1C00; (这类定义一般放在CMD文件最前前面)然后在.C文件中添加声明extern uint16_t  PassWd;就可以在程序中可以直接修改了PassWd了。

  • 进士 2075 points

    回复 Chao Gao5:

    那如果是在在CMD文件中直接指定一个地址给一个数组呢,怎么操作? 


    MG

  • 进士 2075 points

    回复 Chao Gao5:

    我在.cmd中 : PassWd = 0x5000; //将变量存于FRAM中

    然后在main.c 中:extern uint16_t  PassWd;

    这样程序编没问题,但是似乎不能正常运行啊?

    MG

  • 回复 m:

    你好

    我在MSP430FR5994的Lanchpad 上测试过,没有问题的。这是我的测试代码。你再仔细检查一下把。

    CMD文件无法上传我就直接复制在这里吧

    PassWd = 0x1C00;

    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 = 0x34000
    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 : {} > 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_CODE_MODEL__
    .text : {} > FRAM /* Code */
    #else
    .text : {} >> FRAM2 | FRAM /* Code */
    #endif

    #ifdef __TI_COMPILER_VERSION__
    #if __TI_COMPILER_VERSION__ >= 15009000
    #ifndef __LARGE_CODE_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 : type = NOINIT{} > INFOA
    .infoB : type = NOINIT{} > INFOB
    .infoC : type = NOINIT{} > INFOC
    .infoD : type = NOINIT{} > 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 : { * ( .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

  • 进士 2075 points

    回复 Chao Gao5:

    好的,谢谢!

    另外请教两个关于cmd文件的问题:

    1. FRAM一定要这样划分吗?是不是只要地址不重叠就可以随意修改?

    FRAM : origin = 0x4000, length = 0xBF80
    FRAM2 : origin = 0x10000,length = 0x34000


    2.  

    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

    这样就是讲 #pragma PERSISTENT 命令定义的变量存放在0x4000处,即前面划分的FRAM : origin = 0x4000, length = 0xBF80 ,len=0xBF80(47KB), 但是如果变量太大,这个地址空间不够用怎么处理?


    MG

  • 回复 m:

    Hi m

    1. FRAM之所以划分成两部分是为了避开中断向量表。

                      比如            .const            : {} >> FRAM | FRAM2  /* Constant data                     */  常量在FRAM 区域不够使用时,会自动使用FRAM2区域

    2.这个问题我们后续会发布一个Application report 会详解讲解如何进行FRAM区域读写权限的划分。看你之前发的帖子应该是在使用FR5994吧。对于FR5XX6XX 因为带有MPU模块。可以使用这个模块进行读写区域权限划分。这里提供一个CCS修改的过程

    (1)在C代码中使用 声明变量比如

                       #pragma PERSISTENT (framArray1)

                             uint8_t framArray1[0xFFFF] = {0};

    (2)修改CMD文件

          假如我需要设置的读写区域:0x4000~0x20000 为RX(read and execute)    0x20000~0x20400为R  其它为RW(read and write)

           

         FRAM                    : origin = 0x4000, length = 0xBF80

        //FRAM2                 : origin = 0x10000,length = 0x34000

        FRAM2                   : origin = 0x10000,length = 0x10000

        FRAM_READ_ONLY          : origin = 0x20000,length = 0x4000

        FRAM_READ_WRITE         : origin = 0x20400,length = 0x23C00

    把GROUP(RW_IPE)放到FRAM_READ_WRITE区(原先起始地址为0x4000)

    GROUP(RW_IPE)
    {

    } > FRAM_READ_WRITE

    然后把常量放到只读区域

    #ifndef __LARGE_DATA_MODEL__

        .const            : {} > FRAM_READ_ONLY          /* Constant data                     */

    #else

        .const            : {} > FRAM_READ_ONLY  /* Constant data                     */

    #endif

    然后设置CCS GUI

    然后把数据模式改成Large就可以了,你就可以定义超过64k大小的数组了。

    对于IAR 暂时没有详细的流程,但是需要的工作是差不多的,但IAR GUI 目前还不提供图像化的MPU配置功能,需要用户手动配置MPU寄存器。同样也需要修改Link file.

  • 进士 2075 points

    回复 Chao Gao5:

    十分感谢这么晚还回帖,问题基本解决了,给力!

    MG