Bootloader para PIC24EP?

2

Estoy trabajando en el gestor de arranque pic24EP. Mi cargador de arranque tiene su propio formato de paquete para comunicarse con un script de Python para actualizar el firmware del microcontrolador. El gestor de arranque se encuentra 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 script del enlazador de mi firmware de aplicación para que el archivo hexadecimal de la aplicación no use ningún espacio entre 0x200 y 0x005BF0. El script del enlazador del proyecto de aplicación se encuentra 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 cargador de arranque rechaza el firmware (archivo hexadecimal) en algún punto, ya que tiene una dirección entre 0x200 y 0x005BF0, pero he editado el script del vinculador de la aplicación para usar solo las direcciones por encima de 0x6000 mediante la modificación de variables: __CODE_LENGTH y programa.

El mapa de memoria de mi microcontrolador está abajo:

Eltamañodelflashesde256kByeltamañodelapáginaesde1024instrucciones(1024*4bytes).ElarchivoHexseencuentraen aquí . Y el script del enlazador se encuentra en aquí .

EDITAR: He solucionado mi problema. Parece que PIC utiliza un HEX File Format ligeramente diferente que INTEL . Las direcciones en el archivo HEX son 2 veces la dirección real en PIC . Por lo tanto, necesito 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. Entonces, lo estoy agregando aquí. Ahora, mi aplicación (bien probada) cargada a través del gestor de arranque funciona hasta que se enciende cualquier interrupción. Si alguna interrupción se dispara, se cuelga. Todo lo que puedo comprobar es que no termina en ninguna trampa. ¿Alguien puede indicarme la dirección correcta?

    
pregunta abhiarora

3 respuestas

2

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

  1. El primer error en mi gestor de arranque fue en la interpretación del formato de archivo HEX para los microcontroladores pic. %código%. Yo no sabía eso. Estaba usando esa dirección directamente sin dividirla. Por lo tanto, necesito dividir la dirección en un registro de archivo hexadecimal entre 2 y debo usar esa dirección para la imagen de programación.

  2. El segundo error fue al escribir el flash. Mi imagen ( The address field in the hex file is double that of the PIC device address ) solo admite la operación 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é algo de código en línea usándolo. Puedo escribir una sola instrucción al enmascarar la instrucción superior o inferior con una operación de escritura de flash de doble instrucción. El código que encontré está pegado a continuación:

    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;
     }
    
respondido por el abhiarora
2

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

Sus direcciones están comenzando en 0x0, no hay duda al respecto. Si su secuencia de comandos de Python está enviando ingenuamente los bytes a su mcu, de hecho enviará direcciones dentro del rango 0x200-0x005BF0. He adjuntado un fragmento de su archivo hex que ilustra que la dirección base del archivo hexadecimal es 0x0.

¿Apuntaste tu vinculador al archivo .ld correcto?

La solución rápida es simplemente ignorar estas direcciones fuera de los límites con su script de python. También puede ignorar los fuera de los límites en el lado del mcu, pero esto puede dar lugar a errores silenciosos y desagradables cuando no está totalmente actualizado.

Una solución más completa es averiguar por qué el script del enlazador no está haciendo lo que le estás diciendo. No estoy familiarizado con el lenguaje del enlazador de imágenes, pero he hecho algo similar con un núcleo Cortex M-0 y una cadena de herramientas GCC. Recomiendo encarecidamente buscar una guía. Su 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 fragmento de su archivo hex cargado, que ilustra el contenido en 0x200.  

Permaneceenblancohasta0xC000,dondeparecequeseinicialaaplicación:

EDITAR PARA RESPONDER A UNA PREGUNTA EDITADA:

Necesitas depurar este nuevo problema. Suena como si tu tabla vectorial estuviera dañada. Use una herramienta como MPLAB IPE para descargar el contenido flash de su MCU y verifique que su cargador de arranque mcu no esté haciendo nada tonto con sus tablas vectoriales.

    
respondido por el gregb212
1

Como otro método de solución de problemas para el cargador de arranque PIC, puede agregar el proyecto MPLABX del cargador de arranque como "cargable" de su proyecto de aplicación principal. El compilador luego le dará advertencias sobre cualquier superposición de memoria o conflicto según lo definan sus archivos de enlace individuales.

Para agregar un cargable, haga clic derecho en el proyecto de su aplicación y haga clic en Propiedades. En Conf / Loading selecciona tu proyecto de gestor de arranque.

    
respondido por el justing

Lea otras preguntas en las etiquetas