errores de lectura / escritura de EEPROM en dsPIC

8

Estoy ejecutando un Microchip dsPIC30F6012a. Tengo este chip en varios PCB, todos ejecutando el mismo software, y observo el mismo problema en todos ellos. Esto implica un problema sistémico, no un problema de producción excepcional. El problema también es reproducible, lo que implica que debería poder matarlo si sé dónde buscar. Pero todavía tengo dificultades sorprendentes para depurar la aplicación.

La placa en prueba acepta 24V, que se reduce a 5V a través de un V7805. El chip se ejecuta en su oscilador interno, con un PLL 16x, dando una velocidad de operación de ~ 29.5 MIPS. El código relevante en este tablero es esencialmente muy simple: despierte, lea datos de EEPROM, luego ingrese un bucle infinito. Interrumpa cada milisegundo, observe algunos datos ambientales y escriba un valor actualizado en la EEPROM. Hay otras cosas en marcha, pero el problema sigue ocurriendo incluso si el código no relacionado está comentado, por lo que puedo estar razonablemente seguro de que no es relevante para el problema en cuestión.

En uso general, el 95% del tiempo la placa se despierta con el valor correcto en la memoria y continúa con su negocio. El otro 5% del tiempo, sin embargo, se despierta con un valor incorrecto. Específicamente, se despierta con una versión bit-volteada de los datos que se supone que tiene. Es un largo de cuatro bytes sin firmar que estoy viendo, y tanto la palabra superior como la inferior del texto largo se pueden voltear. Por ejemplo, 10 se convierte en 2 ^ 16-10, que luego se convierte en 2 ^ 32-10. Puedo reproducir el fallo al ciclar manualmente el poder varias docenas de veces, pero eso no es muy consistente, y mi interruptor se desgasta.

Para reproducir el problema de una manera controlada, construí una segunda placa que impulsa el suministro de 24 V a la placa bajo prueba. (Otro dsPIC que maneja un optoacoplador Darlington). La placa del comprobador apaga los 24V durante 1.5 segundos (el tiempo suficiente para que el riel de 5V caiga a 0 y permanezca allí por un segundo), luego enciende los 24V durante un tiempo configurable . Con un tiempo de funcionamiento de aproximadamente 520 mS, puedo reproducir esta falla de EEPROM dentro de cinco ciclos de energía, cada vez.

El riel de 5V se está comportando razonablemente. Se establece en 5V dentro de 1 mS de encendido, con quizás .4V de rebasamiento, asumiendo que puedo confiar en mi alcance. Al apagar, decae exponencialmente a 0V, alcanzando 1V dentro de 50 mS. No tengo advertencias de compilación que parezcan relevantes, solo variables no utilizadas y nuevas líneas faltantes al final de los archivos.

He intentado varias cosas:

  • Habilitar / deshabilitar MCLR
  • Habilitar / deshabilitar el WDT
  • Habilitar / deshabilitar la protección de código
  • Habilitar / deshabilitar / cambiar el voltaje de detección de caída de tensión
  • Habilitar / deshabilitar / cambiar el temporizador de encendido
  • Diferentes configuraciones de PLL en el oscilador interno principal
  • Conectar / desconectar mi programador PICkit 3
  • Agregar 470 uF de capacitancia al riel de 5V
  • Agregar / eliminar .1 uF a través del pullup de 4.7k en mi pin MCLR
  • Deshabilitar todas las interrupciones en el código y no dejar más que actualizaciones de EEPROM en el ciclo principal
  • Agregar una demora de 1.5 segundos a mi rutina de inicio antes de comenzar a leer EEPROM

También escribí un código de prueba separado que no hace nada más que escribir valores continuamente en la EEPROM y luego leerlos nuevamente, asegurándome de que el valor no haya cambiado. Decenas de miles de iteraciones no dieron errores. Todo lo que puedo concluir es que algo va mal con la lectura o escritura de EEPROM, específicamente en el encendido / apagado.

He estado usando las mismas bibliotecas EEPROM desde 2007. He visto fallos ocasionales, pero nada reproducible. El código relevante se puede encontrar aquí:
enlace
enlace
enlace
enlace

He visto errores de EEPROM antes en otras aplicaciones, pero siempre como fallos puntuales, nada tan reproducible o consistente.

¿Alguien tiene alguna idea de lo que está pasando? Me estoy quedando sin cosas para probar.

    
pregunta Stephen Collings

3 respuestas

3

Dos cosas vienen a mi mente:

Primero, según la hoja de datos, un ciclo de borrado-escritura toma al menos 0,8 ms y hasta 2,6 ms. Usted dice que tiene una interrupción cada 1 ms, lo que puede llevar a una operación de escritura. He visto en el código que deshabilita las interrupciones para partes del borrado y para partes de la función de escritura. Pero todavía puede obtener entrecruzamiento divertido de las llamadas de función. ¿Quizás te ayude cuando desactivas las interrupciones para toda la secuencia de borrar y escribir?

En segundo lugar, es posible que desee escribir mientras la alimentación disminuye, y la escritura de EEPROM ocurre exactamente en el momento en que la tensión de alimentación desciende por debajo de la tensión de funcionamiento. Puede intentar controlar la tensión de alimentación y rechazar una escritura cuando está debajo, digamos, 4.5V. Esto supone que permanece lo suficientemente largo por encima de 2,7 V como el voltaje de operación mínimo, y la detección de paro está configurada para activarse solo por debajo de ese punto.

    
respondido por el hli
4

Has visto muchos posibles problemas de hardware. Está bien, pero es muy probable que sea un error de firmware.

Desafortunadamente, su código fuente está mal documentado y está formateado para ser difícil de seguir visualmente. Su primer archivo contiene una declaración de rutinas externas en la parte superior:

void readEEByte(unsigned int, unsigned int, void*);
void eraseEEWord(unsigned int, unsigned int);
void writeEEWord(unsigned int, unsigned int, void*);

No solo es una mala idea poner declaraciones como esta en los módulos de clientes, ¡no hay un solo comentario a la vista! Solo podemos adivinar qué pretende hacer estas rutinas a partir de su nombre, y los argumentos de la llamada son completamente indocumentados. Además, en ese archivo tiene varias líneas que comienzan con "//" y una línea completa de signos iguales. Estos agregan desorden visual, lo que hace que sea demasiado complicado tratar de seguir el código.

Puede decir que nada de esto importa para la operación del código. Sin embargo, malas prácticas de programación como esta sí importan, mucho. Hacen que el código se escriba de manera deficiente y dificultan la detección de errores o incluso lo que se supone que debe hacer el código. Todo esto se traduce en acechar difícilmente para encontrar problemas, como usted está descubriendo. Incluso dijiste que ocasionalmente has visto fallas en este código desde 2007. Eso debería haber sido una pista fuerte de un error, posiblemente incluso de un mal diseño general.

Repare el desorden, documente adecuadamente todas las interfaces y coloque declaraciones comunes en los archivos de inclusión que escribe una vez, luego haga referencia cuando sea necesario. También su declaración de No tengo advertencias de compilación que parezcan relevantes es una gran señal de advertencia. De nuevo, arregla el desorden. Al realizar la depuración, siempre vaya primero a los problemas fácilmente reproducibles y solucionables. A veces, esas son realmente la causa de los problemas difíciles o, a veces, para solucionarlos, descubre la causa de otros problemas. El compilador le está advirtiendo de descuidos en una bandeja de plata. ¿Qué más quieres? No debe tener variables no utilizadas porque causan confusión a cualquiera que intente darle sentido a su código, y no hay ninguna excusa para perder nuevas líneas. Nuevamente, corríjalos en un lío obvio, especialmente antes de pedirle a otra persona que revise su código.

La pulcritud y la atención a los detalles son importantes . Mucho.

    
respondido por el Olin Lathrop
0

Tuve un comportamiento idéntico con 4 unidades de dsPIC30F6014A (de aproximadamente 10 usadas en los últimos meses ...), la única forma de evitar la corrupción esporádica de datos durante el apagado es poner a cero el MCLR justo antes del apagado.

Obviamente, esto no es factible en la práctica, así que opté por el reemplazo del dsPIC "malo", si alguien tiene otra solución en su lugar ...

    
respondido por el Angelo

Lea otras preguntas en las etiquetas