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.
在过去的几周里、我一直与 TI Guru Ki RE 保持一致:当 DSS 脚本使用 asm (" :)构造以标记 DSS 脚本定义断点的代码中的位置。 起初、我认为问题出在 TI 演示板的错误构建上。 我最近的测试使用了5个不同的 TI 演示板、一个 controlCARD 和4个不同的 LaunchXL-F28379D 板。 都表现得相同。 下面是我的测试说明。
该测试程序从两个 GPIO 引脚(52和67)读取数据。 如果一个输入为高电平、另一个为低电平、则测试软件成功。 如果 GPIO67为低电平且 GPIO52为高电平、则发生 VALLED_CACT_0。 如果 GPIO67为高电平且 BPIO52为低电平、则发生 VALICAL_case_1。 如果两个引脚匹配、则返回 INVALID_GPIO_INPs、这两个引脚都为高电平或都为低电平。 这种方法可以轻松地通过 if / else 逻辑测试不同的路径、而无需对固件进行任何更改。
我已经使用编译器版本20.5和 CCS 版本12以及编译器版本22.6测试了 CCS 版本10.4的行为。 结果相同。 注意:结果随工程编译器优化级别的变化而变化。 此处列出的结果为优化级别1:局部优化。
对于所有演示板、3个测试用例的输出如下所示:
GPIO52=1、GPIO67=0:正确、如果执行、结果为:VALICE_SAFLE_0、TEST_DONE
GPIO52=0、GPIO67=1执行时出现故障、结果为:VALICAL_case1、VALICE_case_0、TEST_DONE
GPIO52=1、GPIO67=1如果执行时出现故障、结果为:INVALID_GPIO_INPINPINPINPs、VALID_C壳 体0、TEST_DONE
在所有3种情况下、第一个报告的 if case 是正确的、但当执行时显然有故障时、在程序完全退出 if / else case 之前、第二个 if /else case 的断点也会被命中。
我测试了一个假设、即当 asm (" :)语句是 if / else 情况中的最后一个语句。 在测试程序中、我将 asm (*)语句移动到每个 if / else 情况下最后一个可执行行的上方。 现在、DSS 针对所有3个测试用例正确执行调试会话。 因此、如果 if / else 逻辑是 if 或 else 情况下的最后一条语句、C2000编译器错误可能会将断点标签放置在错误的位置。 了解问题后的解决方法是移动断点标签、使其不是 if 或 else 情况下的最后一条语句。
这是一个包含 CCS 项目的 ZIP 文件。 DSS 脚本位于文件夹 JVScript 中。
请注意、启用优化级别1 (-o1)时、我可以重现故障行为。 如果我完全禁用优化、我始终会获得正确的行为。
我知道、在 C 代码中添加显式 asm 语句时、还需要考虑其他注意事项。 我将把这种解释留给我的同事、他们对编译器更熟悉
Ki
编译器没有做任何错误。 问题在于您假设有一种方法可以到达 ASM 创建的标签、该标签显示在由 if/else 条件控制的块的末尾。 正如您将看到的、这一假设是不正确的。
感谢您提交 CCS 项目。 我使用 C2000编译器版本20.2.5.LTS 构建它。 具体而言、我确保使用编译器选项-opt_level=1。 我还添加了选项--src_interlist。 这会导致编译器不会删除自动生成的汇编文件、并向其添加注释、从而使其更易于理解。 汇编文件与源文件具有相同的名称、文件扩展名更改为.asm。 考虑文件 GpioInputCheck.asm。 为了便于集中精力处理重要的行、我通过以下方式更改了文件:
其中包括:
_CheckIdInputs: ;* AR4 assigned to $O$C1 ;* AL assigned to _bGpioInputsAreValid ;*** 81 ----------------------- if ( !*(C$1 = &GpioValues[0]) ) goto g4; MOVL XAR4,#_GpioValues ; [CPU_ARAU] |81| MOV AL,*+XAR4[0] ; [CPU_ALU] |81| B $C$L3,EQ ; [CPU_ALU] |81| ; branchcc occurs ; [] |81| ;*** 81 ----------------------- if ( !C$1[1] ) goto g7; MOV AL,*+XAR4[1] ; [CPU_ALU] |81| B $C$L5,EQ ; [CPU_ALU] |81| ; branchcc occurs ; [] |81| ;*** 86 ----------------------- if ( GpioValues[0] ) goto g6; MOVW DP,#_GpioValues ; [CPU_ARAU] MOV AL,@$BLOCKED(_GpioValues) ; [CPU_ALU] |86| B $C$L4,NEQ ; [CPU_ALU] |86| ; branchcc occurs ; [] |86| $C$L3: ;*** -----------------------g4: ;*** 86 ----------------------- if ( !GpioValues[1] ) goto g6; MOVW DP,#_GpioValues+1 ; [CPU_ARAU] MOV AL,@$BLOCKED(_GpioValues)+1 ; [CPU_ALU] |86| B $C$L4,EQ ; [CPU_ALU] |86| ; branchcc occurs ; [] |86| ;*** 88 ----------------------- _bGpioInputsAreValid = 1u; ;*** 89 ----------------------- asm("VALID_CASE_1:"); ;*** ----------------------- goto g8; MOVB AL,#1 ; [CPU_ALU] |88| VALID_CASE_1: B $C$L6,UNC ; [CPU_ALU] ; branch occurs ; [] $C$L4: ;*** -----------------------g6: ;*** 93 ----------------------- _bGpioInputsAreValid = 0u; ;*** 94 ----------------------- asm("INVALID_GPIO_INPUTS:"); ;*** 94 ----------------------- goto g8; MOVB AL,#0 ; [CPU_ALU] |93| INVALID_GPIO_INPUTS: B $C$L6,UNC ; [CPU_ALU] |94| ; branch occurs ; [] |94| $C$L5: ;*** -----------------------g7: ;*** 83 ----------------------- _bGpioInputsAreValid = 1u; ;*** 84 ----------------------- asm("VALID_CASE_0:"); ;*** -----------------------g8: ;*** 97 ----------------------- return _bGpioInputsAreValid; MOVB AL,#1 ; [CPU_ALU] |83| VALID_CASE_0: $C$L6: SPM #0 ; [CPU_ALU] LRETR ; [CPU_ALU]
该代码是正确的、这是因为它返回所有输入的正确结果。 但请注意第48行和第49行。 它们各自为相同的地址定义标签。 第48行定义了标签 VALAR_CASE_0、第49行定义了标签$C$L6。 任何以$C$开头的标签都是编译器生成的标签。 请注意、$C$L6有两个分支。 一个在第30行、另一个在第39行。 假设执行达到第30行。 这意味着看到了 VALLED_CACT_1的断点。 接下来会发生什么情况? 到$C$L6的无条件分支。 这意味着即使在它之前的指令不执行、也会看到 VALLED_CACT_0的断点。 当执行达到第39行时、情况类似。
我不确定最佳解决方案。 一个快速解决方法是在每个 asm 语句中添加一个 nop。
asm("VALID_CASE_0: nop");
谢谢、此致、
乔治
George -感谢您花时间彻底分析此问题。 我想知道有多少 DSS 脚本的其他用户遇到了这种情况。 您是否知道 TI 是否计划修改编译器以在未来版本中防止此行为?
我已在我的所有 DSS ASM 标签上添加了一个 NOP、以免再次遇到此问题。
没有这种计划。
谢谢、此致、
乔治