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.

[参考译文] CCS/MSP430F5418A:从闪存的最后8个字节执行指令提取时、发生空存储器中断

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/733578/ccs-msp430f5418a-vacant-memory-interrupt-occurs-when-executing-instruction-fetch-from-last-8-bytes-of-flash

器件型号:MSP430F5418A
主题中讨论的其他器件:MSP430F5437AMSP430WARE

工具/软件:Code Composer Studio

您好!

我最近将 CCS 从7.x 升级到8.1.0、并首次启用空存储器访问中断。 这样做之后、每次 执行从地址 0x25BFF 取指令的函数时、我都会遇到非常常规和奇怪的 SYSNMI_Vector 中断。

在每次编译时尝试调试问题、它会随着放置在末尾位置的函数的更改而不断移动。 得出这一结论需要许多红色的鲱鱼和死鱼路径。

从.cmd 文件执行的命令现在读取;

内存
{
SFR :origin = 0x0000、length = 0x0010
外设_8位 :origin = 0x0010,length = 0x00F0
外设_16BIT :origin = 0x0100,length = 0x0100

BSL0 :origin = 0x1000、length = 0x0200
BSL1 :origin = 0x1200,length = 0x0200
BSL2. :origin = 0x1400、length = 0x0200
BSL3 :origin = 0x1600,length = 0x01F0
/*这将完全固定 BSL,而不是让其启动。
*在 BSL3区域的下一个擦除周期时、将设置此值
将*更改为0xFFFF、这是一个可接受的值。 它必须为0xFFFF
或0x0000。 如果情况并非如此、则器件变为
*不可操作。 这将是坏的:)
*
*侧注;这还确保 BSL 永远不会识别
*已输入。
*
BSLZ :origin = 0x17F0、length = 0x0010、fill = 0x0000

信息系统 :origin = 0x1800,length = 0x0080
信息系统 :origin = 0x1880、length = 0x0080
信息 :origin = 0x1900,length = 0x0080
INFOA :origin = 0x1980,length = 0x0080
//RAMZ:origin = 0x1C00,length = 0x0100,fill=0xA0A0
RAM :origin = 0x1C00,length = 0x4000
闪存 :origin = 0x5C00,length = 0xA380,fill = 0x3FFF
FLASH2 :origin = 0x10000、length = 0x15B80、fill = 0x3FFF
//将这些字节保留为空。 在上一节中提出了 VMAI 错误
FLASH3 :origin = 0x25B80,length = 0x80,fill = 0x3FFF
…

部分
{
.TI.noinit:{}>RAM /*用于#pragma noinit *
.bss :{}> RAM /*全局和静态变量 *
.data :{}> RAM /*全局和静态变量 *
.cio :{}> RAM /* C I/O 缓冲器 *
dbg :{}> RAM
sysmem :{}> RAM /*动态内存分配区域*/
/******** 内存孔 /
堆栈 :{}> RAM (高) /*软件系统堆栈 //

#ifndef __large_code_model__
.text :{}>闪存 /*代码 */
#else
.text :{}>> FLASH2 | FLASH /*代码 */
#endif
.text:_ISR:{}> FLASH /* ISR 代码空间 *
.cinit :{}>闪存 /*初始化表 */
#ifndef __large_data_model__
.const :{}>闪存 /*常量数据 */
#else
.const :{}>> FLASH | FLASH2 /*常量数据 */
#endif

.pinit :{}>闪存 /* C++构造函数表 *
二进制文件 :{}>闪存 /*引导时初始化表*/
init_array:{}> FLASH /* C++构造函数表 *
.mspabi.exidx:{}>闪存 /* C++构造函数表 *
.mspabi.extab:{}> FLASH /* C++构造函数表 */
#ifdef __TI_Compiler_version__
#if __TI_Compiler_version__>=15009000
#ifndef __large_code_model__
.TI.ramfunc:{} load=flash,run=RAM,table (BINIT)
其他
.TI.ramfunc:{} load=flash | FLASH2、run=RAM、table (BINIT)
endif
#endif #endif #endif


.bsl0.noinit :{}> BSL0,type=NoLoad
.bsl1.noinit :{}>BSL1, type=NoLoad
.bsl2.noinit :{}>BSL2, type=NoLoad
.bsl3.noinit :{}>BSL3, type=NoLoad

/* Nerf BSLZ 区域保持 BSL 被禁用和 JTAG 访问
*支持开发/发布
*
bslz :{}> BSLZ、fill=0x0000

信息 A :{}>INFOA /* MSP430 INFO 闪存段*/
信息 B :{}>INFOB
.infoC :{}>INFOC
信息 D :{}>INFOD 

我将使用0x3FFF 填充所有未使用的闪存、以确保在执行繁重的任务时实现正确的代码跳转。 放置在最后几个字节中的函数是

proof_outc 位于地址范围的末尾;

0x025BE2 _outc
0x025BE2 9D9D 0002 0004 2C07 4D2E 0ECF 531F
0x025BF0 4F8D 0000 4CCE 0000
0x025BF8 $C$L6
0x025BF8 539D 0004 4C4C 0110 

使用链接器指令;

内存
{...

FLASH3 :origin = 0x25B80,length = 0x80,fill = 0x3FFF...

} 
部分{... VMI.endFlash:{--library=rts430x_lc_sd_eabi.lib (.text:_outc)}> FLASH3 (HIGH)...}


在程序地址0x25BEE 之后设置断点、以便能够在运行时单步执行代码。

在启动时执行此代码;

/*启用闪存和存储器访问中断
*
/ SFR_clearInterrupt (SFR_空置 的存储器访问中断|
SFR_FLASH_CONTROLLER_ACCESS_ACCESS_violation_interrupt);
SFR_enableInterrupt (SFR_空置 的存储器访问中断|
SFR_FLASH_CONTROLLER_ACCESS_CONTROLLER_ACCESS_CONTRAL_INTERRUVE_INTERRUPT); 


预置和后置中断内核寄存器


如果我在 MSP430F5437A 上运行相同的十六进制文件、我不会获得相同的中断。 我假设这是因为下一个0x25C00闪存地址有效、并且在不检查闪存边界限制的情况下进行某种预取操作。

如果在闪存的最后0x08字节中执行任何取指令操作、则发生 VMA 中断。 (我已经从闪存末尾测试了0x10到0x01缓冲区)

这将失败;少于8个字节

//将这些字节保留为空。 在上一节中提出了 VMAI 错误
FLASH3:origin = 0x25B00,length = 0xFA,fill = 0x3FFF
FLASH4:origin = 0x25BFA,length = 0x06,fill = 0x3FFF

这是正常的;等于或大于8字节

//将这些字节保留为空。 在上一节中提出了 VMAI 错误
FLASH3:origin = 0x25B00,length = 0xf8,fill = 0x3FFF
FLASH4:origin = 0x25BF8,length = 0x08,fill = 0x3FFF

e2e.ti.com/.../lnk_5F00_msp430f5418a.7z

MSP430F5418a 项目的有效链接器文件

这是我所有构建选项和包含项的链接器行。

"c:/ti/ccsv8/tools/compiler/ti-cgt-msp430_18.1.2.LTS/bin/cl430















/ti/ccsv8/ccs_base/msp430/include

/ti/ccsv8/tools/compiler/ti-cgt-msp430_18.1.2.LTS/include -vmspx --data_model=small -o0 --opt_for_speed=1 --align_for_power --use_hw_mpy=F5 --define=_MSP430F5418A_--c99 --float_operations_allow=all --use_printf_support=full --gen_mpy=fb --define=atterms-ins-iclif_ipot-at_ine-reguls=-at_ips=-ines=-ina-cs=-ine-ment-cs=-in-in-in-at_ipot_in-in-in-in-in-at_in-at_in-in-in-at_ins-ine-reguli=-ins-ins-over-ment-link=cand-ines=cat_ins-ins-ins-intrad_ines=-ines=-ins-ins-inattrad_ines=-ines=cat_ins-ins-ins-ins-ins-ins-out-ines=-at_at

/ti/msp/MSP430Ware_3_80_04_05/iqmathlib/libraries/CCS/MPY32/5xx_6xx /ti/ccsv8/ccs_base/msp430/lib/5xx_6xx_FRxx /ti/ccsv8/tools/compiler/ti-cgt-msp430_18.1.2.LTS/lib



###"../lnk_msp430f5418a.cmd"-llibc.a -llibmath.a -lIQmathLib.a -lIQmathLib_ccs_MPY32_5xx_6xx_CPUx_large_code_small_data.lib 




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

    这在这里看起来很奇怪。 从外观来看、您似乎正在使用自定义链接器文件。 您是否能够在默认链接器文件上重现错误?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    我最初有一个自定义链接器文件、然后从 msp430ware 更新到最新的1.205、同时尝试确定我出错的位置。 因此、是的、我在添加所有其他关断之前检测到了默认链接器文件的问题。

    附加的是使用 driverlib 源代码构建的清理工程、所有中断都使用干净的 CMD 文件和校正命令文件进行了"编码"。 校样文件仅在闪存的末尾查找_outc 函数、以显示芯片故障。

    使用连接到 XT1的20MHz 晶体构建并运行调试(为开发板提交或修改此内容。 遗憾的是、我没有 MSP430 Launchpad 板可与之配合使用)

    然后

    构建并运行"Debug_proof"并在 main.c 的第192行放置一个断点。或者在调试器崩溃后暂停:)

    e2e.ti.com/.../VMA_5F00_Erattum_5F00_Example.7z

    TI-format txt 文件也位于构建目录中。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我还一直在研究 eratum 文档(www.ti.com/.../slaz280z.pdf) 、很奇怪、主要故障是 identifid、默认情况下未在 CMD 文件中实现。

    FLASH35闪存模块
    类别功能
    函数闪存读取错误可能会导致无效的存储器访问
    说明
    闪存存储器访问始终为32位宽并且在32位边界上执行。 A
    访问闪存时的读取错误可能会损坏32位中的最高有效位(MSB)
    编程为逻辑0时进行访问。
    当受影响的闪存处于空闲状态时、可能会在第一次闪存访问时发生读取干扰
    以下列出的任何事件:
    -复位时在 RST 输入引脚上发出
    -访问中断矢量地址时从低功耗模式唤醒
    位于地址<0x8000
    -当将程序执行从不受影响的闪存区移动到受影响的闪存区时
    -从 RAM 执行后访问受影响的闪存时
    权变措施
    详细信息请参见《MSP430F54xxA 的闪存读取误差和易感性》(文献编号:SLAA470)
    背景信息和可能的解决方法。

    应在0x8000和0xFF80之间定义一个所有 ISR 函数都必须驻留的段、然后其他初始化块可以使用该区域的其余部分。 因此、再次拆分闪存部分、以确保所有 ISR 地址指针都是0x8###、与勘误表状态类似。

    您对此有何看法?

    我个人对这一系列芯片没有任何随机问题。 很难跟踪、模糊的问题、每次编译都会发生变化...
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Lucas、

    我认为 FLASH35与您看到的行为无关、它仅适用于 RevB 到 D

    仅当您在最后一个地址中添加了以下代码时、才会显示该代码是否正确?

    0x025BE2 _outc

    0x025BE2 9D9D 0002 0004 2C07 4D2E 0ECF 531F

    0x025BF0 4F8D 0000 4CCE 0000

    0x025BF8 $C$L6

    0x025BF8 539D 0004 4C4C 0110

    您能不能向我发送反汇编窗口、以便我可以看到在那里执行了什么代码。
    根据流水线 CPU、如果您在最后一个地址上执行、VMA 标志会根据代码被触发。

    例如、如果您在0x25BFE 上使用 JMP &(机器代码0x3FFF)、它还应触发 VMA、因为 CPU 将读取不存在的下一个地址。 这是很正常的、所以最好不要像您指出的那样在最后一个字上放置代码。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这是"Disassembly"窗口输出

    _outc ():
    025be2:9D9D 0002 0004 CMP.W 0x0002 (R13)、0x0004 (R13)
    025be8:2C07 JHS (0x5bf8)
    102. *holder ->out_end++= c;
    025bea:4D2E MOV.W @R13、R14
    025bec:0ECF MOVA R14、R15
    025bee:531F Inc. W R15
    025bf0:4F8D 0000 MOV.W R15、0x0000 (R13)
    025bf4:4CCE 0000 MOV.B R12、0x0000 (R14)
    104. 持有者->written ++;
    $C$L6:
    025bf8:539D 0004 事件 W 0x0004 (R13)
    106 返回 c;
    025bfc:4C4C MOV.B R12、R12
    025bfe:0110 返回 

    我尝试了我的主代码、将此例程放置在顶部、如上所示、并从最后一个闪存地址填充多达8个字节、以1字节为增量。 一旦闪存阵列末尾有8个字节的填充、问题就会停止。 我还具有 fill=0x3FFFF、以便下一个地址位置具有一些 wiki 中建议的无效内存跳转位置。

    您是否需要任何其他输出?

    我对主线 CMD 文件进行了另一项更改、其中包括强制将任何 ISR 例程链接到0x8000-0xFF80地址范围、如 FLASH35所示

    闪存:origin = 0x5C00,length = 0x2400,fill = 0x3FFF //警告:受影响的是 FLASH35
    FLASH_ISR:origin = 0x8000,length = 0x7F80,fill = 0x3FFF //警告:受影响的是 FLASH35 

    这确实使我的分区看起来很脏。 也许我应该使用一个小组?

    #ifndef __large_code_model__
    .text :{}> FLASH | FLASH_ISR /*代码 */
    #else
    .text :{}>> FLASH2 | FLASH | FLASH_ISR /*代码 */
    #endif
    /*将所有 ISR 代码作为中断跳转表保留在较低地址范围内*/
    出于寻址原因、/*要求中断路由低于64KB *
    .cinit :{}> FLASH | FLASH_ISR /*初始化表 */
    #ifndef __large_data_model__
    .const :{}> FLASH | FLASH_ISR /*常量数据 */
    #else
    .const :{}>> FLASH | FLASH_ISR | FLASH2 /*常量数据 */
    #endif
    
    .pinit :{}> FLASH | FLASH_ISR /* C++构造函数表 *
    二进制文件 :{}> FLASH | FLASH_ISR /*启动时初始化表*/
    init_array:{}> FLASH | FLASH_ISR /* C++构造函数表 *
    .mspabi.exidx:{}> FLASH | FLASH_ISR /* C++构造函数表 *
    .mspabi.extab:{}> FLASH | FLASH_ISR /* C++构造函数表 * 

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

    我所采用的分辨率就是这样

    lnk_msp430f5418a.cmd

    //将大小减小8个字节,以防止放置在闪存组
    FLASH2的末尾 :origin = 0x10000、length = 0x15BF8、fill = 0x3FFF
    //将这些字节留空。 在最后一节
    FLASH3 (R)中提出了 VMAI 错误 :origin = 0x25BF8,length = 0x08,fill = 0x3FFF // fatal: affected by erratum unknown 

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

    关于 FLASH35:如果您已经影响了裸片修订版本 B 至 D、您只需要执行此操作、我无法想象、因为这是非常旧的材料、通常您只能得到 F 至 H、可能是 E

    关于其他现象、您可以在 RETA 之后放置一个"nop 指令"来查看这是否有用。 然后将 RETA 放置在0x25BFC。同时将它移动另一个32位到0x25BF8、并在之后放置3次 nops。

    最后8个字节显示此行为的位分段是什么? 通常、闪存以32位双字读取。 因此、我可以理解最后32位中的 RETA 是否会影响它、但0x25BF8处的 nop 位于0x25BFA 处应该起作用。
    编译器处理了这方面的一些错误。 您刚才提到、在下载最新的 CCS 正确之后、您看到了这一点。 您能告诉我您现在使用的是哪种编译器、您以前使用过哪种编译器吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    卢卡斯

    进行了一些额外的设计检查。 重点是使用流水线型 CPU、这将在 REFTA 被确认时继续增加 MAB、这就是为什么您需要为存储器的边界留出一定的空间以确保不触发 VMA 的原因。 至少对于代码放置、不应使用存储器的这一部分。 对于数据、这不是问题。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    卢卡斯

    我使用一个非常简单的汇编代码执行了一个基准测试、我无法100%确认您的结果。 我使用了较大的存储器旋转 F5438A RevH、并在地址0x45BFC 处放置了"Reta"指令、如下所示。 在这种情况下会触发 VMA NMI、因为 CPU 会由于流水线架构而自动递增。

    但是、我删除了3 个 nops 并将"Reta"置于0x45BF6上 VMA NMI 消失在位置0x45BF8、0x45BFA、0x45BFC 上、它仍然显示

    在这里、Reta 之后的 nop 也不起作用。 我将更详细地检查设计、并将向您返回我们如何处理此问题。 但如前所述、这是由流水线 CPU 架构造成的。

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

    好的,知道你也可以在更大的芯片上复制它,我不会疯了:)

    我确信、对于指令、不会错过8个字节的闪存。 我将其保留在这里、因为我已经调整了 CMD 文件以排除该块、因此我将再次运行。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    好的、我必须仔细阅读 FLASH35的工作表(偏斜)。 当时我疯了。

    我使用过18.1.3和18.1.2。

    我不记得在之前的版本中看到过它、但话虽如此、我之前从未启用中断、因为我在电源电路中遇到 SVMH/L 问题、并且无数次代码执行未解释为无限执行、而在版本18.1.2/3之前、我从未见过这种情况

    我的器件 FWiw 中有 MSP430F5418A 修订版 E。 在以后的器件中、我有版本 H。如果您愿意、我可以从正在运行的器件转储 TLV 表。 它应该是最新的修订版、因为它是今年用新的库存制造的。

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

    您好 Lucas、

    明白了。 仿真工作仍在进行中、只要我有一些新东西、我会告诉您、但预计在本周结束时会获得结果。

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

    卢卡斯

    我现在模拟了这个行为、并且必须根据仿真来纠正我的问题。只有当"Reta"指令位于地址0x45BFC、0x45BFE 时、这才是关键。 最后、它意味着只有最后2个字不应使用指令代码和最后4个字填充。

    我还在芯片上确认了这一点!  我之前在地址0x45BF8和0x45BFA 处也看到过这一点的原因是我在 Reta 上有一个断点、这将导致额外的闪存访问。 但在自由运行模式下或未连接调试器时、"Reta"不应位于0x45BFC、0x45BFE 上。 请确认。

    流水线型 CPU 架构及其预取机制之前提到的根本原因。

    在上面、您必须知道"Reta"是一个仿真 Mova @SP+、PC、它需要5个时钟。

    查看指令周期、可以看到其他指令占用时钟更多、例如 MOVA &EDE、PC。 为此、该指令不应位于地址0x45BFA 上

    最后说过、如果最后8个字是空闲的、或者不将其用于指令代码、那么它应该可以正常工作。 但是、"Reta"足以保持最后2个字的自由。 如果您可以确认、请告诉我。

    之后,我们将在内部系统中归档,并决定如何处理此问题,例如外部勘误表或链接器命令文件修复.....