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.

[参考译文] MSP430FR6928:链接器命令和.ti.noinit 问题

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1334742/msp430fr6928-issues-with-linker-command-and-ti-noinit

器件型号:MSP430FR6928
主题中讨论的其他器件: MSP430FR6989

我曾尝试将此帖子作为 Code Composer Studio 问题发布、但后来被带到这个论坛

我编写了一个应用程序、其中我从不同的源(例如 a2d、计时器计算等)收集数据、并将收集到的数据作为结构的对象放置。 然后、我创建一个包含这些结构的数组。
我使用的是 MSP430FR6928。 首先,数组有大约100个对象。 我使用的链接器命令是由 CCS 创建的默认命令。 原始阵列放置在 FRAM 中。
然后我修改了代码、以便将该数组和索引变量放置在.ti.persistent 段中。 也没有问题。 (默认链接器将.ti.persistent 段放置在 FRAM 中)。
然后、我修改了.ti.persistent 段的位置、并将数组和索引变量(无符号整数)移至 FRAM2。 当我这样做时,首先我有一个错误,解决了将内存模型更改为大(我还将"什么数据必须接近"选项更改为"无"). 程序编译没有错误,但现在,当我检查区域的 FRAM2的阵列应该是...它是空的。 未在 FRAM2中写入任何数据、也未报告任何错误消息。 研究了 控制 MPU 的部分后、我保留了由 Code Composer 创建的默认设置。 我决定禁用 MPU、程序又开始工作。 我宁愿让 MPU 处于活动状态、但似乎这样做的系统会自动创建错误的设置... 我不确定如何自己配置它。
最后,这是我的文章的真正原因:我取代.ti.persistent 在 FRAM2与.ti.noinit . 现在代码不再起作用...我收到了一些错误消息与单词"trampoline",我不熟悉这个概念. 我认为.persistent 和.noinit 的唯一区别与初始化有关。 我想还有更多的东西吗? 我们将感谢您在这方面提供任何帮助。

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

    您好,Carlos Yanzig

    请根据 MSP430FR58xx、MSP430FR59xx 和 MSP430FR6xx 系列用户指南(修订版 P)查看 MPU 设置 和 CCS 设置

    谢谢

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

    我不确定你的目标是什么、但:

    1) TI.noinit 通常被放置在 RAM 中(因为我不知道的原因)。 若要将其放入 FRAM 中、您应更改链接器.cmd 以在 READ_WRITE_MEMORY 组中移动 TI.noinit 规范。 这允许链接器/运行时找出 MPU 设置。 类似于以下内容:

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

    2)为安排 NOINIT,需要将"Project->Properties->Debug->MSP430 Flash Settings->Erase Options"更改为"Erase and download necessary segments",以避免(批量)擦除 NOINIT 数据。

    3)每次下载新代码时会重新初始化持久性数据,但 NOINIT 不会重新初始化。 你应该考虑如何处理第一次(更不用说腐败)为 NOINIT。  校验和/CRC 可能很有用。

    4)我在(1)-(2)中描述的方法会让你走,但该段很容易在程序增长时被移动。 如果这是个问题、你可能需要它有一个单独的存储器段、这意味着需要使用链接器.cmd 和 MPU。 (我不想让这个声音比它更难、但它不是微不足道的。) 如果您的 NOINIT 段非常大、您可能也需要这样做。

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

    感谢您的回复。 首先、我将.TI.persistent 段移至其自己的段。 此部分占用几乎所有 FRAM2。 如前所述、当我禁用 MPU 时、这可以正常工作。 更明确

    部分
    {
    .TI.persistent:{}> FRAM2 /*的#pragma PERSISTENT。 我在此处添加了未分组的该部分*/  
    //.TI.noinit :{}> FRAM2 /* for #pragma noinit。 注释掉了固件正常工作的情况*/

    组(RW_IPE)
    {
    组(READ_WRITE_MEMORY)
    {
    //.TI.persistent:{}/*对于#pragma persistent 我已从组中删除此条目*/

    根据我在手册中所读的内容、我的理解是没有必要提及读写、因为它默认为读写。  

    当我尝试用 noinit 替换 persistent 时出现问题...也就是说:

    //.TI.persistent:{}> FRAM2 /* for #pragma PERSISTENT。 我添加了持久部分的注释*/  
    .TI.noinit :{}> FRAM2 /* for #pragma persistent. 现在我已经创建了一个由编译器独自保存的数据段*/

    组(RW_IPE)
    {
    组(READ_WRITE_MEMORY)
    {
    //.TI.persistent:{}/*对于#pragma persistent 我从此处删除了此条目*/

     我没有做的是第2点)...我将尝试下一个,假设编译是成功的。 固件中的函数允许我处理阵列中发生的情况。 我已经处理了您刚才提到的问题。  

    该部分足够大、无法移动。 数组是连续的内存块、在这种情况下无法移动。

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

    如果您的目标是将 NOINIT 变量放在高 FRAM (FRAM2)的开头、那么正如晓东所说、您将需要 MPU 编辑器(Build Settings->General->MPU[Tab])。 此外(我的算术运算)、您需要确保所有代码均适合低 FRAM。

    MPU 只为您提供3个区域。 最低的值(FR6928上为0x4400)通常应该是 RW、因为正如您所见、编译器/链接器可能期望那样。 (如果映射显示 READ_WRITE_MEMORY 为空、也可以使该 RX 生效。) 第二个区域--编码和只读数据--通过中断向量(0xFFFF)延伸,应该是 RX。 第三个区域是您的数据(0x10000)、它应该是 RW。

    在大型模型中、.text 优先放置在 FRAM2中、因此您应在链接器.cmd 的该行中删除 FRAM2。 为安全起见、应从其他任何位置删除 FRAM2、尽管其他位置不太可能发生溢出。

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

    根据上一次答复和上一次尝试中的建议,我做了以下工作:

    我解组 persistent 并在链接器中初始化、如下所示。 我的数组几乎占用了所有的 FRAM2 (我也在这段内存中有一个无符号变量...一种索引(uint16_t )。 我写道:

    .TI.persistent:{}> 0x10000

    以确保数组将从0x10000开始。 BTW...阵列的长度为49000字节。

    在 MPU 设置中、我执行了以下操作:

    我启用了 MPU 并选择了手动调整的选项。 我只对已设置的选项进行了一项更改:

    在段3中、我指定了 R 和 W 选项、而不是 X 选项、并且我在0x10000处启动该段。 一切都正常。 我还进行了检查以将段3的大小增加到0xE000。 它没有区别。

    我还做了:

    按照建议将"Erase Options"更改为"Erase and download necessary segments"。 其他设置已经正确。

    当我尝试相同的方法、将 PERSISTENT 替换为 NOINIT 时、我收到一个链接器错误、提示数据不适合。  导致该错误的原因是我忘记删除这2个变量的初始化。

    在我的代码中、我对这2个变量使用了#pragma PERSISTENT 指令、并将它们初始化为0。

    我在前面提到过、这不是我想要的。 我的目标 是使阵列和变量在 FRAM2中保持不受干扰。

    接下来、我在链接器中添加了.TI.persistent 并将其替换为

    .TI.noinit :{}> 0x10000

    在我的代码中,对于前面提到的2个变量,我用#pragma NOINIT 替换了#pragma PERSISTENT。这次我删除了变量的初始化。。。工具抱怨了这个问题。 这对我来说很好。 我的程序负责该初始化。

    工具运行正常,没有投诉或警告和 FRAM2初始化为0xFFFF ... 如果数组中写入了一些内容、它将被擦除。

    那么现在我有2个选项:我可以应用#pragma PERSISTENT 并让所有内容都由工具初始化,或者我可以应用#pragma NOINIT 并将所有内容擦除至0xFFFF ...

    BTW、根据 CCS、程序占用 FRAM 的大约30%、且在 RAM 中分配的字节数少于300。

    此致

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

    我在确定你最终得到了什么方面遇到了一些困难。

    当你前面问的时候,我用我建议的方法在一个 FR5994 (我想足够接近)上模拟了你要做什么(我认为),我得到了我期望的结果--重新加载代码没有擦除 NOINIT 变量,它们是可写的。 我们必须做一些不同的事情。

    1)您的(大型)数组没有初始化器,并且使用#pragma NOINIT ()进行关联,这是正确的吗?

    2) 2)您是否从链接器.cmd 中的.text 段中删除了"FRAM2"引用?

    3)在.map 文件中,除了阵列之外,还有什么其他的显示在0x10000以上?

    4) 4)您的数组被擦除这一事实表明、链接器确定包含您的 TI.noinit 段的段是"必需的"、即它是可加载的。 您可以尝试类似以下内容的操作:

    .TI.noinit :类型=无负载{}>FRAM2

    明确要求的提示。 我只是尝试了它,它成功了,虽然这不能证明太多,因为我的程序是成功没有它。

    5) 5)您可以在 linker.cmd 中发布数组和 TI.noinit 行的声明、每个声明都有几行上下文吗? 可能有些东西我们都缺失了。

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

    当你之前问,我建模了你试图做什么(我认为),使用我建议的方法,在一个 FR5994上(我认为足够接近),我得到了我预期的结果...

    正如我之前提到的、我将使用 MSPFR6928。 如果他们是相似的,我听你的话。 我有一个基于 FR5994的 Launchpad。 如果您想分享您正在做的事情、我可以
    尝试重现它。

    重新加载的代码没有擦除 NOINIT 变量,它们是可写的。 我们必须做一些不同的事情。

    我们可能会遇到问题、除非为 FR5994生成的链接器命令文件不同或其他情况。

    1)您的(大型)数组没有初始化器,并且使用#pragma NOINIT ()进行关联,这是正确的吗?
    我不知道你是什么意思初始化器...我的代码做以下:

    #pragma NOINIT (Logger_Wr_Index)
    uint16_t Logger_Wr_Index;

    #pragma NOINIT (Cycle_Logger)
    Acq_Cycle Cycle_Logger SMBUS[MAX_CYCLES];//这是结构... 49000字节大小。 它位于0x10000……

    Logger_Wr_Index 放置在结构之后、即使我先声明它也是如此。

    为了修改阵列中的内容、用户必须通过串行端口发送命令。

    2) 2)您是否从链接器.cmd 中的.text 段中删除了"FRAM2"引用?
    以下是我所做的操作(从链接器命令文件复制):

    #ifndef __large_data_model__
    .text:{}> FRAM /*代码*/
    #else
    .text :{}>> FRAM | FRAM2 /*代码*/
    //.text :{}>> FRAM2 | FRAM /*代码*/
    #endif

    我不知道这是否会对问题产生任何影响。 ...我可以删除它。

    3)在.map 文件中,除了阵列之外,还有什么其他的显示在0x10000以上?
    我想我刚刚回答了这个问题、但映射文件的这个部分如下:

    0000fffe _reset_vector
    00010000 Cycle_Logger
    0001bf68 Logger_Wr_Index
    FFFFFFFF __TI_pprof_out_hndl
    FFFFFFFF __TI_PROF_DATA_SIZE
    FFFFFFFF __TI_PROF_DATA_START
    FFFFFFFF _c_args_


    4) 4)您的数组被擦除这一事实表明、链接器确定包含您的 TI.noinit 段的段是"必需的"、即它是可加载的。 您可以尝试类似以下内容的操作:
    .TI.noinit :类型=无负载{}>FRAM2


    我可以尝试、如果工具允许、我也可以:
    .TI.noinit :类型=无负载{}>0x10000

    5) 5)您可以在 linker.cmd 中发布数组和 TI.noinit 行的声明、每个声明都有几行上下文吗? 可能有些东西我们都缺失了。

    内存
    {
    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
    FRAM : origin = 0x4400, length = 0xBB80 //在保存中断矢量、复位等的区域之前完成。
    FRAM2:origin = 0x10000、length = 0xBFFE   
    JTAGSIGNATURE:origin = 0xFF80、length = 0x0004、fill = 0xFFFF
    BSLSIGNATURE:origin = 0xFF84、length = 0x0004、fill = 0xFFFF
    IPESIGNATURE:origin = 0xFF88、length = 0x0008、fill = 0xFFFF


    部分
    {
    .TI.noinit :{}> 0x10000 /* for #pragma noinit */
    组(RW_IPE)
    {
    组(READ_WRITE_MEMORY)
    {
    .bss :{}/*全局和静态变量*/
    .data :{}/*全局和静态变量*/
    //.TI.noinit :{}/* for #pragma noinit */
    //.TI.persistent:{}/* for #pragma persistent */
    .cio:{}/* C I/O 缓冲器*/
    .sysmem:{}/*动态内存分配区*/
    }PALIGN (0x0400)、RUN_START (FRAM_RW_START)

    组(IPENCAPSULATED_MEMORY)
    {
    .ipestruct:{}/* IPE 数据结构*/
    .ipe :{}/* ipe */
    .ipe_const:{}/* IPE 受保护的常量*/
    .ipe:_isr:{}/* IPE ISR */
    .ipe_vars:type = NOINIT{}/* ipe 变量*/
    }PALIGN (0x0400)、RUN_START (FRAM_IPE_START) RUN_END (FRAM_IPE_END) RUN_END (FRAM_RX_START)
    }> 0x4400

    为了完整起见...
    在 MPU 中、我将手动设置、但只进行以下更改:
    段3 R 和 W (无 X)从0x10000开始并完成0x1BFFF
    (我还在一个测试中将0x10000更改为0xE000……没有区别。

    我尝试了以下建议:

    .TI.noinit :类型=无负载{}> FRAM2

    它给了我一个编译错误、所以我在编译时  

      .TI.noinit : load = 0x10000 type =无 load{}  

    我没有在这里得到任何错误,,,但它也没有帮助...  

    我还从.txt 中删除了 FRAM2 ...就像这样:

    #ifndef __large_data_model__
    .text:{}> FRAM /*代码*/
    #else
    .text:{}> FRAM
    //.text :{}>> FRAM | FRAM2 /*代码*/
    //.text :{}>> FRAM2 | FRAM /*代码*/
    #endif

    没有任何帮助。

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

    我还没有成功地创造你的症状。  

    您在"type=NoLoad"时遇到了什么编译错误?  我直接从.cmd 文件粘贴该行、因此我感到有点惊讶的是链接器没有接受它。

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

    我研究了一个我导入到 CCS 中的用于 FR5994的小项目。 该项目是有关如何使用 ADC 的示例。 我查看了该项目的链接器命令。  示例中没有"type=NoLoad"。 你能给我一个剪切和粘贴的链接命令,显示这个表达式在你的链接命令中的位置和如何使用...事实上..如果你可以给我发送你的

    部分

    {

    ……

    看起来效果会更好。 至少包含 GROUP 指令的第一个部分。

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

    我的项目不需要 type=NoLoad --不管有没有它都可以成功。 [我引入它是为了明确通常隐式发生的事情。] 但事实上,你的链接者拒绝它,而我接受它似乎(偶然)提示,有一些东西在外面发生了我们所讨论的。 (版本冲突? 与一些古墓工程设置或.cmd 文件中的其他东西(未显示)进行交互?) 您看到了什么错误消息?

    要证明您的症状、需要使用真实的器件、但我没有 FR6928。 因此、我选择了同一(FR5/6)系列中的一款具有相似存储器布局(主要是一个较大的 FRAM2)的器件(c)、我实际上拥有该器件。 这种症状(几乎)肯定是编译/调试操作、而不是 MCU 本身。

    此症状的主要故障是(仍然)闪存(擦除)设置。 也许值得再看一下,确保没有任何变化,没有告诉你。

    这里我没有我的材料、但我希望我能在今晚上传我正在处理的内容(.c +.cmd)。

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

    我必须为我以前所作的发言道歉。 今天、我在链接器中尝试了相同行的代码:

    .TI.noinit :类型=无负载{}>FRAM2

    以及项目的编译没有任何问题。 这并不意味着它正常工作。 我想,我不能再这样做了,但我不能这样做。"  

    现在...这是发生了什么。 当我尝试运行由这个连接器命令文件生成的代码时、当代码在部件中被编辑时、FRAM2的区域被写入0xFFFF (或被擦除为0xFFFF)。 但我无法在 FRAM2中写入数据、也没有出现任何错误。 或者、我应该说代码正在运行、看起来好像什么都不出错(只是看到存储器(FRAM2)没有更改而已。 就像配置 MPU 时没有 W 波浪号...而不正确。

    我用2个版本的 CCS、6.2 (旧机器)和12 (新机器)编译了软件。 这两个软件似乎行为相同,一旦我更改一些设置,使它们都匹配(大模型...)

    我想知道是否还有其他一些我缺失的设置在创建这个。 我读取了软件使用 GROUP 指令来正确配置 MPU。 是否有可能将.TI.noinit 置于 GROUP 指令之外会得到用于设置 MPU 寄存器等内容的软件的错误配置?

      

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

    如果让链接器处理 MPU 设置(MPU 选项卡中的复选框)、FRAM 的低端(GROUP (RW_IPE)将设置为 RW、其他所有器件(尤其是 FRAM2)都将受写保护。 这就是为什么我说如果你想把你的数据放在 FRAM2中、你需要使用 MPU 编辑器。

    MPU 设置之一是"在违反访问权限时使 PUC 生效";如果未选中此复选框、将安静地忽略写保护 FRAM 的写入。

    实际使用的 MPU 设置显示在.map 文件中、其中包含名为 MCU_ctl0_value、MPU_SAM_VALUE、MPU_SEGMENT_Border1/2 (et al.)的符号。 您可以使用 FR5x 用户指南(SLAU367P)第9.7节解释这些内容。

    我再也没有 CCS v6的副本。 我是使用 CCS v12.6执行此操作。 旧版本的行为可能存在差异。

    ----------------

    我正在使用的项目具有一个

    1) 1)处理器选项:代码/数据=大型、near =无

    2)调试->闪存(擦除)设置"仅擦除和下载必要的段"

    3) MPU 边界{0x4400、0x10000}与相应的段访问{RX、RX、RW}。 PUC 被禁用。  

    这是我一直在使用的.c 文件(没有太多内容)。 第一次调试/下载时、我使用调试器在 main 正在改变的周围写一些字、以便在 FRAM 被擦除时更明显。 运行到 LPM0、然后再次退出并进行调试/下载。

    #include <msp430.h> 
    
    #pragma NOINIT(ni_array)
    unsigned ni_array[49000U/2];
    #pragma NOINIT(ni_array_small)
    unsigned ni_array_small[10U/2];
    
    /**
     * main.c
     */
    int main(void)
    {
    	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
    	PM5CTL0 &= ~LOCKLPM5;
    	ni_array[2]++;
    	ni_array_small[2]++;
    	while (1)
    	{
    	    LPM0;
    	}
    	/*NOTREACHED*/
    	return 0;
    }
    

    这是我要使用的(整个).cmd 文件。 我从 CCS 提供的默认.cmd 开始;你将能够识别(很少)的差异。

    /******************************************************************************
    *
    * Copyright (C) 2012 - 2021 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            */
    /*                                                                            */
    /*----------------------------------------------------------------------------*/
    /* 1.213 */
    /*----------------------------------------------------------------------------*/
    
    /****************************************************************************/
    /* 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 = 0x33FF8 /* Boundaries changed to fix CPU47 */
        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
    {
                .TI.noinit : {} >0x10000 /* type = NOLOAD{} > FRAM2                  /* For #pragma noinit                */
        GROUP(RW_IPE)
        {
            GROUP(READ_WRITE_MEMORY)
            {
                .TI.persistent : {}              /* For #pragma persistent            */
     			//.TI.noinit : {}
                 .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              */
        .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
    
    
    

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

    好吧...我想我已经设法让事情工作...我做了几件事情、所以我不知道哪一件事做了工作。

    我在此论坛中发现了一个名为"MSP430FR6989、无法将 FRAM2与#pragma PERSISTENT 配合使用"的帖子。  这里提出的问题与我的问题没有太大的不同,我发现凯蒂码头一个非常详细的解释,如何解决一个大对象在记忆的问题。
    如前所述、默认情况下、工具(MPU、链接器等)尝试创建特定的模型。 该模型将数据保存在存储器(RW)的较低部分、在中间保存一个常量(R)区域、在顶部保存一个代码(RX)区域。
    在本例中、她将该模型倒置、但仅保留2个分段。 代码位于下部区域(RX)、其余部分作为数据(RW)进入上部区域。 她创建/将 FRAM 分成2个部分、并仅保留 FRAM2。
    我做了同样的事情、但对尺寸做了一点修改。 我的代码需要更多空间。 然后她修改连接器命令文件以设置 MPU。 我采取了同样的方法。 她还保留了 CCS 属性中的 MPU 配置:"让编译器处理内存分区、相关访问权限和链接器输出段的放置"。 这种设置让我惊讶...我自己会选择手动选项...因为这就是我在做的。 但我还是跟着她走了。
    我还使用了较新版本的 CCS ...我认为它是9. 我有一个疑问、即.ti.noinit 无法在6.2条件下正常工作。
    我在链接器命令文件中将.ti.persistent 替换为.ti.noinit。
    在她的帖子中,她谈到了如何使用内在函数来解决 FRAM2的元素...我没有这么做。 我只是使用了常规 C 来复制结构对象。 这一直对我有用...这可能是一个问题,当她写她的方法。

    此帖子非常详细、但并不意味着(我认为)是应用手册、我不完全理解这个问题:

    引用链接器希望创建的模型、该模型分为3组:READ_WRITE_MEMORY、READ_EXECUTE 等、具有这些符号 FRAM_Rx_START fRAM_r_start FRAM_RW_START 。 我无法理解符号和组之间的关联。 如果您有这方面的信息,我将不胜感激。 我知道他们代表群体开始的地址,但他们是否也代表和秩序? 在这方面,我找不到太多的资料。

    此致

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

    FRAM_Rx_START 用于自动生成 MPU 值(在该链接器.cmd 文件中、起始行为337)。  我不知道谁(如果有人)使用 FRAM_RW_START。 (我看不到任何名为 fram_r_start 的命令。) MPU 和 IPE 库似乎没有使用它们。

    使用 MPU 编辑器时、计算的值会作为-D 符号提供给链接器、链接器将这些值转换为外部值。 [参考"Build Settings->Build->Compiler->Predefined Symbols"。]

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

    这是一个拼写错误...名称是 FRAM_RO_START ...这是从名为 MSP430技术讲座的 FRAM 培训中捕获的...大约用14分钟时间看完视频。

    www.ti.com/.../msp430-workshop.html

    看起来您在 GUI 中输入的值可以通过我在前一篇文章中提到的这些值到达链接器。

    此致