Actualice la aplicación de usuario utilizando un cargador de arranque personalizado a través de UART (STM32)

Estoy usando una placa STM32L4 y mi memoria flash se ve así:

|______________
|
| Solicitud de USUARIO
|
|
|______________
|Tabla de vectores(UA)
|______________ 0x8000 - 8000
|
| Cargador de arranque personalizado
|
|
|______________
|Tabla de vectores(BL)
|______________ 0x8000 - 0000

Mi placa está conectada a otra placa mediante UART (definamos la otra placa como maestra y mi placa como esclava).
La placa maestra podrá actualizar la aplicación de usuario de la placa esclava a través de UART. La idea es enviar un archivo binario a través de UART y escribirlo en la sección de la aplicación de usuario.

De acuerdo con la nota de aplicación de ST, hay un comando llamado comando Escribir memoria:

El comando Escribir memoria se usa para escribir datos en cualquier dirección de memoria válida (consulte la nota a continuación), es decir, RAM, memoria flash, área de bytes de opciones.
Cuando el cargador de arranque recibe el comando Escribir memoria, transmite el byte ACK a la aplicación. Después de la transmisión del byte ACK, el cargador de arranque espera una dirección (4 bytes, el byte 1 es la dirección MSB y el byte 4 es el LSB) y un byte de suma de verificación, luego verifica la dirección recibida. Para el área de bytes de opción, la dirección de inicio debe ser la dirección base del área de bytes de opción (ver nota) para evitar escribir inoportunamente en esta área.

si la dirección recibida es válida y la suma de verificación es correcta, el gestor de arranque transmite un byte ACK; de lo contrario, transmite un byte NACK y aborta el comando. Cuando la dirección es válida y la suma de comprobación es correcta, el gestor de arranque:

• obtiene un byte, N, que contiene el número de bytes de datos que se recibirán

• recibe los datos del usuario ((N + 1) bytes) y el checksum (XOR de N y de todos los bytes de datos)

• programa los datos del usuario en la memoria a partir de la dirección recibida

• al final del comando, si la operación de escritura fue exitosa, el gestor de arranque transmite el byte ACK; de lo contrario, transmite un byte NACK a la aplicación y aborta el comando

• La longitud máxima del bloque a escribir para el STM32 es de 256 bytes

Esto significa que solo puedo actualizar 256 bytes mediante un paquete proveniente de la placa maestra a la placa esclava.

Ahora digamos que la placa maestra tiene una tarjeta SD que contiene un archivo binario y quiero mostrar este archivo en la sección de la aplicación del usuario. ¿Cómo puedo hacer esto? ¿Debería leer el archivo binario y enviar una serie de 256 bytes, cada 256 en un paquete?

Respuestas (2)

Sí. Obviamente, puede enviar varios paquetes.

Existe una compensación entre la eficiencia y el costo de obtener un paquete incorrecto. Con paquetes pequeños, hay más sobrecarga total por la cantidad de datos realmente entregados. Sin embargo, si hay un error, habrá que volver a enviar menos datos.

Dicho todo esto, los errores de datos son, o al menos deberían ser, raros. Por lo general, envía paquetes de tamaño máximo hasta que queda menos de un paquete completo de datos.

Su algoritmo de suma de comprobación es más bien una broma, digamos "primitivo" en el mejor de los casos. Los paquetes más pequeños tienen más protección de suma de verificación porque efectivamente hay más bits de suma de verificación por bit de datos.

Por supuesto, no está atascado con este gestor de arranque. Puedes escribir uno que haga lo que quieras. Consulte esta pregunta para obtener más información sobre los gestores de arranque en general.

Más sobre la verificación

Como señaló Peter en un comentario, la exactitud de los datos es esencial en un gestor de arranque.

Ese es un buen argumento para deshacerse de este gestor de arranque y su algoritmo de suma de comprobación ridículamente ingenuo. Lo que suelo hacer es ni siquiera intentar hacer una suma de comprobación de los paquetes individuales. Diseño el protocolo para una eficiencia razonable, pero agrego una buena suma de verificación a toda la imagen.

Comunicar los datos del host al dispositivo es solo una parte del problema. Luego tiene que escribirse correctamente en la memoria no volátil. Eso es en realidad mucho más probable que falle. Una falla de energía, o que el usuario presione el botón de reinicio en un mal momento puede causar corrupción, por ejemplo.

Mi estrategia generalmente es no preocuparme por los posibles errores en los pasos individuales del proceso, sino verificar el resultado final. Por lo general, coloco algo como una suma de verificación CRC de 24 o 32 bits al final de la imagen cargada. Antes de que el cargador de arranque ejecute la aplicación principal, verifica la suma de verificación. Si falla, solicita una nueva imagen, ejecuta la imagen anterior, indica un error o algo así. Nunca ejecute una imagen corrupta.

De un comentario:

El archivo binario contiene un firmware (algunos .c y .h y bibliotecas generadas con un IDE integrado como Keil). ¿Cómo agregar esta suma de verificación a la imagen en sí? ¿Es seguro modificar un archivo de este tipo?

No, el archivo binario no contiene ningún archivo .c ni .h. Es un archivo binario . Debe dar un paso atrás y aprender qué hacen cada uno el compilador, el bibliotecario y el enlazador, y qué tipo de información hay en los distintos tipos de archivos. No puede desarrollar código en el que está cerca del hardware sin comprender estas cosas.

Agregar la suma de verificación al archivo binario (a menudo en formato Intel Hex) es una forma de agregar una suma de verificación a la imagen. Podría escribir una herramienta separada que se ejecute después del enlazador. Esta herramienta lee la imagen, calcula la suma de verificación y la vuelve a incrustar en la imagen en un lugar conocido.

Otra forma es hacer que el programa de carga agregue la suma de verificación sobre la marcha. El cargador lee el archivo binario no modificado y agrega la suma de verificación en las ubicaciones conocidas, generalmente los últimos bytes de la imagen. Esta imagen modificada luego se envía al cargador de arranque, pero el archivo binario nunca se modifica.

la eficiencia no es el problema principal cuando actualiza el firmware. La exactitud de los datos es
Corrígeme si me equivoco, tomo la imagen binaria, la envío paquete por paquete hasta la última parte. Una vez que termino, envío un CRC de 32 bits del archivo binario y compruebo si es el mismo que el calculado en mi placa.
Siempre puede verificar la corrección leyendo los datos programados. Esto también verificaría los errores de programación flash, en lugar de solo verificar la comunicación. Definitivamente seguiría usando el gestor de arranque de ROM, porque permanecerá disponible incluso si de alguna manera borras accidentalmente todo el flash.
@Pryda: creo que es mejor incrustar una suma de verificación directamente en la imagen cargada. De esa manera, siempre se puede verificar la corrección de la imagen, no solo en el momento en que el cargador de arranque se comunica con el host.
Olaf. Por lo general, implemento el doble control. La suma de comprobación de la imagen es una parte de la imagen. La suma de verificación de la transmisión es algo encima. Por lo general (en realidad siempre hoy en día) también cifro la imagen.
¿Es normal meterse con un archivo binario generado? El archivo binario contiene un firmware (algunos .c y .h y bibliotecas generadas con un IDE integrado como Keil). ¿Cómo agregar esta suma de verificación a la imagen en sí? ¿Es seguro modificar un archivo de este tipo?

Quiere escribir su propio gestor de arranque, pero cita la nota de la aplicación para el integrado. Olvídate de este.

Escriba el cargador de arranque y lea solo el Manual de referencia. Olvídese del bootlader incorporado y sus "comandos"