2012-02-08 17 views
6

Tengo un error extraño en mi código que desaparece cuando intento depurarlo.Error de Schrödinger cuando se establece un punto de interrupción

En mi interrupción del temporizador (siempre corriendo ticker sistema) Tengo algo como esto:

if (a && lot && of && conditions) 
{ 
    some_global_flag = 1;     // breakpoint 2 
} 

en mi bucle principal tengo

if (some_global_flag) 
{ 
    some_global_flag = 0; 
    do_something_very_important(); // breakpoint 1 
} 

Esta condición en el bucle principal nunca es llamado cuando las condiciones en el temporizador están (creo) cumplidas. Las condiciones son externas (portpins, resultados de ADC, etc.). Primero puse un punto de interrupción en la posición 1, y nunca se desencadena.

Para verificarlo, puse breakpoint nr. 2 en la línea some_global_flag = 1;, y en este caso el código funciona: ambos puntos de interrupción se activan cuando las condiciones son verdaderas.

Actualización 1:

Para investigar si alguna condición de tiempo es responsable, y la if en el temporizador no se introduce si se ejecuta sin depurar, añadí lo siguiente en mi contador de tiempo:

if (a && lot && of && conditions) 
{ 
    some_global_flag = 1;     // breakpoint 2 
} 


if (some_global_flag) 
{ 
    #asm("NOP"); // breakpoint 3 
} 

La bandera no se usa en ningún otro lado en el código. Está en la RAM, y la RAM se borra a cero al comienzo.

Ahora, cuando todos los puntos de interrupción están desactivados (o solo está habilitado el punto de interrupción 1 en el principal), el código no funciona correctamente, la función no se ejecuta. Sin embargo, si habilito solo el punto de interrupción 3 en el NOP, ¡el código funciona! El punto de interrupción se activa y, después de continuar, se ejecuta la función. (Tiene salida visible y audible, por lo que es evidente si se ejecuta)

Actualización 2:

la interrupción de temporizador fue interrumpible, por medio de un "SEI" en su comienzo. Eliminé esa línea, pero el comportamiento no se modifica de manera notable.

Actualización 3:

No estoy usando cualquier memoria externa. Como estoy muy cerca del límite en el flash, tengo la optimización de tamaño en el compilador al máximo.

¿Puede el compilador (CodeVision) ser responsable, o hice algo muy mal?

+0

¿Hay alguna manera de intentar agregar algún tipo de registro, en lugar de establecer puntos de interrupción? Normalmente dudaría en sugerir eso, pero en este caso puede ser menos perturbador para el sistema. En particular, lo que registraría es el estado de sus condiciones en cada pasada a través del código de interrupción del temporizador. –

+1

¿Cómo se define some_global_flag? ¿Estás usando 'volatile int some_global_flag'? – DipSwitch

+0

¿Está usando memoria externa? ¿O solo la SRAM interna? ¿Qué chip estás usando exactamente? – DipSwitch

Respuesta

3

Puede parecer extraño, pero finalmente resultó ser causado por fuertes transitorios en una de las líneas de entrada (que alimenta el sistema, pero su medición ADC también se usa como condición).

El sistema puede tener fallas de energía periódicas durante un corto período de tiempo y se guardan datos temporales importantes en parte de la SRAM interna, que no se limpia después del arranque y está diseñado para retener los datos (durante 10 minutos o más)) con el uso de un pequeño condensador mientras la CPU está apagada.

No publiqué esto en la pregunta porque probé esta parte del sistema y funcionó perfectamente, así que no quise desviar tu curso.

Lo que descubrí al final, es que se utilizó una nueva característica en un entorno que creaba transitorios muy fuertes, y una de las condiciones en mi pregunta dependía de un estado que dependía de una de esas variables en el " RAM permanente ", y finalmente usar un punto de interrupción me salvó de los efectos de ese transitorio.

Finalmente el problema se resolvió con ajustes en el tiempo.

Editar: lo que me ayudó a encontrar la ubicación del problema fue que registré los valores de mis variables más importantes en el área de "memoria RAM permanente" y pude ver que algunos de ellos se corrompieron.

+2

Esto es realmente una razón general para este tipo de problema: la eliminación de errores tiende a perturbar el tiempo de alguna manera, y si tiene una situación que es sensible a los problemas de sincronización, la depuración definitivamente puede afectarlo. A menudo no hay mucha información significativa en _how_ la depuración lo afecta (en parte porque es difícil decir cómo la depuración está afectando el tiempo), sin embargo. –

+2

Creo que sería interesante agregar un poco a esta respuesta que describe cómo terminó diagnosticando el problema, así como también lo que encontró. Además, dado que sabes que esta es la respuesta correcta, debes aceptarla para que esté completa. :) –

+0

Bueno que lo hayas solucionado. Algo bueno salió de eso: agregaste volatilidad a tu bandera global (si no la agregaste, por favor, realmente debería estar allí). – Gauthier

1

Puede que me equivoque aquí, pero si está utilizando un depurador para conectarlo al tablero en cuestión y depurar el programa en el hardware que se suponía debía ejecutar, creo que puede cambiar el comportamiento del microcontrolador cuando funciona un adjunto .... Aparte de eso, y la palabra clave volátil sugerida anteriormente, no tengo pistas.

+0

También lo probé con 'volátil', sin cambios en el comportamiento. – vsz

+0

Lo extraño es que la funcionalidad ** correcta ** se logra cuando se utiliza el depurador. – vsz

4

Esto es probablemente un error típico de optimización/depuración. Asegúrese de que some_global_flag esté marcado como volátil. Esto puede ser un int uint8 uint64 lo que quieras ...

volatile int some_global_flag 

De esta manera usted le dice al compilador que no hacer ninguna suposición sobre cuál será el valor de some_global_flag. Debe hacer esto porque el compilador/optimizador no puede ver ninguna llamada a su rutina de interrupción, por lo que asume que some_global_flag siempre es 0 (el estado inicial) y nunca cambia.

Lo sentimos leído mal la parte donde bastante bueno en ello ...

Usted puede tratar de compilar el código con avr-gcc y ver si tiene el mismo comportamiento ...

+0

Lo probé con volátiles, lo que no produjo ningún cambio en el comportamiento. – vsz

4

depuradores puede/hacer cambia la forma en que el procesador se ejecuta y el código se ejecuta, por lo que no es sorprendente.

divide y conquista. Comience a quitar cosas hasta que funcione. Paralelamente a ese comienzo con nada, solo agregue la interrupción del temporizador y las pocas líneas de código en el ciclo principal con do_something_very_important() siendo algo tan simple como parpadear un led o escupir algo fuera del uart. si eso no funciona, no obtendrás la aplicación más grande para funcionar. Si eso funciona, comienza a agregar el código de inicio y más condiciones en tu interrupción, pero no compliques el ciclo principal más que las pocas líneas descritas. Aumente las condiciones del controlador de interrupciones agregando más código nuevamente hasta que falle.

Cuando llegue al límite donde puede agregar una cosa y fallar y eliminarla, y no fallar, desarme para ver si se trata de algo del compilador. esto podría justificar otro ticket SO si no es obvio, "¿por qué se rompe mi controlador de interrupción avr cuando agrego ..."

Si puede obtener esto a un número pequeño de líneas de código una docena o tan principales y solo las pocas líneas de interrupción, publíquelas para que otros puedan probarlas en su propio hardware y quizás lo resuelvan en paralelo.

1

Esto se escribe suponiendo un procesador ARM.

usando un punto de interrupción (RAM o bkpoint ROM) procesador fuerzas para cambiar de modo de marcha al modo de depuración en el punto de interrupción (ya sea a modo de detener o modo de monitor) y forzar para que se ejecute en la velocidad de depuración o para ejecutar un controlador de interrupción y por lo tanto, la depuración basada en JTAG es básicamente una depuración intrusiva.

ETM (Trace Macrocell incorporado), específicamente en ARM (u otros tipos de instrumentación de bus) está diseñado para no ser intrusivo y puede registrar las instrucciones y datos en tiempo real para que podamos inspeccionar lo que realmente sucedió.

Cuestiones relacionadas