嵌入式C:AVR; header 中的变量无法在 main 中求值

Embedded C: AVR; variable in header cannot be evaluated in main

感谢您抽出时间阅读。

我遇到的问题

我有:

main.h 

声明:

uint8_t u_newVar

我也有

foo.h 

写着:

extern uint8_t u_newVar

应用程序处于 main.c 的无限 while 循环中,直到发生 ISR。

在foo.c中表示ISR调用了foo.c内的一个函数。

在那个函数中(foo_function() 如果你愿意):0x01 被写入 u_newVar.

最后,从中断返回并回到无限 while 后,有一个 "if" 语句:

while(1){
  if(u_newVar == 0x01){
    uartTX_sendArray(st_uartRX_MessageContents->u_command, (sizeof st_uartRX_MessageContents->u_command));
    uartTX_sendButtonPressData(st_uartRX_MessageContents->u32_value);    
    u_newVar = 0x00;
  }
}

但是,应用程序永远不会进入 if。如果这个 "if" 块在 foo.c 中,在

之后,它将起作用
u_newVar = 0x01;

行。

我试过的东西

我查看了编译后的程序集,发现的东西让我有些困惑。

如果我查看 main 中的 "if",这就是我所看到的:

所以它从地址加载值:SRAM 的 0x011D,我可以确认是 0x01。

然后"CPI"将R24直接与0x01进行比较,显然应该可以。

然后"BREQ",如果相等则分支,并将程序计数器递增两次到下面的uart函数。也有道理。

然而这部分很奇怪。否则,使用"RJMP" 跳转到当前所在的指令。除非我弄错了,否则这会永远锁在这里?

所以,还记得我提到过在写入 u_newVar 之后将 if 块放入 foo.c 吗?是的,这不太有趣:

"if"本来应该在"u_newVar = 0x01"之后,但是编译器太聪明了,怎么优化。这就是为什么它总是在那里工作的原因。

您忘记告诉编译器变量可能被异步修改。例如在 ISR 中。

volatile uint8_t u_newVar;

您看到的是汇编程序的输出,而不是链接代码。

链接器在重定位 table 中包含代码中该偏移量的信息(指令的数据字节和实际目标偏移量是什么)。在链接过程中(或对于某些环境)在加载处理期间)这些数据字节将被更新以包含正确的值