¿Qué es un gestor de arranque y cómo desarrollaría uno?

53

He conocido muchos proyectos en los que un microcontrolador AVR usa un cargador de arranque (como el Arduino), pero no entiendo muy bien el concepto.

¿Cómo puedo hacer un gestor de arranque (para cualquier microcontrolador)?

Después de escribir mi gestor de arranque, ¿cómo se programa en el microcontrolador (como cualquier programa .hex grabado en la memoria flash del AVR, o algún otro método)?

mina_g
fuente
10
Lo etiquetó con la etiqueta del cargador de arranque , ¿lo leyó? Si es así, ¿leyó el Arduino Bootloader , Arduino Bootloader Follow On , Arduino Bootloader , Buenas herramientas o métodos para comprender la estructura de bootloader y las preguntas de Detalles de Arduino Bootloader ? Esos todos abordan partes de su pregunta inicial. Lo he reducido a las cosas nuevas.
Kevin Vermeer
Un artículo sobre el método de diseño BootLoader: beningo.com/wp-content/uploads/images/Papers/…
yahya tawil
2
@KevinVermeer Creo que su pregunta es más directa.
richieqianle

Respuestas:

103

Un gestor de arranque es un programa que se ejecuta en el microcontrolador para ser programado. Recibe nueva información del programa externamente a través de algunos medios de comunicación y escribe esa información en la memoria del programa del procesador.

Esto está en contraste con la forma normal de llevar el programa al microcontrolador, que es a través de un hardware especial integrado en el micro para ese propósito. En PIC, esta es una interfaz similar a SPI. Si recuerdo bien, los AVR usan Jtag, o al menos algunos de ellos lo hacen. De cualquier manera, esto requiere un hardware externo que mueva los pines de programación para escribir la información en la memoria del programa. El archivo HEX que describe el contenido de la memoria del programa se origina en una computadora de propósito general, por lo que este hardware se conecta a la computadora por un lado y los pines especiales de programación del micro por el otro. Mi compañía hace programadores de PIC, entre otras cosas, como actividad secundaria, por lo que estoy bastante familiarizado con este proceso en PIC.

El punto importante de la programación externa a través de hardware especializado es que funciona independientemente de los contenidos existentes de la memoria del programa. Los microcontroladores comienzan con la memoria del programa borrada o en un estado desconocido, por lo que la programación externa es el único medio para obtener el primer programa en un micro.

Si está seguro del programa que desea cargar en su producto y sus volúmenes son lo suficientemente altos, puede tener el programa del fabricante o un distribuidor para usted. El chip se suelda a la placa como cualquier otro chip, y la unidad está lista para funcionar. Esto puede ser apropiado para algo como un juguete, por ejemplo. Una vez que el firmware está listo, está prácticamente terminado y se producirá en grandes volúmenes.

Si sus volúmenes son más bajos, o lo que es más importante, espera un desarrollo continuo de firmware y correcciones de errores, no desea comprar chips preprogramados. En este caso, se montan chips en blanco en la placa y el firmware debe cargarse en el chip como parte del proceso de producción. En ese caso, las líneas de programación de hardware deben estar disponibles de alguna manera. Esto puede ser a través de un conector explícito o pads de pin pogo si está dispuesto a crear un accesorio de prueba de producción. A menudo, dichos productos deben probarse y calibrarse de todos modos, por lo que el costo adicional de escribir el programa en el procesador suele ser mínimo. A veces, cuando se utilizan pequeños procesadores, se carga primero un firmware de prueba de producción especial en el procesador. Esto se utiliza para facilitar las pruebas y la calibración de la unidad, entonces el firmware real se carga después de que se sabe que el hardware es bueno. En este caso, hay algunas consideraciones de diseño de circuito para permitir el acceso a las líneas de programación lo suficiente como para que el proceso de programación funcione, pero también para no molestar demasiado al circuito. Para más detalles sobre esto, vea miescritura de programación en circuito .

Hasta ahora todo bien, y no se necesita ningún gestor de arranque. Sin embargo, considere un producto con firmware relativamente complejo que desee actualizar en el campo o incluso permitir que el cliente final se actualice. No puede esperar que el cliente final tenga un dispositivo de programador, o sepa cómo usar uno correctamente, incluso si usted lo proporcionó. En realidad, uno de mis clientes hace esto. Si compra su opción de personalización de campo especial, obtiene uno de mis programadores con el producto.

Sin embargo, en la mayoría de los casos solo desea que el cliente ejecute un programa en una PC y tenga el firmware actualizado mágicamente. Aquí es donde entra un gestor de arranque, especialmente si su producto ya tiene un puerto de comunicaciones que puede interactuar fácilmente con una PC, como USB, RS-232 o Ethernet. El cliente ejecuta un programa de PC que habla con el gestor de arranque que ya está en el micro. Esto envía el nuevo binario al gestor de arranque, que lo escribe en la memoria del programa y luego hace que se ejecute el nuevo código.

Suena simple, pero no lo es, al menos no si quieres que este proceso sea robusto. ¿Qué sucede si se produce un error de comunicación y el nuevo firmware está dañado cuando llega al gestor de arranque? ¿Qué pasa si la energía se interrumpe durante el proceso de arranque? ¿Qué pasa si el gestor de arranque tiene un error y craps en sí mismo?

Un escenario simplista es que el gestor de arranque siempre se ejecuta desde el reinicio. Intenta comunicarse con el host. Si el host responde, le dice al gestor de arranque que no tiene nada nuevo o le envía un código nuevo. A medida que llega el nuevo código, se sobrescribe el código anterior. Siempre incluye una suma de verificación con el código cargado, para que el gestor de arranque pueda saber si la nueva aplicación está intacta. De lo contrario, permanece en el gestor de arranque solicitando constantemente una carga hasta que algo con una suma de verificación válida se cargue en la memoria. Esto puede ser aceptable para un dispositivo que siempre está conectado y posiblemente donde se ejecuta una tarea en segundo plano en el host que responde a las solicitudes del cargador de arranque. Este esquema no es bueno para las unidades que son en gran medida autónomas y solo ocasionalmente se conectan a una computadora host.

Por lo general, el gestor de arranque simple como se describió anteriormente no es aceptable ya que no hay seguridad contra fallas. Si una nueva imagen de la aplicación no se recibe intacta, desea que el dispositivo continúe ejecutando la imagen anterior, que no esté muerta hasta que se realice una carga exitosa. Por esta razón, generalmente hay dos módulos especiales en el firmware, un cargador y un cargador de arranque. El cargador es parte de la aplicación principal. Como parte de las comunicaciones regulares con el host, se puede cargar una nueva imagen de la aplicación. Esto requiere memoria separada de la imagen principal de la aplicación, como una EEPROM externa o usar un procesador más grande para que la mitad del espacio de memoria del programa se pueda asignar al almacenamiento de la nueva imagen de la aplicación. El cargador solo escribe la nueva imagen de la aplicación recibida en alguna parte, pero no la ejecuta. Cuando se reinicia el procesador, lo que podría ocurrir a pedido del host después de una carga, Se ejecuta el gestor de arranque. Este es ahora un programa totalmente autónomo que no necesita capacidad de comunicación externa. Compara las versiones actuales y cargadas de la aplicación, verifica sus sumas de verificación y copia la nueva imagen en el área de la aplicación si las versiones difieren y la nueva suma de verificación de la imagen verifica. Si la nueva imagen está dañada, simplemente ejecuta la aplicación anterior como antes.

He hecho muchos cargadores de arranque, y no hay dos iguales. No hay un gestor de arranque de propósito general, a pesar de lo que algunas de las compañías de microcontroladores quieren que creas. Cada dispositivo tiene sus propios requisitos y circunstancias especiales para tratar con el host. Estas son solo algunas de las configuraciones del cargador de arranque y, a veces, del cargador que he usado:

  1. Gestor de arranque básico. Este dispositivo tenía una línea en serie y se conectaría a un host y se encendería según sea necesario. El gestor de arranque se ejecutó desde el reinicio y envió algunas respuestas de solicitud de carga al host. Si el programa de carga se estaba ejecutando, respondería y enviaría una nueva imagen de la aplicación. Si no respondía dentro de 500 ms, el gestor de arranque se daría por vencido y ejecutaría la aplicación existente. Por lo tanto, para actualizar el firmware, primero tenía que ejecutar la aplicación de actualización en el host, luego conectar y encender el dispositivo.

  2. Programa de cargador de memoria. Aquí utilizamos el siguiente PIC de tamaño superior que tenía el doble de memoria de programa. La memoria del programa se dividió aproximadamente en el 49% de la aplicación principal, el 49% de la nueva imagen de la aplicación y el 2% del gestor de arranque. El gestor de arranque se ejecutará desde el reinicio y copiará la nueva imagen de la aplicación en la imagen de la aplicación actual en las condiciones adecuadas.

  3. Imagen EEPROM externa. Como # 2, excepto que se usó una EEPROM externa para almacenar la nueva imagen de la aplicación. En este caso, el procesador con más memoria también habría sido físicamente más grande y en una subfamilia diferente que no tenía la combinación de periféricos que necesitábamos.

  4. Cargador de arranque TCP. Este fue el más complejo de todos. Se usó un PIC 18F grande. El último 1/4 de memoria más o menos contenía el gestor de arranque, que tenía su propia copia completa de una pila de red TCP. El gestor de arranque se ejecutó desde el reinicio e intentó conectarse a un servidor de carga especial en un puerto conocido en una dirección IP configurada previamente. Esto fue para grandes instalaciones donde siempre había una máquina de servidor dedicada para todo el sistema. Cada pequeño dispositivo se registraría con el servidor de carga después del reinicio y se le daría una nueva copia de la aplicación, según corresponda. El gestor de arranque sobrescribirá la aplicación existente con la nueva copia, pero solo la ejecutará si la suma de comprobación está marcada. De lo contrario, volvería al servidor de carga e intentaría nuevamente.

    Dado que el gestor de arranque era en sí mismo un código complicado que contenía una pila de red TCP completa, también tenía que ser actualizable en campo. La forma en que lo hicimos fue hacer que el servidor de carga lo alimentara como una aplicación especial cuyo único propósito era sobrescribir el cargador de arranque una vez que se ejecutó, y luego reiniciar la máquina para que el nuevo cargador de arranque se ejecute, lo que haría que el servidor de carga envíe el última imagen de la aplicación principal. Técnicamente, una falla de energía durante los pocos milisegundos que tomó la aplicación especial para copiar una nueva imagen sobre el gestor de arranque sería una falla irrecuperable. En la práctica esto nunca sucedió. Estábamos de acuerdo con la muy improbable posibilidad de que eso ocurriera, ya que estos dispositivos eran partes de grandes instalaciones donde ya había personas que harían mantenimiento en el sistema, lo que ocasionalmente significaba reemplazar los dispositivos integrados por otras razones de todos modos.

Esperemos que pueda ver que hay una serie de otras posibilidades, cada una con sus propias compensaciones de riesgo, velocidad, costo, facilidad de uso, tiempo de inactividad, etc.

Olin Lathrop
fuente
1
Todos los AVR, excepto la familia Xmega (que tiene una nueva interfaz de 2 hilos) usan una interfaz SPI mientras se mantienen en el reinicio. Los más grandes también tienen JTAG, algunos tienen programación paralela, y los más pequeños pueden requerir alto voltaje si el reinicio se ha reconfigurado como E / S. Algunas MCU, como las familias Parallax Propeller y Motorola / Freescale 68HC08, no tienen hardware de programación mínimo sino cargadores de arranque en ROM.
Yann Vernier
Compara las versiones actuales y cargadas de la aplicación, verifica sus sumas de verificación y copia la nueva imagen en el área de la aplicación si las versiones difieren y la nueva suma de verificación de la imagen verifica. Sí, pero si el poder se interrumpe en medio de esta acción, habría una imagen corrupta en el "área de la aplicación". Supongo que puede ser mejor tener una aplicación bootloader-failsafe que escriba la nueva aplicación en el mcu flash y si la suma de comprobación es válida, también escriba en algún lugar "está bien para iniciar la nueva aplicación". Entonces, al inicio, verifica si está bien iniciar la nueva aplicación, si no es así, continúa ejecutándose (aplicación a prueba de fallas)
Ervadac
@Erv: Si la energía falla en el medio de copiar la nueva versión en la actual, la suma de verificación de la versión actual fallará cuando vuelva la energía y el gestor de arranque vuelva a funcionar. Por lo general, pongo la palabra de suma de verificación al final de la imagen para que cualquier escritura parcial tenga muy buenas posibilidades de fallar la suma de verificación.
Olin Lathrop
Hola. Puedo recomendarle el gestor de arranque tipo 5: en lugar de la pila TCP, puede implementar UDP. Luego use TFTP para descargar la actualización o el protocolo nativo.
i486
22

¿Cuál es el concepto del gestor de arranque?

Imagine este escenario: tiene una buena cantidad de almacenamiento en su microcontrolador, suficiente para almacenar más de 2-3 programas o aplicaciones que son independientes entre sí. Suponga que cuando inicia su dispositivo, es posible que desee elegir cuál ejecutar. Entonces, ¿qué necesitarías para apoyar esto? Necesitaría un programa de inicio que luego le permita elegir entre los demás en el momento del arranque.

¿Cómo funciona?

Un cargador de arranque es ese programa: es lo primero que se ejecuta y puede cargar otras aplicaciones en lugares específicos de la memoria (ya sea persistente como FLASH o volátil como RAM) y luego salta al programa deseado donde luego se hará cargo de la ejecución desde allí .

¿Cómo hacer un gestor de arranque avr (o para cualquier microcontrolador)?

Nunca he hecho un gestor de arranque, pero así es como creo que lo haría: comenzar a escribir un programa de firmware como lo haría normalmente, pero asegúrese de que esté ubicado en un área tal que siempre sea lo primero que se ejecute cuando El dispositivo arranca. Fuera de mi cabeza, algunas de las funcionalidades que quisiera de este pequeño programa: la capacidad de cargar un nuevo programa en un lugar disponible en la memoria, borrar un programa previamente cargado, elegir qué programa ejecutar (si hay más de uno), y tener algún tipo de estructura de datos de almacenamiento (¿tabla de salto capaz de crecer?) para poder recordar dónde están los otros programas y saltar a ellos. La interacción podría realizarse a través de UART, donde puede presentarle un menú de terminal muy simple y la capacidad de cargar firmware a través de ese mismo canal.

¿Cómo se programa en el microcontrolador (como cualquier programa .hex grabado en la memoria flash del avr, o algún otro método)?

Si es un chip completamente en blanco sin un gestor de arranque existente que pueda actualizarse a sí mismo, entonces necesitaría grabar en FLASH como lo describió utilizando cualquier técnica que se requiera para lograr eso (ICSP en el caso de AVR).

Esto de ninguna manera es exhaustivo de lo que son los "cargadores de arranque". Dependiendo de lo que desee de uno o del sistema para el que están diseñados, puede diseñar uno para cargar cosas a una ubicación especificada en RAM en lugar de FLASH, y comenzar la ejecución en cualquier ubicación de memoria arbitraria. O tal vez desee uno que sea capaz de elegir qué sistema operativo cargar cuando su PC se inicia (consulte grub por ejemplo). Los cargadores de arranque para microcontroladores de 8 bits tienden a ser muy simples.

Una nota sobre Arduino: este gestor de arranque solo administra un programa AFAIK, también toma el puerto serie para administrar la carga de firmware y otras cosas .

Jon L
fuente
Para su información, la respuesta se escribió para abordar los puntos originales que ahora se han editado.
Jon L
3

El concepto de un cargador de "arranque" es similar al concepto de "cebar" una bomba. En otras palabras, necesita "algo" que cargue un programa en una dirección determinada y luego comience a ejecutar el programa en esa dirección. Ese algo, es el gestor de arranque. En el caso más simple, el cargador de arranque "aparece" en la dirección de inicio designada de la CPU (cero, muy probablemente), carga el programa en el segmento de memoria requerido, le transfiere el control y "desaparece". La apariencia y desaparición están controladas por hardware "externo". Una posible implementación sería mediante el uso de una ROM que se activa a través de un reinicio de "hardware" y se desactiva con un reinicio de "software". El cargador en la ROM puede ser tan simple o complejo como sea necesario, y debe escribirse en forma binaria que comprenda la CPU en particular. Si no se necesita el espacio de direcciones utilizado por la ROM, no se requeriría la desactivación de la ROM. Obviamente, EEPROM, ePROM, flash PROM, etc. podrían usarse en lugar de la ROM.

Guill
fuente