0

我有两个数组。我在 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 循环中更新数组索引一样运行,而不是手动。任何人都可以提供见解可能是错误的。

4

2 回答 2

2

您可能在这里遇到细微的同步错误:

  1. 正如乔纳森指出的那样raw_data,它在函数内部失去了限定符。以这种方式使用volatile变量是未定义的行为,即使不涉及信号处理程序。
  2. 此外,信号处理程序似乎还异步触摸了您的数据。从 C99 开始,您可以使用此类信号处理程序接触的唯一数据类型是sig_atomic_t. C11 更进一步,还允许其他无锁原子类型:

当抽象机的处理因接收到信号而中断时,既不是无锁原子对象也不是 volatile sig_atomic_t 类型的对象的值是未指定的,浮点环境的状态也是如此。处理程序修改的任何对象(既不是无锁原子对象也不是 volatile sig_atomic_t 类型)的值在处理程序退出时变得不确定,如果浮点环境的状态被处理程序修改且未恢复,则它的状态也是不确定的回到原来的状态。

如您所见,尤其是接触浮点数被认为是不行的。

于 2012-10-21T14:21:41.460 回答
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. 您是否查看过为该函数生成的汇编语言?

于 2012-10-21T13:55:45.233 回答