Pregunta

creo que podría estar teniendo un problema de desbordamiento de pila o algo similar en mi código de firmware embebido. Soy un programador nuevo y nunca he tratado con un SO así que no estoy seguro si eso es lo que está pasando o no.

Los controles de firmware de un dispositivo con una rueda que tiene imanes espaciados uniformemente alrededor de ella y la placa tiene un sensor de efecto Hall que los sentidos cuando el imán está sobre ella. Mi firmware opera el paso a paso y también contar los pasos mientras se monitoriza el sensor de imán con el fin de detectar si la rueda se ha estancado.

Estoy utilizando una interrupción de temporizador en mi chip (8 bit, 8057 ACRH.) A puertos de salida ajustado para controlar el motor y para la detección de la parada. Los códigos de detección de parada es similar al siguiente ...

    //   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();
            }
        }
    }

este código se llama cada vez que se activa el ISR. PosSensor es el sensor de imán. MagnetSize es el número de pasos de pasos que se necesita para obtener a través del campo magnético. GapSize es el número de pasos entre dos imanes. Así que quiero para detectar si la rueda se atasca o bien con el sensor sobre un imán o no más de un imán.

Esto funciona muy bien durante mucho tiempo, pero después de un tiempo se producirá el primer evento parada porque 'StallDetector> (MagnetSize + 10)', pero cuando miro el valor de StallDetector es siempre alrededor de 220! Esto no tiene sentido, porque MagnetSize está siempre alrededor de 35. Así que el evento puesto debería haber sido activado en como 46 pero de alguna manera se puso todo el camino hasta 220? Y no establecer el valor de detector de parada en cualquier otro lugar en mi código.

¿Tiene algún consejo sobre cómo puedo localizar a la raíz de este problema?

Las miradas ISR como este

void Timer3_ISR(void) interrupt 14
{
    OperateStepper();  // This is the function shown above
    TMR3CN &= ~0x80;   // Clear Timer3 interrupt flag        
}

HandleStallEvent simplemente establece una variable de volver a unos pocos de sus valores por defecto para que pueda intentar otro movimiento ...

#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
¿Fue útil?

Solución

es PosSensor volátil? Es decir, se puede actualizar PosSensor alguna parte, o es directamente leyendo un GPIO?

Asumo GapSize es bastante grande (> 220?) Me suena como que podría tener una condición de carrera.

// 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();
            }
        }
    }

Se debe almacenar en caché el valor de PosSensor vez, justo después de hacer StallDetector ++, por lo que en caso PosSensor cambia durante su código, no se empieza a probar el nuevo valor.

Otros consejos

Esto definitivamente no es desbordamiento de pila. Si usted sopló la pila (desbordado ella) su aplicación se limitaría a estrellarse. Esto suena más como algo de lo que solían llamar pisando memoria en mis días de C ++. Puede que no esté accediendo a la memoria en la cual el valor StallDetector ocupa través StallDetector variable solamente. Puede haber otra parte de su código "pisando fuerte" esta posición de memoria particular, erróneamente.

Por desgracia, este tipo de problema es muy difícil de rastrear. Sobre la única cosa que podría hacer es sistemáticamente aislado (quitar de la ejecución) trozos de su código hasta que optimizar y encontrar el error.

¿Tiene ISR anidan en su sistema? Podría ser algo en la línea de empezar el ISR e incrementar su recuento, a continuación, interrumpirlo y hacerlo de nuevo. Hacer esto suficientes veces y su pila de interrupción puede desbordarse. También podría explicar una variable de contador tan alta también.

¿El HandleStallEvent() "ver" StallDetector dentro del ISR o se desencadenan algo en el bucle principal? Si está en el bucle principal, que está limpiando el bit de interrupción?

O estás mirando StallDetector de un depurador fuera del ISR? A continuación, volver a activar una interrupción usaría el valor correcto cada vez, pero ejecutar demasiadas veces, y sólo se vería el valor final, inflado.

En el segundo pensamiento, más probable es que no tiene que borrar un registro de generación de interrupción, sino más bien el pin de interrupción está quedando afirmado por el sensor. Es necesario hacer caso omiso de la interrupción después de que primero manejado hasta que los deasserts línea, como por tener el disable ISR original de sí mismo y y volver a instalarlo en un segundo ISR que se ocupa de la transición 1-> 0.

A continuación, podría también necesitar agregar hardware o supresión de rebotes ajustarlo si lo tiene.

Compruebe sus tipos de parámetros. Si se han definido los parámetros de una manera diferente que las Espera de llamadas a continuación, llamando a su método podría sobrescribir el espacio de esa variable se almacena en. (Por ejemplo, si usted escribió la función que espera un int pero está presionando mucho en la pila.)

Se podía ver qué opciones adicionales que admite su depurador. En Visual Studio, por ejemplo, es posible establecer un "punto de interrupción de datos", en donde se rompe cuando un cambios de ubicación de memoria (o se establece en un valor determinado, o por encima de un umbral, ...).

Si algo como esto es posible en su caso, se podía ver donde se cambian los datos y si hay algún otro escrito a la memoria erróneamente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top