我在大学的实时系统课程中使用 ARM 微控制器。在我目前正在进行的项目中,我正在实现矢量场直方图(VFH)算法。
问题是:我需要在线程之间进行通信;更具体地说,我希望有一个线程从测距仪获取传感器数据,对其进行必要的转换并将它们存放在队列中。他们,另一个线程必须获取这些数据并处理它,等等。
目前,我正在使用它的一个更简单的版本——一个线程从 ADC(SensorAcquisitionHandler)获取数据,另一个线程(最多)将前 5 个项目的平均值输出到显示器(ControlSignalHandler)。
/* Queue used to store data from the rangefinder sensors. */
static unsigned int Sensors[100];
static int SensorsHead = 0;
static int SensorsTail = 0;
void SensorAcquisitionHandler(void) {
/* Clear the interrupt. */
ADCIntClear(ADC0_BASE, 1);
int i; /* Index for the measurements buffer. */
/* There are only 3 rangefinders used. */
if (ADCSequenceDataGet(ADC0_BASE, 1, rangeBuffer) == 3) {
/* Put rangeBuffer's data into SensorDataQueue. */
/* Also, when using SensorDataQueue, must put what's the direction of
the corresponding range measurement. */
/* Critical section ahead!!! Turn off interrupts!!! */
IntMasterDisable();
/* Temporarily using the simple FIFO... */
for (i = 0; i < 3; ++i) {
if (SensorsHead < 100) {
Sensors[SensorsHead] = rangeBuffer[i];
SensorsHead++;
}
}
/* All is fine, turn on interrupts. */
IntMasterEnable();
}
}
void ControlSignalHandler(void) {
/* Clear the timer interrupt. */
TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
unsigned char i; /* Index for the measurements buffer. */
unsigned long average = 0;
char buffer[20];
/* Average first n (n <= 5) elements from Sensors queue. */
for (i = 0; i < 5 && SensorsTail < SensorsHead; ++i) {
average += Sensors[SensorsTail];
SensorsTail++;
}
IntMasterDisable();
average /= i;
sprintf(buffer, "%d ", average);
average = 0;
if (SensorsTail >= SensorsHead) {
SensorsTail = 0;
SensorsHead = 0;
}
Display96x16x1StringDraw(buffer, 0, 0);
IntMasterEnable();
}
结果在一段时间内相对稳定,但在随机间隔内会变得非常高(结果几乎一直是 ~330)。此外,当我在“非常高的价值”时刻使用符号调试器时,索引 SensorTail 和 SensorHead 可以达到 300+(队列是一个 100 元素的数组)。
这听起来像是某种溢出,但我无法想象它是如何发生的。有人可以帮我找到吗?
我知道问题的答案是“使用线程安全队列”,但我想了解这里的竞争条件是如何发生的,索引是如何搞砸的,等等。谢谢!