4 votos

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

He escrito una aplicación de bootloader para PIC32MX. Me gustaría decirle al enlazador que la ponga completamente en la memoria de arranque, para que todo el espacio de programa se mantenga para la aplicación final.

Actualmente, las que creo que son las partes relevantes de mi .ld archivo se vea así:

_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 linker generado por defecto script, para un PIC32MX695F512H Aunque la longitud de algunas secciones puede haber cambiado, la disposición de la memoria del chip se encuentra en la página 61 de la hoja de datos.

¿Debo simplemente cambiar el ORIGIN y LENGTH de kseg0_program_mem a los valores de kseg0_boot_mem y decirle al enlazador que permita la superposición de secciones? Eso no parece tan limpio. ¿Hay alguna manera de decirle al enlazador que ponga el código de la aplicación no en kseg0_program_mem pero en kseg0_boot_mem ?

0 votos

Acabo de leer sobre esto en este libro electrónico - No puedo responder yo mismo, pero echa un vistazo a la página 44 y puede haber información útil.

0 votos

Justo debajo de eso probablemente tienes algo como ".text ORIGIN(kseg0_program_mem) :" que le dice al enlazador que cualquier cosa en la sección .text debe estar ubicada en el segmento kseg0_program_mem. Esto no es algo que haya probado, pero probablemente podrías cambiar eso por kseg0_boot_mem en su lugar...

0 votos

Entiendo que se pregunte aquí, pero hay gente bastante decente en el foro de pic32 que entiende bien de linkers.

4voto

CHendrix Puntos 56

El compilador de C colocará el código de inicio del tiempo de ejecución de C en el archivo 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 compilación de depuración y una de lanzamiento. Si no recuerdo mal, cuando trabajaba en un gestor de arranque para un PIC32MX250F, la compilación de depuración ocupaba el 70 % del tiempo. kseg0_boot_mem que no era suficiente para mi gestor 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 en C, reducen el tamaño del kseg0_boot_mem y luego reubicar kseg0_program_mem por encima del nuevo boot_mem espacio. Tenga en cuenta que no puede mover la ubicación inicial del kseg0_boot_mem espacio. La ejecución del código comienza en 0xBFC00000 en el PIC32, y no hay nada que puedas hacer para cambiar eso. Si quieres mover el todo bootloader, también tendrás que 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 sólo un ejemplo de bootloader script, y de ninguna manera debe ser copiado en producción!

Dicho esto, puedo hablar por experiencia de que intentar meter un gestor de arranque no trivial en el boot_mem el espacio del programa no funciona. El espacio que queda del código de inicio en C no suele ser suficiente, especialmente si se desea un manejo y validación de errores pesados (¡y sí, se desea esto!). Eliminar las construcciones de depuración del muy limitado arsenal de herramientas de depuración embebidas tampoco es bueno. Usted tendrá que ser capaz de depurar en el hardware en algún momento en el futuro. Yo aprendí esa lección de la manera más difícil.

Mi recomendación es dejar el kseg0_boot_mem sección de código solo, y solo trabajar con el kseg0_program_mem espacio. Coge un trozo de la kseg0_program_mem en la parte superior o inferior (no importa) y utilizarlo para el código del cargador de arranque y la tabla de ISR. Deja algo de espacio para el crecimiento del código del cargador de arranque también. Tratar con múltiples scripts del linker es un poco de dolor.

1voto

Ranjit Puntos 51

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

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 tu código, puedes ir poniendo cada función donde quieras.

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, ten en cuenta que si no utilizas ninguna interrupción, puedes ganar otros 0x1000 de espacio. BTW, si esto no es un gestor de arranque en serie, no veo que encaje.

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