Ejecute el código una vez en la vida de un programa C incrustado

8

¿Cómo puedo hacer que un fragmento de código se ejecute solo una vez en la vida de un programa? Se puede apagar y encender muchas veces. La única opción para ejecutar el fragmento de código nuevamente debe ser flashear la placa nuevamente.

El código es una sección de calibración que no quiero volver a ejecutar. Si uso EEPROM o Flash estaremos configurando un indicador en verdadero o falso. Entonces, cuando leemos por primera vez esa ubicación de memoria, ¿cuál sería el valor aleatorio en esa área de memoria?

¿Cuál es el mejor método para implementar esto en C incrustado?

ganeshredcobra
fuente
55
Use una bandera y guarde esta bandera en eeprom (o el flash). En cada instante lee la bandera de eeprom. La primera vez del instante, el valor de la bandera obligará a la función a ejecutarse. Después de eso, puede cambiar el valor de la bandera y guardarlo en eeprom nuevamente. Todas las demás veces el valor del indicador no forzará la ejecución de la función.
hoo2
2
No está claro lo que está preguntando.
old_timer
2
¿Cuál es su motivación para evitar que el código se ejecute por segunda vez? ¿Es importante que el código no se pueda aplicar ingeniería inversa, en cuyo caso establecer una bandera para omitirlo puede no ser lo suficientemente seguro? ¿Ejecutar el código por segunda vez dañaría el hardware? ¿Es una cuestión de UX, como mostrar un mensaje tutorial la primera vez que se usa el sistema, en cuyo caso podría ser deseable que la función de "restablecimiento de fábrica" ​​(si está presente) active el código para que se ejecute nuevamente?
Micheal Johnson el
55
En general, es una buena idea permitir la recalibración en caso de que algo se estropee la primera vez, o si el sistema necesita ser recalibrado para una configuración diferente o para compensar el envejecimiento del hardware, etc. Yo, por ejemplo, tiendo a estropear la calibración. primera vez porque no sé lo que se supone que debo hacer.
Micheal Johnson
3
¿Qué tal si configura el código para que haya una manera de ordenar que se ejecute (es decir, enviar algo a través de un puerto serie)? De esta manera, no hay necesidad de molestarse con la memoria no volátil y puede activar la calibración durante la producción de manera controlada.
alex.forencich

Respuestas:

18

Su microcontrolador puede tener alguna EEPROM, memoria OTP, bits de fusible de usuario, donde puede establecer una bandera.

No existe un "mejor método en C incrustado", escribir memoria no volátil es diferente en cada microcontrolador.

editar:

DESTELLO

El contenido de la memoria flash se borra mientras se programa el dispositivo. Después de la programación, todos los bytes que no se escribieron contienen 0xFF. Consulte la hoja de datos para encontrar un área que se pueda programar de forma segura desde el firmware en ejecución.

EEPROM

Aunque no está garantizado en las hojas de datos, todas las EEPROM que he visto hasta ahora contenían 0xFF: s cuando se enviaban desde la fábrica (excepto las preprogramadas con una dirección MAC única, pero eso está documentado explícitamente). Algunos dispositivos / software de programación también pueden borrar o programar contenidos EEPROM. Algunos pueden estar protegidos contra escritura, de forma permanente o reversible.

OTP

La memoria programable de una vez siempre contiene valores iniciales bien definidos, documentados en la hoja de datos.

Siempre es una buena idea incluir una buena suma de verificación como CRC32 con los datos escritos, para proteger contra la corrupción de datos causada por piezas defectuosas, errores de transmisión, rayos cósmicos, lo que sea.

berendi - protestando
fuente
Si uso EEPROM o Flash, configuraremos un indicador en verdadero o falso. Entonces, cuando leamos por primera vez esa ubicación de memoria, ¿cuál sería el valor aleatorio en esa área de memoria?
ganeshredcobra
2
Durante la fabricación, reinicie la EEPROM (ya sea con un programador, si es posible, o haciendo un pequeño programa tonto, limpie eso, enciéndalo normalmente durante unos segundos y luego cargue su programa de producción).
Nick T
13

Tu dijiste:

La única opción para ejecutar ese código debe volver a parpadear en el tablero.

Otros han dicho que usan EEPROM para almacenar una bandera para indicar cuándo se ha ejecutado la función run_once (). Sin embargo, esto tiene un inconveniente: si vuelve a actualizar el microcontrolador, el indicador ran_it_once en EEPROM ya se ha establecido y la función run_once () no se ejecutará. Si su microcontrolador tiene EEPROM integrada, entonces puede ser posible borrar el indicador ran_it_once cuando vuelve a instalar el microcontrolador, si el programador lo admite.

Una mejor manera es tener números de versión tanto en EEPROM como en el código. Cuando el código se ejecuta desde el encendido, debe leer el número de versión de EEPROM y compararlo con el número de versión almacenado en el código. Si no coinciden, se llama a la función run_once (), y el acto final del código run_once () es escribir el número de versión del firmware en EEPROM. Cada vez que modifique el código fuente del firmware, debe incrementar el número de versión incorporado en él.

Steve G
fuente
1
En realidad, esto tendría el mismo problema que una bandera booleana si todo lo que el usuario hizo fue volver a flashear el microcontrolador y necesitaba volver a ejecutarse nuevamente (en ese escenario). Definitivamente resolvería el problema si el firmware se actualizara y necesitara volver a ejecutarse.
Taegost
8

Elija un microcontrolador que pueda escribir / borrar su propia memoria de programa. Después de ejecutar el código en cuestión, haga que la última parte de dicho código reemplace la primera instrucción con un salto que lo omita. Opcionalmente, también puede borrar el resto (tal vez reemplazar con nop), para que no haya absolutamente ninguna posibilidad de que vuelva a ejecutarse.

Este mensaje se autodestruirá en 5..4 ...

apalopohapa
fuente
1
Por inteligente que pueda ser esta respuesta, creo que es innecesariamente compleja. ¿Tal vez podría usar una nota que especifique que probablemente solo debería usarse si la memoria persistente fuera de la memoria del código no está disponible?
skrrgwasme
Incluso si otras soluciones son posibles, creo que esto es más fácil de entender que otros.
Joshua
1
Incluso si otras soluciones fueran posibles, creo que esto sería muy difícil de entender a nivel de código fuente.
un CVn
La mayoría de los PIC solo tienen 35 instrucciones ... ¿qué podría salir mal? ;)
rdtsc
5

Como está utilizando este código para la calibración, mi sugerencia sería crear un proceso de explosión que ejecute el código de calibración como una primera etapa y ni siquiera tenerlo en la versión de producción terminada de la placa. Esto es similar a la respuesta de apalopohapa, excepto que es diferente en el sentido de que tendría dos cargas de programa separadas: tener un proceso de ráfaga que muestre la primera carga de programa que ejecuta todas las calibraciones y escupe los datos de eso. Luego tome esos datos e incorpórelos a los datos de la segunda carga del programa.

Una ventaja de este enfoque es que minimiza absolutamente la cantidad de espacio de almacenamiento que necesita: no necesita almacenar su código de una sola vez, solo los datos que genera. Al tener un proceso explosivo que carga dos programas separados, también se aísla un poco de los errores en el código de inicialización que de otro modo podrían demorarse. También tiene cierta flexibilidad adicional si desea volver a ejecutar su código de calibración: en lugar de tener que escribir código adicional para borrar cualquier bit que indique que su código se ha ejecutado (que ya podría borrarse accidentalmente) simplemente vuelva a ejecutar su proceso de explosión.

Miguel
fuente