PIC24FV Restablecer sin marca

1

Estoy trabajando en la creación de un flujo de programa basado en interrupciones utilizando el módulo PIC24FV32KA302 de Microchip. Sin embargo, estoy teniendo algunos problemas con los reinicios intermitentes (parece).

Actualmente estoy usando el simulador MPLAB X, tratando de averiguar dónde está ocurriendo el problema. Originalmente estaba usando un PICKit3 en hardware real, pero me encontré con un problema en el que, después de algunos ciclos a través del bucle principal, el depurador se detendría y lanzaría un error "PC en 0x0", que es una dirección sin una instrucción válida. No creo que estos problemas estén relacionados, pero realmente no puedo eliminar la posibilidad.

En esencia, el flujo de mi programa es el siguiente:

main()
{
   init();
   print_an_init_message();
   while(1)
   {
       check_some_flags();
       if(flags_are_set)
       {
          do_something_about_them();
       }
   }  
}

Durante la simulación, el programa imprime repetidamente el mensaje de inicio. Se atrapa en un punto de interrupción en el bucle while (1), por lo que debe estar entrando. Además, si continúo desde ese punto de interrupción, se repetirá (no se restablecerá). Si salgo de ese punto de interrupción, el depurador se bloquea.

Entonces, intenté imprimir los valores del registro RSON (que se supone que se debe establecer durante cualquier condición de reinicio) en el mensaje de inicio. Ninguno de los valores está establecido. Si agrego un retraso simple (XC16 __delay_ms () incorporado al bucle while, se llama a la interrupción _AddressError. La instrucción a partir de la cual se origina el error de dirección es siempre una instrucción ULNK de una de las funciones utilizadas en do_something_about_them () (que representa múltiples indicadores y funciones, parece posible que sea cualquiera de las funciones, pero la mayoría de las veces es la primero o último).

También vale la pena señalar, si coloco un punto de interrupción en la última línea de main (retorno -1), nunca se alcanza, pero el simulador imprime continuamente el mensaje de inicio.

¿Es probable que esto sea un problema con el simulador o con mi programa? ¿Podría estar relacionado con el problema de mi PC 0x0 cuando se ejecuta en hardware real, o es probable que sean diferentes?

Si alguien quiere un código real para ayudar, puedo proporcionarlo, simplemente no lo proporcioné de inmediato porque creo que podría ofuscar mi problema real, que no creo que esté causado por mi código C.

Gracias de antemano!

Después de un poco de depuración, logré que desapareciera el error de PC 0x0. Todavía estoy tratando de aterrizar en el error de dirección ISR. Ahora está programando hardware real con PICKit3.

Creo que el código que está causando el problema es una cola con la que estoy tratando.

typedef struct uint16_queue_tag {
    uint16_t *contents;
    int front;
    int back;
    int maxSize;
    int cnt;
} uint16_queue;

bool uint16_InitQueue(uint16_queue *queueP, uint8_t queueSize)
{
    uint16_t newContents[queueSize];

    queueP->contents = &newContents[0];
    queueP->maxSize = queueSize;
    queueP->cnt = 0;
    queueP->front = -1;
    queueP->back = -1;

    return true;
}

bool uint16_IsQueueEmpty(uint16_queue *queueP)
{
    return (bool) (queueP->cnt == 0);
}

bool uint16_IsQueueFull(uint16_queue *queueP)
{
    return (bool) (queueP->cnt == queueP->maxSize);
}

bool uint16_ClearQueue(uint16_queue *queueP)
{
    queueP->front = -1;
    queueP->back = -1;
    queueP->cnt = 0;

    return true;
}

bool uint16_PushQueue(uint16_queue *queueP, uint16_t element)
{
    if (uint16_IsQueueFull(queueP))
    {
        return false; // We can't push to the queue, its full
    }
    else
    {
        queueP->back++;
        queueP->contents[(queueP->back % queueP->maxSize)] = element;
        queueP->cnt++;
        return true;
    }
}

uint16_t uint16_PullQueue(uint16_queue *queueP)
{
    if (uint16_IsQueueEmpty(queueP))
    {
        return NULL;
    }
    else
    {
        queueP->front++;
        queueP->cnt--;
        return queueP->contents[(queueP->front % queueP->maxSize)];
    }
}

Parece que todo funciona bien para algunas iteraciones, pero en algún momento un uint16_PushQueue(&queue_obj, value) rompe el código. Una vez que se inicializa la cola, todo lo que hago es verificar si está llena, Push y Pull. Extrañamente, parece que el valor del puntero del contenido es diferente: después de que se rompe, el puntero apunta al mismo valor que "frente", que definitivamente no es el mismo valor en el que comenzó. Además, el elemento en el lugar al que apunta se informa, por MPLAB, como 0.0 (que definitivamente no es un flotador).

Supongo que esto es solo una especie de estupidez de asignación de punteros, lo que explica también todo el problema de la dirección: de alguna manera me estoy moviendo hacia donde apunta el puntero del contenido.

    
pregunta Ken

3 respuestas

2

La forma en que inicializas tu cola no está bien:

bool uint16_InitQueue(uint16_queue *queueP, uint8_t queueSize)
{
    uint16_t newContents[queueSize];
    queueP->contents = &newContents[0];
    queueP->maxSize = queueSize;
    queueP->cnt = 0;
    queueP->front = -1;
    queueP->back = -1;
    return true;
}

La matriz de longitud variable newContents se inicializará en la pila de uint16_InitQueue . Una vez que se devuelve la función, queueP->contents apuntará a la pila y cualquier intento de modificar su contenido dañará la pila y podría causar un bloqueo.

  

Parece que todo funciona bien para algunas iteraciones, pero en algunos   point a uint16_PushQueue (& queue_obj, valor) rompe el código. Después de la   la cola se inicializa, todo lo que hago es verificar si está llena, Push y   Tire.

Esto tiene mucho sentido, ya que hacer un uint16_PushQueue dañará la pila.

La matriz debe ser asignada dinámicamente (no es una buena práctica para sistemas integrados sin un sistema operativo) o asignada globalmente. Al programar el sistema integrado, normalmente se establece un tamaño máximo para la cola (o cualquier otro contenedor) en el momento de la compilación.

Algunos nitpicking:

bool uint16_IsQueueEmpty(uint16_queue *queueP)
{
    return (bool) (queueP->cnt == 0);
}

El elenco es totalmente inútil. Puedes hacer: return (queueP->cnt == 0) en su lugar.

Cuanto menos código, mejor.

    
respondido por el m.Alin
2

Suena como uno de dos posibles problemas. O el código está golpeando un puntero nulo o se habilita alguna interrupción que no tiene un controlador. En cualquier caso, el código intenta saltar a ninguna parte de manera efectiva y ese error podría establecerse.

Para verificar que este es el problema, cree cuatro interrupciones para las trampas incorporadas. Mire las cuatro interrupciones principales en la sección de interrupciones de la hoja de datos.

  1. Trampa de falla del oscilador
  2. Trampa de error de dirección
  3. Trampa de error de la pila
  4. trampa de error matemático

Depure el código como estaba antes y verifique si se encuentra en la trampa de error de dirección. Esto confirmaría el problema.

    
respondido por el vini_i
0

Parece que podrías tener un problema con el temporizador de vigilancia. Asegúrese de que el watchdog esté deshabilitado o que esté reiniciando correctamente el temporizador de watchdog. A veces, el temporizador de vigilancia se habilita como opción predeterminada. Así que creo que el programa es el tema aquí. Y el problema que está experimentando en el hardware es que la misma PC en 0x0 significa literalmente que el programa vuelve a cero, en otras palabras, el hardware se ha reiniciado.

    
respondido por el Kvegaoro

Lea otras preguntas en las etiquetas