2 votos

¿Cargador de arranque para PIC24EP?

Estoy trabajando en el cargador de arranque pic24EP. Mi gestor de arranque tiene su propio formato de paquete para comunicarse con un script de python para actualizar el firmware del microcontrolador. El bootloader reside en la primera página libre después de la tabla de vectores de interrupción (0x000800). Para hacer espacio para la aplicación, he editado el linker script de mi aplicación firmware para que el archivo hexadecimal de la aplicación no utilice ningún espacio entre 0x200 y 0x005BF0. El linker script del proyecto de aplicación se da a continuación:

/*
** Memory Regions
*/
MEMORY
{
  data  (a!xr)   : ORIGIN = 0x1000,        LENGTH = 0x8000
  reset          : ORIGIN = 0x0,           LENGTH = 0x4
  ivt            : ORIGIN = 0x4,           LENGTH = 0x1FC
  program (xr)   : ORIGIN = 0x6000,        LENGTH = 0x23FFE
  FICD           : ORIGIN = 0x2AFF0,       LENGTH = 0x2
  FPOR           : ORIGIN = 0x2AFF2,       LENGTH = 0x2
  FWDT           : ORIGIN = 0x2AFF4,       LENGTH = 0x2
  FOSC           : ORIGIN = 0x2AFF6,       LENGTH = 0x2
  FOSCSEL        : ORIGIN = 0x2AFF8,       LENGTH = 0x2
  FGS            : ORIGIN = 0x2AFFA,       LENGTH = 0x2
  FUID0          : ORIGIN = 0x800FF8,      LENGTH = 0x2
  FUID1          : ORIGIN = 0x800FFA,      LENGTH = 0x2
  FUID2          : ORIGIN = 0x800FFC,      LENGTH = 0x2
  FUID3          : ORIGIN = 0x800FFE,      LENGTH = 0x2
}

__FICD = 0x2AFF0;
__FPOR = 0x2AFF2;
__FWDT = 0x2AFF4;
__FOSC = 0x2AFF6;
__FOSCSEL = 0x2AFF8;
__FGS = 0x2AFFA;
__FUID0 = 0x800FF8;
__FUID1 = 0x800FFA;
__FUID2 = 0x800FFC;
__FUID3 = 0x800FFE;
__CODE_BASE = 0x6000;
__CODE_LENGTH = 0x23FFE;
__IVT_BASE  = 0x4;

__DATA_BASE = 0x1000;
__DATA_LENGTH = 0x8000;

Parece que mi gestor de arranque rechaza el firmware (archivo hexadecimal) en algún momento, ya que tiene la dirección en entre 0x200 y 0x005BF0 pero he editado la aplicación linker script para utilizar sólo las direcciones por encima de 0x6000 mediante la modificación de las variables: __CODE_LENGTH y programa.

El mapa de memoria de mi micro-controlador es el siguiente:

Memory Map Image

El tamaño de flash es de 256kB y el tamaño de página es de 1024 instrucciones (1024*4 Bytes). El archivo hexadecimal es de más de ici . Y la secuencia de comandos del enlazador ha terminado ici .

EDITAR: He resuelto mi problema. Parece que PIC utiliza un ligeramente diferente HEX File Format que INTEL . Las direcciones en el archivo HEX son 2 veces la dirección real en PIC . Por lo tanto, tengo que dividir la dirección en el archivo hexadecimal por 2 para obtener la dirección flash del microcontrolador PIC.

Sin embargo, he identificado un nuevo problema con mi sistema. No puedo publicar una nueva pregunta. Por lo tanto, estoy añadiendo aquí. Ahora, mi aplicación (bien probado) cargado a través de bootloader funciona hasta que cualquier interrupción se dispara. Si cualquier interrupción se dispara, se cuelga. Todo lo que puedo comprobar es que no termina en ninguna trampa. ¿Puede alguien indicarme la dirección correcta?

2voto

dast Puntos 41

He completado con éxito bootloader para pic24EP256GP204 . Hubo dos problemas con mi cargador de arranque:

  1. El primer error en mi gestor de arranque fue en la interpretación de HEX formato de archivo para microcontroladores pic. The address field in the hex file is double that of the PIC device address . No lo sabía. Estaba usando esa dirección directamente sin dividirla. Por lo tanto, tengo que dividir la dirección en un registro de archivo hexadecimal por 2 y debe utilizar esa dirección para la programación de pic.

  2. El segundo fallo fue al escribir el flash. Mi foto ( pic24ep256gp204 ) sólo admite operaciones de escritura flash de doble instrucción. Estaba cometiendo un pequeño error al escribir las instrucciones si necesitamos escribir una sola instrucción. Encontré un código en línea usándolo puedo escribir una sola instrucción enmascarando la instrucción superior o inferior con una operación de escritura flash de doble instrucción. El código que encontré está pegado abajo:

    unsigned NVMemWriteWord(uint32_t address, uint32_t data)
    {
    DWORD_VAL writeAddress;
    DWORD_VAL writeData;
    
    writeAddress.Val = address;
    writeData.Val = data;
    
    NVMCON = 0x4001;        //Perform WORD write next time WR gets set = 1.
    NVMADRU = writeAddress.word.HW;
    NVMADR = writeAddress.word.LW;
    
    // Set the table address of "Latch". The data is programmed into the FLASH from a temporary latch. 
    TBLPAG = 0xFA;
    //The smallest block of data that can be programmed in
    //a single operation is 2 instruction words (6 Bytes + 2 Phantom Bytes).
    // Mask the high or low instruction words depending on the address and write either high or low instruction word.
    if(address % 4)
    {
        __builtin_tblwtl(0, 0xFFFF);                //Mask the low word of 1-st instruction into the latch.
        __builtin_tblwth(1, 0x00FF);                //Mask the high word of 1-st instruction into the latch. (8 bits of data + 8 bits of "phantom data" (phantom byte is always 0))
    
        __builtin_tblwtl(2, writeData.word.LW);     //Write the low word of 2-nd instruction into the latch
        __builtin_tblwth(3, writeData.word.HW);     //Write the high word of 2-nd instruction into the latch        
    
    }
    else
    {
        __builtin_tblwtl(0, writeData.word.LW);     //Write the low word of 1-st instruction into the latch
        __builtin_tblwth(1, writeData.word.HW);     //Write the high word of 1-st instruction into the latch 
        __builtin_tblwtl(2, 0xFFFF);                //Mask the low word of 2-nd instruction into the latch.
        __builtin_tblwth(3, 0x00FF);                //Mask the high word of 2-nd instruction into the latch. (8 bits of data + 8 bits of "phantom data" (phantom byte is always 0))
    
    }       
    
    INTCON2bits.GIE = 0;                            //Disable interrupts for next few instructions for unlock sequence
    __builtin_write_NVM();
    while(NVMCONbits.WR == 1){}
    INTCON2bits.GIE = 1;                            // Re-enable the interrupts (if required).
    
    // Return WRERR state.
    return NVMCONbits.WRERR;
     }

1voto

U85 Puntos 46

Más o menos ampliando mi comentario aquí. No estoy 100%, pero el formato hexadecimal parece ser intelhex. Estoy usando el visor hexadecimal proporcionado por el programa Segger JFlash para ver el contenido del archivo hexadecimal.

Tus direcciones empiezan en 0x0, no hay duda. Si tu script python está enviando ingenuamente los bytes a tu mcu, entonces enviará direcciones dentro del rango 0x200-0x005BF0. He adjuntado un recorte de su archivo hexadecimal que ilustra que la dirección base del archivo hexadecimal es 0x0.

¿Apuntaste tu enlazador al archivo .ld correcto?

La solución rápida es simplemente ignorar estas direcciones fuera de límites con su script python. También podrías ignorar los "out-of-bounds" en el lado de la mcu, pero esto podría llevar a errores silenciosos cuando no está completamente flasheada.

Una solución más completa es averiguar por qué el script enlazador no está haciendo lo que le estás diciendo. No estoy familiarizado con el lenguaje linker de pic, pero he hecho algo similar con un núcleo Cortex M-0 y una cadena de herramientas GCC. Te recomiendo encarecidamente que busques una guía. Tu caso de uso no es inusual y estoy seguro de que está documentado. Me disculpo por no poder ofrecer más orientación, pero un rápido google de "pic bootloader linker script" produjo algunos resultados prometedores.

Un recorte de su archivo hexadecimal Snip of hex file demonstrating base address at 0x0

Permanece en blanco hasta 0xC000, donde aparece que se inicia la aplicación: enter image description here

EDITAR PARA RESPONDER A LA PREGUNTA EDITADA:

Tienes que depurar este nuevo problema. Parece que tu tabla de vectores está corrupta. Utilice una herramienta como MPLAB IPE para descargar el contenido de la flash de su MCU y verificar que el gestor de arranque mcu no está haciendo nada tonto a sus tablas de vectores.

1voto

Konstantin Puntos 64

Como otro método de solución de problemas para PIC bootloader's, puede agregar el proyecto MPLABX bootloader como un "loadable" de su proyecto de aplicación principal. El compilador te avisará entonces de cualquier solapamiento de memoria o conflicto definido por tus archivos linker individuales.

Para añadir un cargador, haz clic con el botón derecho del ratón en el proyecto de tu aplicación y haz clic en propiedades. En Conf/Carga selecciona tu proyecto de cargador de arranque.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X