assembly - Cortex M4: cmp instruction broken?
问题描述
This one's a doozy and I'm scratching my head.
Setup:
- ARM Cortex M4 microcontroller (PAC5532).
- Segger J-Link Plus debugger.
- GCC 7.2.0 compiler
- GDB 8.0.1
- Compiled with -O0 (no optimizations)
Here's the code. It's part of the debounce logic for a GPIO input. The GPIO is read via the pac5xxx_tile_register_read
function. The pin is bit 0 in dinsig1
. If dinsig
is 0x01
, that means the GPIO is high. If dinsig
is 0x00
, the GPIO is low.
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;
The if ((dinsig1 & 0x01) != 0)
instruction is the one causing problems. The code will correctly run until the GPIO goes from high to low, and then low to high (dinsig
goes from 0x01
to 0x00
to 0x01
). dinsig
always reads accurately, but if ((dinsig1 & 0x01) != 0)
evaluates to true.
Here's the disassembly for the if ((dinsig1 & 0x01) != 0)
statement.
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.
I'm watching the ASPR register register while stepping through the disassembly. The cmp r3, #0
instruction clearly sets the Zero flag, which it should not. Because r3 is 0x01
, and that is not equal to zero.
I'm at a loss here. Is this a branch predictor gone rogue? Tools broken? I know better than to blame the tools because it's virtually always my fault, but I find it hard to believe the CPU is misbehaving.
解决方案
感谢所有的建议。我通过将 GCC 更新到 9.3.1 和 GDB 到 9.2 解决了这个问题
推荐阅读
- javascript - 你如何在 JavaScript 中创建一个 12 小时的时间
- r - 使用 facet_wrap() 时在 ggplot 中手动标记轴
- r - 要在 R 中列出的数据框列的唯一值
- jenkins - 如何使用 curl 和身份验证令牌将参数传递给 Jenkins
- python - 将行中的所有值加 100 并更改零的函数
- database - 在 laravel 8 中使用 vuejs 从数据库中获取数据
- django - 设计问题:如何设计临时用户表?
- angular - 在Angular中将一个数据字段绑定到另一个?
- docker - 用户定义的桥接网络上的 Docker 容器无法通信
- python - 将什么 dtype 数据传递到 Tensorflow 模型中进行预测是否重要?