我想我可能在我的嵌入式固件代码中遇到了堆栈溢出问题或类似的问题。我是一个新程序员,从来没有处理过SO,所以我不确定这是不是正在发生的事情。
固件控制一个带有轮子的设备,轮子周围均匀分布着磁铁,电路板上有一个霍尔效应传感器,当磁铁在其上方时,该传感器可以感知。我的固件操作步进器,并在监测磁铁传感器的同时计数步数,以检测轮子是否已经熄火。
我在我的芯片上使用定时器中断(8位,8057acrh.)设置输出端口以控制电机并进行失速检测。失速检测代码看起来像这样...
// Enter ISR
// Change the ports to the appropriate value for the next step
// ...
StallDetector++; // Increment the stall detector
if(PosSensor != LastPosMagState)
{
StallDetector = 0;
LastPosMagState = PosSensor;
}
else
{
if (PosSensor == ON)
{
if (StallDetector > (MagnetSize + 10))
{
HandleStallEvent();
}
}
else if (PosSensor == OFF)
{
if (StallDetector > (GapSize + 10))
{
HandleStallEvent();
}
}
}每次触发ISR时都会调用此代码。PosSensor是磁铁传感器。MagnetSize是通过磁场所需的步进步数。GapSize是两个磁铁之间的步数。所以我想要检测轮子是否被磁铁上的传感器卡住了,或者没有被磁铁卡住。
这在很长一段时间内都很有效,但过了一段时间后,第一个stall事件将会发生,因为'StallDetector > (MagnetSize + 10)‘,但当我查看StallDetector的值时,它总是在220左右!这没有意义,因为MagnetSize总是在35左右。因此,拖延事件应该在46触发,但不知何故,它一直到220?并且我没有在代码中的其他任何地方设置stall检测器的值。
关于如何找到这个问题的根源,你有什么建议吗?
ISR如下所示
void Timer3_ISR(void) interrupt 14
{
OperateStepper(); // This is the function shown above
TMR3CN &= ~0x80; // Clear Timer3 interrupt flag
}HandleStallEvent只是将一些变量设置回它们的默认值,这样它就可以尝试另一次移动...
#pragma save
#pragma nooverlay
void HandleStallEvent()
{
///*
PulseMotor = 0; //Stop the wheel from moving
SetMotorPower(0); //Set motor power low
MotorSpeed = LOW_SPEED;
SetSpeedHz();
ERROR_STATE = 2;
DEVICE_IS_HOMED = FALSE;
DEVICE_IS_HOMING = FALSE;
DEVICE_IS_MOVING = FALSE;
HOMING_STATE = 0;
MOVING_STATE = 0;
CURRENT_POSITION = 0;
StallDetector = 0;
return;
//*/
}
#pragma restore发布于 2010-04-17 01:59:14
PosSensor是易失性的吗?也就是说,您是在某个地方更新PosSensor,还是直接读取GPIO?
我假设GapSize相当大(> 220?)我觉得你可能有种族问题。
// PosSensor == OFF, LastPosMagState == OFF
if(PosSensor != LastPosMagState)
{
StallDetector = 0;
LastPosMagState = PosSensor;
}
else
{
// Race Condition: PosSensor turns ON here
// while LastPosMagState still == OFF
if (PosSensor == ON)
{
if (StallDetector > (MagnetSize + 10))
{
HandleStallEvent();
}
}
else if (PosSensor == OFF)
{
if (StallDetector > (GapSize + 10))
{
HandleStallEvent();
}
}
}应该在执行StallDetector++之后缓存一次PosSensor的值,以便在代码过程中PosSensor发生变化时,不会开始测试新值。
发布于 2010-04-17 01:16:54
HandleStallEvent()是在ISR内“查看”StallDetector,还是在主循环上触发某些东西?如果它在主循环上,你是否清除了中断位?
或者,您正在从ISR之外的调试器中查看StallDetector?然后,重新触发的中断每次都会使用正确的值,但是执行的次数太多,您只能看到最终的、膨胀的值。
转念一想,您更有可能不必清除中断生成寄存器,而是由传感器保持对中断引脚的断言。您需要在第一次处理中断后忽略该中断,直到线路解除断言为止,例如,通过让原始ISR禁用自身,然后在处理1->0转换的第二个ISR中重新安装它。
然后,您可能还需要添加去抖动硬件或调整它(如果有)。
发布于 2010-04-17 01:23:27
这绝对不是堆栈溢出。如果你搞砸了堆栈(溢出堆栈),你的应用程序就会崩溃。这听起来更像是我在C++时代常说的记忆践踏。您可能无法仅通过StallDetector变量访问StallDetector值所占用的内存位置。您的代码的另一部分可能会错误地“践踏”这个特定的内存位置。
不幸的是,这类问题很难追踪。你唯一能做的就是系统地隔离(从执行中移除)你的代码块,直到你缩小范围并找到bug。
https://stackoverflow.com/questions/2654895
复制相似问题