【发布时间】:2013-09-04 12:32:56
【问题描述】:
我正在用 C 语言编写一个回调函数。它旨在初始化 I2C 传感器,并在每个(分阶段)配置步骤结束时调用;在第 9 次通话后,设备几乎可以使用了。
函数的基本思路是这样的:
void callback(void)
{
static uint8_t calls = 0;
if (++calls == 9) {
// Finalise device setup (literally a single line of code)
}
}
我的问题是上面的 if 语句从未被输入,尽管函数被调用了 9 次。
我的函数的(反)汇编代码看起来很正常(除了subi . 0xFF 增量技巧,尽管包含inc 指令):
00000a4c <callback>:
a4c: 80 91 9e 02 lds r24, 0x029E
a50: 8f 5f subi r24, 0xFF ; 255
a52: 80 93 9e 02 sts 0x029E, r24
a56: 89 30 cpi r24, 0x09 ; 9
a58: 09 f0 breq .+2 ; 0xa5c <callback+0x10>
a5a: 08 95 ret
a5c: 2e e1 ldi r18, 0x1E ; 30
a5e: 35 e0 ldi r19, 0x05 ; 5
a60: 41 e0 ldi r20, 0x01 ; 1
a62: 60 e0 ldi r22, 0x00 ; 0
a64: 84 e7 ldi r24, 0x74 ; 116
a66: 0c 94 c7 02 jmp 0x58e ; 0x58e <twi_set_register>
我正在为 Atmel AVR 芯片编写代码,因此使用 avr-gcc 进行编译。我没有有意义的代码调试能力(我没有 JTAG 程序员,而且该功能无论如何都是异步/分相的;USART 打印太慢了)。
但是,我可以使用逻辑分析器,并且能够通过在代码中放置 while (1) ; 语句来确定许多事情:
- 函数被调用 - 如果我在函数开头放置一个无限循环,微控制器就会挂起
- 该函数应该被调用9次 - 该函数的触发器是一次I2C通信,在上一步中它在第一次通信后立即挂起;我可以观察到 9 个完整且有效的 I2C 通信
-
调用在函数内递增 - 如果我在递增之后添加
if (calls == 0) { while (1) ; },它不会挂起 -
调用在函数开始时永远不会非零 - 如果我在增量之前添加
if (calls) { while(1) ; },它不会挂起
我完全没有想法。
有没有人对可能导致这种情况的原因提出任何建议,或者甚至对我可以采取的新调试步骤有什么建议?
【问题讨论】:
-
编译器似乎没有正确处理静态变量。您是否尝试过使用全局变量?
-
根据您提供的事实,唯一可以推测的是您实际上并没有调用 9 次回调。反汇编是正确的(如预期的那样),并且您说回调至少被调用一次。但是,您没有在哪里确认它被调用了 9 次。一个建议:将循环计数器从 9 降低(到 7 或 5 或 2),然后查看您实际调用 twi_set_register 的时间点。另一个想法是,如果你有空闲的 I/O 在进入/退出时切换一个 pin 到 callback() 并使用逻辑分析器来确认你在其中的频率。
-
@IngoLeonhardt - 我尝试使用全局变量,结果相同。我还检查了地址
0x029E是否在.data中(它在内部 SDRAM 中,所以应该适合读/写访问) -
@Sapi 我同意调用在开始时为零。但是鉴于您提供的事实,我不相信回调被调用了 9 次。它可能被多次调用,但不会被调用 9 次。因此,如果您将检查从 9 降低到任何值,您可以确定它被调用了多少次;从而将您指向代码问题(可能不是此段)...
-
能否提供触发回调的代码?与内存损坏、静态变量处理不正确等相反,我更容易相信这不起作用。
标签: c static embedded avr avr-gcc