【问题标题】:Cortex M4: cmp instruction broken?Cortex M4:cmp 指令损坏?
【发布时间】:2021-03-08 16:46:42
【问题描述】:

这是一个笨蛋,我正在摸不着头脑。

设置:

  • ARM Cortex M4 微控制器 (PAC5532)。
  • Segger J-Link Plus 调试器。
  • GCC 7.2.0 编译器
  • GDB 8.0.1
  • 使用 -O0 编译(无优化)

这是代码。它是 GPIO 输入的去抖动逻辑的一部分。 GPIO 通过pac5xxx_tile_register_read 函数读取。该引脚是dinsig1 中的位0。如果dinsig0x01,则表示GPIO 为高电平。如果dinsig0x00,则GPIO 为低电平。

static uint32_t triggerDebounce = 0;
volatile uint8_t dinsig1 = pac5xxx_tile_register_read(ADDR_DINSIG1);
if ((dinsig1 & 0x01) != 0) //This is the problem line.
  triggerDebounce = (triggerDebounce << 1);
else
  triggerDebounce = (triggerDebounce << 1) | 1;

if ((dinsig1 &amp; 0x01) != 0) 指令是导致问题的指令。代码将正确运行,直到 GPIO 从高到低,然后从低到高(dinsig0x010x000x01)。 dinsig 总是准确读取,但 if ((dinsig1 &amp; 0x01) != 0) 评估为真。

这是if ((dinsig1 &amp; 0x01) != 0) 语句的反汇编代码。

0x00004268  ldrb r3, [r7, #7] ;Loads dinsig into r3.
0x0000426a  uxtb r3, r3       ;Expands dinsig 3 into a 32 bit word.
0x0000426c  and.w r3, r3, #1  ;ANDs dinsig 3 with 0x01 and stores result in r3
0x00004270  cmp r3, #0        ;Compares r3 with 0
0x00004272  beq.n 0x4280 <IsTriggerPressed+40> ; Jumps to address 0x4280 if the ZERO flag is set.

我在逐步进行反汇编时正在查看ASPR register 寄存器。 cmp r3, #0 指令清楚地设置了零标志,它不应该这样做。因为r3是0x01,不等于0。

我在这里不知所措。这是一个分支预测器流氓吗?工具坏了?我知道最好不要责怪这些工具,因为这几乎总是我的错,但我很难相信 CPU 行为不端。

【问题讨论】:

  • 很奇怪。确保微控制器上的代码与您的测试代码相同。超出勘误表所述的指令不太可能存在缺陷。
  • 您已确认 r3 不为零?
  • 如果您不使用调试器而只运行代码会发生什么?
  • 分支预测不会影响 cmp 的结果,这将是 ALU 指令的值预测。并且分支预测或其他推测在架构上不可见 - 单步执行应该始终将您带到正确的分支目标,而不是推测性的猜测。

标签: assembly arm cortex-m branch-prediction


【解决方案1】:

感谢所有建议。我通过将 GCC 更新到 9.3.1 并将 GDB 更新到 9.2 解决了这个问题

【讨论】:

  • 大多数时候它不是工具链错误,直到极少数时候它是工具链错误:)
【解决方案2】:
.thumb_func
.globl TEST0
TEST0:
    mov r0,#1
    mov r3,#1 
    uxtb r3,r3       
    and.w r3,r3,#1  
    cmp r3,#0        
    beq.n skip
    mov r0,#0
skip:
    bx lr

按预期返回零。在皮质-m4 上。 r3 不包含您认为它包含的内容。在没有调试器的情况下试一试。

那或者你正在以某种方式自我修改代码。如果您认为这是分支预测(您在 sram 中运行代码,然后更改该代码并在同一地址空间中运行一些其他代码)。添加 BPIALL 写入

ldr r0,=0xE000EF78
str r0,[r0]

分支预测不执行分支,它只是提前几个时钟开始预取,如果分支没有发生,则不使用那些获取的指令。

如果您的内核甚至支持分支预测(CCR 寄存器位 18),您可以禁用分支预测。我现在运行的那个你不能设置那个位,所以似乎不受支持。

【讨论】:

    猜你喜欢
    • 2021-07-23
    • 1970-01-01
    • 2020-03-22
    • 2017-09-05
    • 1970-01-01
    • 1970-01-01
    • 2020-11-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多