我有两个数组。我正在main中调用一个函数,我根据另一个数组中的一些值更新其中一个数组。
volatile float32_t raw_data[3]; //this is being updated by an interrupt handler
void get_acc(int32_t* acc_data, float32_t* raw_data)
{
acc_data[0] = (raw_data[0] - OFFSETX)/SENSX; //OFFSETX and SENSX defined as a macro
acc_data[1] = (raw_data[1] - OFFSETY)/SENSY;
acc_data[2] = (raw_data[2] - OFFSETZ)/SENSZ;
}
int main()
{
int32_t acc_data[3];
int32_t data_ready = 0; //being updated by interrupt handler
while(1)
{
if(data_ready)
get_acc(acc_data,raw_data);
}
}
令我绝对震惊的是,当我使用断点观察变量并逐步执行get_acc时,只有第一个acc_data [0]得到更新,所有其他的都被设置为0,即使它们已被执行。现在我的第一个怀疑是它与指针有关,可能是地址没有正确更新。因为我已经使用了传递数组来像我更新for循环中的数组索引,而不是手动。 任何人都可以洞察可能出现的问题。
答案 0 :(得分:2)
这里可能有微妙的同步错误:
raw_data
已失去其功能内的限定符。以这种方式使用volatile
变量是未定义的行为,即使没有涉及信号处理程序。sig_atomic_t
。 C11更进一步,并允许其他无锁原子类型:当抽象机器的处理因收据而中断时 信号的对象,既不是无锁原子的对象的值 对象和类型volatile sig_atomic_t都没有指定,因为它是 浮点环境的状态。任何对象的价值 由处理程序修改,既不是无锁原子对象也不是 的 类型volatile sig_atomic_t在处理程序退出时变得不确定,如果它是浮点环境的状态也是如此 由处理程序修改而不是 恢复到原来的状态。
如你所见,特别是触摸浮点被视为不行。
答案 1 :(得分:1)
编译代码(Mac OS X 10.7.5上的GCC 4.7.1)时,我收到警告:
warning: passing argument 2 of ‘get_acc’ discards ‘volatile’ qualifier from pointer target type [enabled by default]
note: expected ‘float32_t *’ but argument is of type ‘volatile float32_t *’
我不确定这会解决您的麻烦,但这可能是一个因素。我注意到data_ready
也应该volatile
合格。
此外,如果使用-Wshadow
进行编译,则会得到:
In function ‘get_acc’:
warning: declaration of ‘raw_data’ shadows a global declaration [-Wshadow]
这更像是一种“误解风险”问题,而不是更严重的问题。
但是,除了限定符之外,您显示的代码是干净的,编译器应该生成代码以从raw_data
读取三个值并将其处理为acc_data
。您是否查看了为该函数生成的汇编语言?