Estoy trabajando en un proyecto de firmware en el que tengo que hacer una verificación crc16 para la integridad del flash.
Controlador: MSP430 IDE: IAR EW 5.40 (Linker Xlink)
El crc se calcula utilizando el enlazador IAR Xlink y se mantiene al final del flash. Nuevamente, crc se calcula en tiempo de ejecución a partir del código y se compara con el valor almacenado en la memoria flash para verificar la integridad. Sin embargo, solo podemos calcular crc en el segmento de código de la memoria flash. Su tamaño puede cambiar cada vez que hacemos algunos cambios en el código. ¿Puedo automatizar este proceso que estoy haciendo manualmente en este momento?
del archivo del enlazador .xcl:
// ---------------------------------------------------------
// CRC16 Essentials: -H for fill,-J for checksum calculation
// ---------------------------------------------------------
-HFF
-J2,crc16,,,CHECKSUM2,2=(CODE)5C00-FF7F;(CODE)10000-0x20A13
Aquí necesito cambiar el valor final del segundo segmento de código que es 0x20A13 en este momento. Obtengo este valor del archivo .map, es decir, en cuánto rango de memoria reside mi código dentro del flash. Este es el 1er cambio que hago.
Aquí necesito hacer el segundo cambio del código:
sum = fast_crc16(sum, 0x5C00, 0xFF7F-0x5C00+1);
sum = fast_crc16(sum, 0x10000,0x20A13-0x10000+1);
//Check the crc16 values
if(sum != __checksum)
{
// Action to be taken if checksum doesn't match
}
¡Por favor ayuda a automatizar este proceso!
No conozco su enlazador, pero el enlazador gcc puede PROPORCIONAR una etiqueta, cuya dirección se puede usar en el código. Esta función se usa comúnmente para informar al código de inicio sobre el inicio y el final de los segmentos de DATOS y BSS, de modo que el BSS se pueda borrar y los DATOS (en la RAM) se puedan inicializar desde su copia en la ROM.
Fragmento de un linkerscript (LPC1343) que uso:
.text :
{
. = ALIGN(4);
__text_start = .;
PROVIDE(__text_start = __text_start);
// all text segments are listed here
. = ALIGN(4);
__text_end = .;
PROVIDE(__text_end = __text_end);
} > rom
La etiqueta __text_end estará en la dirección más allá del texto. Se puede utilizar en el código para el cálculo de CRC.
Dos comentarios:
Dices que revisas el segmento del código. ¿Comprueba también el segmento de DATOS (valores globales inicializados)?
Si me asignaran esta tarea, consideraría organizar las cosas para que las ubicaciones de flash no utilizadas se llenen con un valor conocido y organizar la suma de comprobación sobre el flash total.
Estoy usando EW8051, pero también usa Xlink. Hay dos tamaños a tener en cuenta: uno es el tamaño del segmento CÓDIGO, que generalmente no cambiará; y el otro es el tamaño que ocupa su código, que variará (generalmente crecerá) a medida que actualice su programa y compile el enlace.
Por ejemplo, aquí, desde mi archivo .xcl del enlazador, puede ver que el tamaño del segmento CÓDIGO es 0x8000:
/
// CODE
// ----
-D_CODE0_START=0x000000
-D_CODE0_END=0x007FFF // CC1111F32 has 32 kB code (flash)
Sin embargo, la parte de eso que realmente usa mi código se incluye en el archivo .map:
30 739 bytes of CODE memory
Mirando la sección de cálculo de la suma de verificación de la Guía de referencia de herramientas de biblioteca y enlazador IAR , parece que normalmente le indicaría al enlazador que calcule la suma de verificación en todo el segmento de CÓDIGO (todos los 0x8000 bytes en mi caso). Este es el código de ejemplo que proporcionan:
Calculating a checksum in your source code
This source code gives an example of how the checksum can be calculated:
/* Start and end of the checksum range */
/* Must exclude the checksum itself */
unsigned long ChecksumStart = 0x8000+2;
unsigned long ChecksumEnd = 0x8FFF;
/* The checksum calculated by XLINK */
extern unsigned short __checksum;
void TestChecksum()
{
unsigned short calc = 0;
/* Run the checksum algorithm */
calc = slow_crc16(0,
(unsigned char *) ChecksumStart,
(ChecksumEnd - ChecksumStart+1));
/* Rotate out the answer */
unsigned char zeros[2] = {0, 0};
calc = slow_crc16(calc, zeros, 2);
/* Test the checksum */
if (calc != __checksum)
{
abort(); /* Failure */
}
}
Las direcciones de inicio y finalización me sugieren fuertemente que la suma de verificación se calculará sobre todo el segmento.
Al documentar el indicador -J, la referencia indica " Nota : si no especifica ningún rango explícitamente, todos los bytes en la aplicación final se incluyen en el cálculo". Admito que hay cierta ambigüedad en lo que significa "todos los bytes": el segmento CÓDIGO completo, o solo la parte utilizada.
Por supuesto, la única forma en que este esquema puede funcionar sería si los bytes no utilizados en el segmento CODE se inicializaran en cero. Deberías verificar esto. :^)
En resumen: use el indicador -J para verificar la suma de todo el segmento CODE, haga lo mismo en su código y vea si funciona (después de verificar con el depurador, por ejemplo, que la parte no utilizada del segmento CODE no está lleno de basura ).
OnkarK
Wouter van Ooijen
OnkarK
Wouter van Ooijen