Forzar xc32-ld para colocar todo el código de la aplicación en kseg0_boot_mem

4

He escrito una aplicación de cargador de arranque PIC32MX. Me gustaría decirle al vinculador que lo ponga por completo en la memoria de arranque, para que se mantenga todo el espacio del programa para la aplicación final.

Actualmente, las partes que creo que son relevantes de mi archivo .ld tienen este aspecto:

_RESET_ADDR              = 0xBFC00000;  
_BEV_EXCPT_ADDR          = (0xBFC00000 + 0x380);
_DBG_EXCPT_ADDR          = (0xBFC00000 + 0x480);
_DBG_CODE_ADDR           = 0xBFC02000;
_DBG_CODE_SIZE           = 0xFF0     ;
_GEN_EXCPT_ADDR          = _ebase_address + 0x180;

MEMORY
{
  kseg0_program_mem    (rx)  : ORIGIN = 0x9D000000, LENGTH = 0x10000 /* All C Files will be located here */ 
  kseg0_boot_mem             : ORIGIN = 0x9FC00000, LENGTH = 0x1000 /* This memory region is dummy */ 
  exception_mem              : ORIGIN = 0x9FC01000, LENGTH = 0x200 /* Interrupt vector table */
  config3                    : ORIGIN = 0xBFC02FF0, LENGTH = 0x4
  config2                    : ORIGIN = 0xBFC02FF4, LENGTH = 0x4
  config1                    : ORIGIN = 0xBFC02FF8, LENGTH = 0x4
  config0                    : ORIGIN = 0xBFC02FFC, LENGTH = 0x4
  kseg1_boot_mem             : ORIGIN = 0xBFC00000, LENGTH = 0x2FF0 /* C Startup code */
  kseg1_data_mem       (w!x) : ORIGIN = 0xA0000000, LENGTH = 0x8000
  sfrs                       : ORIGIN = 0xBF800000, LENGTH = 0x100000
  debug_exec_mem             : ORIGIN = 0xBFC02000, LENGTH = 0xFF0
  configsfrs                 : ORIGIN = 0xBFC02FF0, LENGTH = 0x10
}

Este es el script de vinculador generado por defecto, para un PIC32MX695F512H , aunque la longitud de algunos Es posible que las secciones hayan cambiado: el diseño de la memoria del chip se encuentra en la página 61 de la hoja de datos.

¿Debería simplemente cambiar los valores de ORIGIN y LENGTH de kseg0_program_mem a los valores de kseg0_boot_mem y decirle al vinculador que permita la superposición de secciones? Eso no se siente tan limpio. ¿Hay alguna manera de decirle al vinculador que ponga el código de la aplicación no en kseg0_program_mem sino en kseg0_boot_mem ?

    
pregunta Keelan

2 respuestas

4

El compilador de C colocará el código de inicio de C-runtime en el kseg0_boot_mem , que configura la pila, el montón y la inicialización general del procesador. La cantidad de código colocado en kseg0_boot_mem variará entre una depuración y una versión de lanzamiento. Si recuerdo correctamente, cuando estaba trabajando en un cargador de arranque para un PIC32MX250F, la compilación de depuración ocupó ~ 70% del kseg0_boot_mem , lo cual no fue suficiente para mi cargador de arranque.

Si su gestor de arranque es lo suficientemente pequeño como para caber en el kseg0_boot_mem junto con el código de inicio de C, reduzca el tamaño del kseg0_boot_mem y luego reubique kseg0_program_mem por encima del nuevo espacio boot_mem . Tenga en cuenta que no puede mover la ubicación inicial del espacio kseg0_boot_mem . La ejecución del código comienza en 0xBFC00000 en el PIC32, y no hay nada que puedas hacer para cambiar eso. Si desea mover el gestor de arranque completo , también deberá mover la tabla ISR. Por ejemplo:

MEMORY
{
  kseg0_program_mem    (rx)  : ORIGIN = 0xBFC01200, LENGTH = 0x1DF0 /* kseg1_boot is 2FF0 long.*/ 
  kseg0_boot_mem             : ORIGIN = 0x9FC00000, LENGTH = 0x1000 /* This memory region is dummy */ 
  exception_mem              : ORIGIN = 0xBFC01000, LENGTH = 0x200 /* Relocated ISR table. */
  config3                    : ORIGIN = 0xBFC02FF0, LENGTH = 0x4
  config2                    : ORIGIN = 0xBFC02FF4, LENGTH = 0x4
  config1                    : ORIGIN = 0xBFC02FF8, LENGTH = 0x4
  config0                    : ORIGIN = 0xBFC02FFC, LENGTH = 0x4
  kseg1_boot_mem             : ORIGIN = 0xBFC00000, LENGTH = 0x1000 /*This has been reduced in size.  Was 0x2FF0*/

  kseg1_data_mem       (w!x) : ORIGIN = 0xA0000000, LENGTH = 0x8000
  sfrs                       : ORIGIN = 0xBF800000, LENGTH = 0x100000
  debug_exec_mem             : ORIGIN = 0xBFC02000, LENGTH = 0xFF0
  configsfrs                 : ORIGIN = 0xBFC02FF0, LENGTH = 0x10
}

NOTA: esto es solo un script de muestra del gestor de arranque, ¡y de ninguna manera debe copiarse y pegarse en producción!

Dicho esto, puedo hablar por experiencia que tratar de meter un cargador de arranque no trivial en el espacio del programa boot_mem no funciona. El espacio restante del código de inicio de C por lo general no es suficiente, especialmente si desea un gran manejo de errores y validación (y sí, ¡QUIERE esto!). La eliminación de las compilaciones de depuración del arsenal muy limitado de herramientas de depuración incrustadas tampoco es buena. Deberá poder depurar el hardware en algún momento en el futuro. Aprendí esa lección de la manera más difícil.

Mi recomendación es dejar la sección de código kseg0_boot_mem sola y solo trabajar con el espacio kseg0_program_mem . Toma un trozo de kseg0_program_mem en la parte superior o inferior (no importa) y úsalo para el código de tu cargador de arranque y la tabla ISR. Déjate un poco de espacio para el crecimiento del código del bootloader también. Tratar con múltiples scripts de enlazadores es un poco molesto.

    
respondido por el CHendrix
2

En lugar de hacerlo todo en el enlazador, también puedes hacerlo de forma similar a esta

MEMORY
{
  kseg0_program_mem    (rx)  : ORIGIN = 0x9D000000, LENGTH = 0x5000
  bootverify_mem       (rx)  : ORIGIN = 0x9D03FFAC, LENGTH = 0x50
  kseg0_boot_mem             : ORIGIN = 0x9FC00490, LENGTH = 0xB70
  exception_mem              : ORIGIN = 0x9FC01000, LENGTH = 0x300
  kseg2_boot_mem             : ORIGIN = 0x9FC01380, LENGTH = 0xC80
  kseg1_boot_mem             : ORIGIN = 0xBFC00000, LENGTH = 0x490
  debug_exec_mem             : ORIGIN = 0xBFC02000, LENGTH = 0xFF0
  config3                    : ORIGIN = 0xBFC02FF0, LENGTH = 0x4
  config2                    : ORIGIN = 0xBFC02FF4, LENGTH = 0x4
  config1                    : ORIGIN = 0xBFC02FF8, LENGTH = 0x4
  config0                    : ORIGIN = 0xBFC02FFC, LENGTH = 0x4
  kseg1_data_mem       (w!x) : ORIGIN = 0xA0000000, LENGTH = 0x10000
  sfrs                       : ORIGIN = 0xBF800000, LENGTH = 0x100000
  configsfrs                 : ORIGIN = 0xBFC02FF0, LENGTH = 0x10
}



SECTIONS
{
  .config_BFC02FF0 0xBFC02FF0 : {
    KEEP(*(.config_BFC02FF0))
  } > config3
  .config_BFC02FF4 : {
    KEEP(*(.config_BFC02FF4))
  } > config2
  .config_BFC02FF8 : {
    KEEP(*(.config_BFC02FF8))
  } > config1
  .config_BFC02FFC : {
    KEEP(*(.config_BFC02FFC))
  } > config0
}

PROVIDE(_DBG_CODE_ADDR = 0xBFC02000) ;
PROVIDE(_DBG_CODE_SIZE = 0xFF0) ;
SECTIONS
{

  .extra_prgm_mem :
  {
    *(extra_prgm_mem)
  } >kseg0_boot_mem

  .extra_prgm_mem2 :
  {
    KEEP(*(extra_prgm_mem2))
  } >kseg2_boot_mem
/*Linker continued*/

Luego, en su código, puede colocar cada función donde desee.

int  __attribute__ ((section ("extra_prgm_mem2")))GetVersion(char * Info){
    int Result = (Info[4] - '0') *  1000;
    Result += ((Info[5] - '0') *  100);
    Result += ((Info[6] - '0') *  10);
    Result += Info[7] - '0';
}

BOOL __attribute__ ((section ("extra_prgm_mem")))BLMedia_LoadEncryptedFile(char *file_name) {
//Function info
}

Además, tenga en cuenta que si no usa ninguna interrupción, puede obtener otro 0x1000 en el espacio. Por cierto, si este no es un gestor de arranque serie, no lo veo apropiado.

    
respondido por el Erik Friesen

Lea otras preguntas en las etiquetas