Errores de lectura / escritura de EEPROM en dsPIC

8

Estoy ejecutando un Microchip dsPIC30F6012a. Tengo este chip en varios PCB, todos ejecutan el mismo software, y observo el mismo problema en todos ellos. Esto implica un problema sistémico, no un problema de producción único. 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 bajo prueba acepta 24V, que se reduce a 5V a través de un V7805. El chip funciona en su oscilador interno, con un PLL de 16x, lo que da una velocidad de operación de ~ 29.5 MIPS. El código relevante en esta placa es esencialmente muy simple: despertar, leer datos de EEPROM, luego ingresar un bucle infinito. Interrumpa cada milisegundo, observe algunos datos ambientales y escriba un valor actualizado en EEPROM. Hay otras cosas que suceden, pero el problema aún ocurre 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% de las veces la placa se despierta con el valor correcto en la memoria y continúa con su actividad. Sin embargo, el otro 5% de las veces se despierta con un valor incorrecto. Específicamente, se despierta con una versión de datos invertidos que se supone que tiene. Es un largo sin signo de cuatro bytes que estoy viendo, y la palabra superior o inferior del largo se puede voltear. Por ejemplo, 10 se convierte en 2 ^ 16-10, que luego se convierte en 2 ^ 32-10. Puedo reproducir la falla al encender y apagar manualmente varias docenas de veces, pero eso no es muy consistente, y mi dedo interruptor se desgasta.

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

El riel de 5V se comporta razonablemente. Se instala a 5V dentro de 1 mS de encendido, con quizás .4V de sobreimpulso, suponiendo que pueda confiar en mi alcance. En el apagado, decae a 0V exponencialmente, 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 el MCLR
  • Habilitar / deshabilitar el WDT
  • Habilitar / deshabilitar la protección del código
  • Habilitar / deshabilitar / cambiar el voltaje de detección de caída de voltaje
  • Habilitar / deshabilitar / cambiar el temporizador de encendido
  • Diferentes configuraciones PLL en el oscilador interno principal
  • Conectar / desconectar mi programador PICkit 3
  • Agregar 470 uF de capacitancia al riel de 5V
  • Agregar / quitar .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 nada más que actualizaciones EEPROM en el bucle principal
  • Agregar un retraso 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 más que escribir continuamente valores en EEPROM y luego volver a leerlos, 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 sale 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 fallas ocasionales, pero nada reproducible. El código relevante se puede encontrar aquí:
http://srange.net/code/eeprom.c
http://srange.net/code/readEEByte.s
http://srange.net/code/eraseEEWord.s
http: / /srange.net/code/writeEEWord.s

He visto errores de EEPROM antes en otras aplicaciones, pero siempre como problemas técnicos únicos, nada tan reproducible o consistente.

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

Stephen Collings
fuente
Consulte aquí para obtener una actualización sobre cómo resolver este problema: electronics.stackexchange.com/questions/38083/…
Stephen Collings

Respuestas:

3

Dos cosas me vienen a la mente:

Primero, de acuerdo con la hoja de datos, un ciclo de borrado-escritura toma al menos 0.8ms, y hasta 2.6ms. Dice que tiene una interrupción cada 1 ms, lo que puede conducir 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 aún puede obtener un entrelazado divertido de las llamadas a funciones. ¿Tal vez ayuda cuando deshabilita las interrupciones para toda la secuencia de borrar y escribir?

Segundo: es posible que desee escribir mientras se apaga la alimentación, y la escritura EEPROM ocurre exactamente en el momento en que el voltaje de suministro cae por debajo del voltaje de funcionamiento. Puede intentar monitorear el voltaje de suministro y rechazar una escritura cuando esté por debajo, digamos, 4.5V. Esto supone que se mantiene el tiempo suficiente por encima de 2.7V como voltaje mínimo de operación, y la detección de caída de voltaje está configurada para activarse solo por debajo de ese punto.

hli
fuente
¡Estás cerca! El ciclo es borrar-> escribir, por lo que si el apagado se produce entre borrar y escribir, perderá sus datos. Mi primera solución fue dividir la EEPROM en múltiples copias redundantes, que se verifican automáticamente en busca de inconsistencias. Pero como eso se comió 3/4 de mi EEPROM, lo estoy reemplazando con un simple buffer de escritura. El búfer será un bloque EEPROM especial que contiene los datos que se escribirán, la dirección en la que escribir y un indicador que indica que la escritura aún no se ha completado. Esto debería abordar el problema y ocupar mucho menos espacio.
Stephen Collings
Ahora puedo confirmar que mi enfoque basado en el búfer funciona y no sufre pérdida de datos debido al apagado asíncrono entre borrar y escribir.
Stephen Collings
5

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

Desafortunadamente, su código fuente está mal documentado y está formateado para que sea difícil de seguir visualmente. Su primer archivo contiene 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 privadas en los módulos del cliente, ¡no hay un solo comentario a la vista! Solo podemos adivinar qué pretende que hagan estas rutinas a partir de su nombre, y los argumentos de la llamada están 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 difícil tratar de seguir el código.

Puede decir que nada de esto es importante para el funcionamiento del código. Sin embargo, las malas prácticas de programación como esta son muy importantes. Causan que el código se escriba mal y dificultan la detección de errores o incluso lo que se supone que debe hacer el código. Todo esto resulta en acechar problemas difíciles de encontrar, como lo está descubriendo. Incluso dijo usted mismo que ocasionalmente ha visto fallas en este código desde 2007. Esa debería haber sido una fuerte pista de un error, posiblemente incluso de un mal diseño general.

Arregle el desorden, documente correctamente todas las interfaces y coloque declaraciones comunes en archivos de inclusión que escriba una vez, luego haga referencia cuando sea necesario. Además, su declaración de que no tengo advertencias de compilación que parecen relevantes es una gran bandera roja. De nuevo, arregla el desastre. Al depurar, siempre busque primero los problemas fácilmente reproducibles y reparables. Algunas veces esas son en realidad la causa de los problemas difíciles, o algunas veces al solucionarlas, descubres la causa de otros problemas. El compilador le advierte de descuido en 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 faltar nuevas líneas. Una vez más, corríjalos de manera evidente, especialmente antes de pedirle a alguien más que mire tu código.

La pulcritud y la atención al detalle importan . Mucho.

 

Olin Lathrop
fuente
Tienes toda la razón sobre el código. Para que quede claro, comencé a usar este código hace cinco años, pero alguien más lo escribió. No escribo cosas que se ve así. Todavía debería arreglarlo, y no es bueno que no lo haya hecho. Solo para que no me parezca un bobo tan grande. :-)
Stephen Collings
2
Acceder a la EEPROM interna es fácil. Para cosas tan simples, es más fácil escribir su propio código que tratar de descubrir cómo funciona el bugware de otra persona, luego parchearlo hasta que parezca funcionar. Lea la hoja de datos y escriba el código. Terminarías en una hora.
Olin Lathrop
Estoy de acuerdo con Olin aquí en que es muy probable que sea firmware. La parte errata menciona que nada es sospechoso con la EEPROM.
Adam Lawrence
2
@Madmad - Las hojas de erratas pueden no decir que hay algo sospechoso con la parte, pero nunca dirán que no hay nada sospechoso :-)
stevenvh
1
@stevenvh Mis tratos con Microchip y sus FAE han sido en su mayoría positivos. La errata de las partes que he estado usando ha sido precisa, y han saltado para ayudarnos con los problemas, a menudo encontrando soluciones para nosotros.
Adam Lawrence
0

Tuve un comportamiento idéntico con 4 PC 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 configurar a cero el MCLR justo antes del apagado.

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

Angelo
fuente
3
¿Por qué no sería eso factible? La detección de cortes de energía se hace mucho, incluso para guardar datos en EEPROM en el último ms.
stevenvh