我有一些针对AVR的C代码。代码是用avr gcc编译的,基本上是具有正确后端的GNU编译器。
我要做的是在我的一个事件/中断驱动的库中创建一个回调机制,但是我似乎在保持函数指针的值方面遇到了一些困难。
首先,我有一个静态库。它有一个头文件(
twi_master_driver.h
)看起来是这样的:
#ifndef TWI_MASTER_DRIVER_H_
#define TWI_MASTER_DRIVER_H_
#define TWI_INPUT_QUEUE_SIZE 256
// define callback function pointer signature
typedef void (*twi_slave_callback_t)(uint8_t*, uint16_t);
typedef struct {
uint8_t buffer[TWI_INPUT_QUEUE_SIZE];
volatile uint16_t length; // currently used bytes in the buffer
twi_slave_callback_t slave_callback;
} twi_global_slave_t;
typedef struct {
uint8_t slave_address;
volatile twi_global_slave_t slave;
} twi_global_t;
void twi_init(uint8_t slave_address, twi_global_t *twi, twi_slave_callback_t slave_callback);
#endif
现在是C文件(
twi_driver.c
):
#include <stdint.h>
#include "twi_master_driver.h"
void twi_init(uint8_t slave_address, twi_global_t *twi, twi_slave_callback_t slave_callback)
{
twi->slave.length = 0;
twi->slave.slave_callback = slave_callback;
twi->slave_address = slave_address;
// temporary workaround <- why does this work??
twi->slave.slave_callback = twi->slave.slave_callback;
}
void twi_slave_interrupt_handler(twi_global_t *twi)
{
(twi->slave.slave_callback)(twi->slave.buffer, twi->slave.length);
// some other stuff (nothing touches twi->slave.slave_callback)
}
然后,我将这两个文件构建成一个静态库(.a)并构建我的主程序。(
main.c
)
包括:
包括:
包括:
#包括
#包括“twi_master_driver.h”
// ...define microcontroller safe way for mystdout ...
twi_global_t bus_a;
ISR(TWIC_TWIS_vect, ISR_NOBLOCK)
{
twi_slave_interrupt_handler(&bus_a);
}
void my_callback(uint8_t *buf, uint16_t len)
{
uint8_t i;
fprintf(&mystdout, "C: ");
for(i = 0; i < length; i++)
{
fprintf(&mystdout, "%d,", buf[i]);
}
fprintf(&mystdout, "\n");
}
int main(int argc, char **argv)
{
twi_init(2, &bus_a, &my_callback);
// ...PMIC setup...
// enable interrupts.
sei();
// (code that causes interrupt to fire)
// spin while the rest of the application runs...
while(1){
_delay_ms(1000);
}
return 0;
}
我小心地触发导致中断触发的事件,并调用适当的处理程序。使用一些fprintf,我可以知道分配给
twi->slave.slave_callback
在
twi_init
函数与
twi_slave_interrupt_handler
功能。
尽管这些数字毫无意义,
捻音
该值为0x13B,且在
twi_slave_中断处理程序
打印时,值为0x100。
通过在
C驱动程序
:
twi->slave.slave_callback = twi->slave.slave_callback;
这个问题消失了,但这显然是一个神奇而不受欢迎的解决方案。我做错什么了?
据我所知,我已经标记了适当的变量
volatile
我试着把其他部分标记为易挥发,去掉易挥发的标记。当我注意到移除时,我想出了解决方法。
fprintf
分配后的语句
捻音
导致稍后以不同方式读取值。
问题似乎在于我如何传递函数指针——尤其是访问指针值的程序部分(函数本身?)从技术上讲是不同的。
有什么想法吗?
编辑:
-
解决了代码中的拼写错误。
-
链接到实际文件:
http://straymark.com/code/
[测试.c_twi_driver.c_twi_driver.h]
-
fwiw:编译器选项:
-Wall -Os -fpack-struct -fshort-enums -funsigned-char -funsigned-bitfields -mmcu=atxmega128a1 -DF_CPU=2000000UL
-
我尝试过直接包含相同的代码(而不是通过库),我也遇到了同样的问题。
编辑(第2轮):
-
我删除了所有的优化,没有我的“解决方法”,代码就可以按预期工作。添加back-os会导致错误。为什么-os会破坏我的代码?