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.

[参考译文] MSP430FR2476:修改链接器文件以存储永久变量时出现问题

Guru**** 2386620 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1258559/msp430fr2476-problem-modifying-linker-file-to-store-persist-variables

器件型号:MSP430FR2476
主题中讨论的其他器件:MSPWARE

你好

我想使用 FRAM 来为我的应用程序存储一些持久变量。 这些是校准变量、所以它们必须是写入/读取的。

我遵循了 CCS/Resource Explorer/MSPware 中的"msp430fr267x_framwrite_persistent.c"示例、该示例运行起来非常顺利、但我不知道这些变量存储在 FRAM 的哪个位置

#include <msp430.h>

// Statically-initialized variable
#ifdef __TI_COMPILER_VERSION__
#pragma PERSISTENT(Port_event)
unsigned long Port_event = 0;
#elif __IAR_SYSTEMS_ICC__
__persistent unsigned long Port_event = 0;
#else
// Port the following variable to an equivalent persistent functionality for the specific compiler being used
unsigned long Port_event = 0;
#endif

void initGpio(void);

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;               // Stop WDT

    // Configure GPIO
    initGpio();

    // Determine whether we are coming out of an LPMx.5 or a regular RESET.
    if (SYSRSTIV == SYSRSTIV_LPM5WU)        // MSP430 just woke up from LPMx.5
    {

        // Add the variable Port_event in FRAM to record the button event
        // Write protection starts from the beginning of Program FRAM + 1024 bytes
        // Code start address + 1024 bytes, Linker command file should be modified
        SYSCFG0 = FRWPPW | FRWPOA0 | DFWP | PFWP;// Configure 1024 bytes for FRAM write
        Port_event++;                       // Record the port event in FRAM
        SYSCFG0 = FRWPPW | DFWP | PFWP;     // Program FRAM write protected (not writable)

        do
        {

            P1OUT |= BIT0;                  // P1.0 = toggle
            __delay_cycles(100000);
            P1OUT &= ~BIT0;                 // P1.0 = toggle
            __delay_cycles(100000);

        }while (Port_event >= 5);           // Recorded 5 port interrupts?

    }

    // Device powered up from a cold start.
    // It configures the device and puts the device into LPM4.5

    P1DIR &= ~(BIT2);                       // Configure P1.2 as input direction pin
    P1OUT |= BIT2;                          // Configure P1.2 as pulled-up
    P1REN |= BIT2;                          // P1.2 pull-up register enable
    P1IES |= BIT2;                          // P1.2 Hi/Low edge
    P1IFG = 0;                              // Clear all P1 interrupt flags
    P1IE |= BIT2;                           // P1.2 interrupt enabled

    // Explicitly clear RTC control registers to disable it
    // just incase if the RTC was previously enabled
    RTCCTL = 0;

    PMMCTL0_H = PMMPW_H;                    // Open PMM Registers for write
    PMMCTL0_L |= PMMREGOFF;                 // and set PMMREGOFF
    PMMCTL0_H = 0;                          // Lock PMM Registers

    // Enter LPM4 Note that this operation does not return. The LPM4.5
    // will exit through a RESET event, resulting in a re-start
    // of the code.
    __bis_SR_register(LPM4_bits | GIE);
}

-- pragma persistent

#pragma PERSISTENT (端口事件)
无符号长整型 PORT_EVENT = 0;

--写变量

//在 FRAM 中添加变量 PORT_EVENT 以记录按钮事件
//写保护从程序 FRAM + 1024字节的开头开始
//代码起始地址+ 1024字节,应修改连接器命令文件
SYSCFG0 = FRWPPW | FRWPOA0 | DFWP | PFWP;//配置1024个字节进行 FRAM 写入
PORT_EVENT++;//在 FRAM 中记录端口事件
SYSCFG0 = FRWPPW | DFWP | PFWP;//程序 FRAM 受写保护(不可写)

在该示例的说明中提到 " 应修改链接器命令文件以更改存储器分区并指定 persistent 变量的位置"

能否提供有关如何将 persistent 变量"放置"到不同存储器位置的一些示例?

查看应用报告 SLAA628b、示例3 (针对 CCS)显示了如何分配一个新的内存块+定义一个存储在这个内存块中的段。

1.分配一个新的存储块(MY_SECTION)。

2.定义存储在此存储块(MY_SECTION)中的段(.Image)。

3.在程序中使用#pragma DATA_SECTION 来定义此段中的变量。   

RAM                     : origin = 0x2000, length = 0x400    
RAM2                    : origin = 0xF100, length = 0x100    
MY_SECTION              : origin = 0xF200, length = 0x100    
FRAM                    : origin = 0xF300, length = 0xC80    

.Image      : {} > MY_SECTION   

#pragma DATA_SECTION(a,".Image")    unsigned char a;

问题是我无法使用第一个例子中的"--write variable"方法在这个新内存块上写入变量。

我是否应该在 FRAM 段内声明这个新的内存块? 如果是这种情况、您能否向我指出如何实现?  

此外、我不知道创建新的内存块而不是使用已声明的持久内存是否是一个好的做法  

此致

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    对于校准、我认为信息存储器是更好的选择。 我的偏好是创建一个保存校准数据的结构、然后使用 memcpy ()(或等效)从信息存储器中读取数据。 无需摆弄链接器脚本。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Albert:

    有关 persistent 关键字的一些信息可在 编译器用户指南中找到。  

    默认情况下、persistent 将置于数据段

    在您链接的示例中、如果打开链接器文件(.cmd)、您可以看到存储器组织是如何构造的。  

    此致、

    卢克

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的快速回答。

     

    这里的问题是、我在离散项目上有一个自定义引导加载程序(使用 MSP430FRBoot 作为基础)。 此引导加载程序为3K 并位于主存储器中。

     

    没有引导加载程序时、主应用可以正常运行、但从引导加载程序加载时、它的运行不正常。 此外、如果主应用程序不使用持久变量、则可以通过引导加载程序正常加载应用程序。

     

    在进行测试后、我发现主要问题是应用程序中有一个部分由引导加载程序进行单步执行。 这就是我尝试了解如何创建数据段或者看看我是否可以控制持久性变量的放置位置的原因

     

    遵循的程序是:

    1. 使用"MSPFRBOOT_LinkerGen"生成用于引导和主应用的链接器
      1. 此时、我正在使用我的 MCU 中的标准未修改连接器文件、
    2. 使用引导链接器编译引导并生成输出文件(boot.txt)
    3. 使用 main app 链接器编译主 app 并生成一个输出文件(main_app.txt)

     

    为了解决此问题、我应该从主应用程序修改链接器文件吗? 我猜测、由于持久数据放置在.data 上、但该段未被保留、因此 LinkerGen 可将部分引导应用程序放在那里、之后、由于引导应用程序正在使用这些地址、MAIN_APP 无法写入这些地址。

     

    在 FRAM 部分中生成新的存储块可以解决该问题? 如何"阻止".data 段、使其不会被引导加载程序淹没?

     

    此致

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Albert:

    我认为 MSP430 FRAM 器件引导加载程序用户指南 中包含您需要的信息。 对于引导配置、我认为您的引导链接器文件和应用链接器文件具有不同的内存部分。 我建议您将引导加载程序部分置于 FRAM 中用于存储校准变量的区域之外、这样就不会认为空间是自由的。

    您还可以通过对 FRAM 进行分区来更改持久性变量的放置位置。  如果需要的话、您可以将 FRAM 块分解成一个更小的变量部分。 在链接器文件中、您可以在"存储器"部分看到、它们将 FRAM 设置为 origin 0x8000、length 为0x7F80。 您可以做的是缩短链接器文件"FRAM"的长度并创建一个新器件以包含您的校准变量、只需确保长度匹配、以便没有重叠、并且您处于所需的存储器段内。

    下面是存储器组织、以便您知道允许使用的范围。

    此致、

    卢克