Таблица векторов файла компоновщика для настройки загрузчика - PullRequest
1 голос
/ 05 ноября 2019

В настоящее время я пытаюсь использовать приложение начального загрузчика, созданное с помощью MCUXPresso, которое требует, чтобы начальный адрес моего приложения находился в 0x80000. Согласно следующей документации: enter image description here

Однако генерируемый .bin, который я создаю, создается в Kinetis Design Studio (более ранняя версия MCUXpresso) и не имеет возможности изменятьТаблицу векторов таким простым способом, как в MCUXPresso. Я пытался изменить файл компоновщика вручную, выполнив следующие действия:

ENTRY(Reset_Handler)

    /* Original Memory Map */
MEMORY
{
  m_interrupts          (RX)  : ORIGIN = 0x00000000, LENGTH = 0x00000400
  m_flash_config        (RX)  : ORIGIN = 0x00000400, LENGTH = 0x00000010
  m_text                (RX)  : ORIGIN = 0x00000410, LENGTH = 0x001FFBF0
  m_data                (RW)  : ORIGIN = 0x1FFF0000, LENGTH = 0x00030000
  m_data_2              (RW)  : ORIGIN = 0x20000000, LENGTH = 0x00030000
}

/* Modified Memory Map */

MEMORY
{
  m_interrupts          (RX)  : ORIGIN = 0x00080000, LENGTH = 0x00000400
  m_flash_config        (RX)  : ORIGIN = 0x00080400, LENGTH = 0x00000010
  m_text                (RX)  : ORIGIN = 0x00080410, LENGTH = 0x001FFBF0
  m_data                (RW)  : ORIGIN = 0x1FFF0000, LENGTH = 0x00030000
  m_data_2              (RW)  : ORIGIN = 0x20000000, LENGTH = 0x00030000
}

/* rest of linker file */
/* Define output sections */
SECTIONS
{
  /* The startup code goes first into internal flash */
  .interrupts :
  {
    __VECTOR_TABLE = .;
    . = ALIGN(4);
    KEEP(*(.isr_vector))     /* Startup code */
    . = ALIGN(4);
  } > m_interrupts

  .flash_config :
  {
    . = ALIGN(4);
    KEEP(*(.FlashConfig))    /* Flash Configuration Field (FCF) */
    . = ALIGN(4);
  } > m_flash_config

  /* The program code and other data goes into internal flash */
  .text :
  {
    . = ALIGN(4);
    *(.text)                 /* .text sections (code) */
    *(.text*)                /* .text* sections (code) */
    *(.rodata)               /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)              /* .rodata* sections (constants, strings, etc.) */
    *(.glue_7)               /* glue arm to thumb code */
    *(.glue_7t)              /* glue thumb to arm code */
    *(.eh_frame)
    KEEP (*(.init))
    KEEP (*(.fini))
    . = ALIGN(4);
  } > m_text

  .ARM.extab :
  {
    *(.ARM.extab* .gnu.linkonce.armextab.*)
  } > m_text

  .ARM :
  {
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
  } > m_text

 .ctors :
  {
    __CTOR_LIST__ = .;
    /* gcc uses crtbegin.o to find the start of
       the constructors, so we make sure it is
       first.  Because this is a wildcard, it
       doesn't matter if the user does not
       actually link against crtbegin.o; the
       linker won't look for a file to match a
       wildcard.  The wildcard also means that it
       doesn't matter which directory crtbegin.o
       is in.  */
    KEEP (*crtbegin.o(.ctors))
    KEEP (*crtbegin?.o(.ctors))
    /* We don't want to include the .ctor section from
       from the crtend.o file until after the sorted ctors.
       The .ctor section from the crtend file contains the
       end of ctors marker and it must be last */
    KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors))
    KEEP (*(SORT(.ctors.*)))
    KEEP (*(.ctors))
    __CTOR_END__ = .;
  } > m_text

  .dtors :
  {
    __DTOR_LIST__ = .;
    KEEP (*crtbegin.o(.dtors))
    KEEP (*crtbegin?.o(.dtors))
    KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors))
    KEEP (*(SORT(.dtors.*)))
    KEEP (*(.dtors))
    __DTOR_END__ = .;
  } > m_text

  .preinit_array :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } > m_text

  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
  } > m_text

  .fini_array :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } > m_text

  __etext = .;    /* define a global symbol at end of code */
  __DATA_ROM = .; /* Symbol is used by startup for data initialization */

  .interrupts_ram :
  {
    . = ALIGN(4);
    __VECTOR_RAM__ = .;
    __interrupts_ram_start__ = .; /* Create a global symbol at data start */
    *(.m_interrupts_ram)     /* This is a user defined section */
    . += M_VECTOR_RAM_SIZE;
    . = ALIGN(4);
    __interrupts_ram_end__ = .; /* Define a global symbol at data end */
  } > m_data

  __VECTOR_RAM = DEFINED(__ram_vector_table__) ? __VECTOR_RAM__ : ORIGIN(m_interrupts);
  __RAM_VECTOR_TABLE_SIZE_BYTES = DEFINED(__ram_vector_table__) ? (__interrupts_ram_end__ - __interrupts_ram_start__) : 0x0;

  .data : AT(__DATA_ROM)
  {
    . = ALIGN(4);
    __DATA_RAM = .;
    __data_start__ = .;      /* create a global symbol at data start */
    *(.data)                 /* .data sections */
    *(.data*)                /* .data* sections */
    KEEP(*(.jcr*))
    . = ALIGN(4);
    __data_end__ = .;        /* define a global symbol at data end */
  } > m_data

  __DATA_END = __DATA_ROM + (__data_end__ - __data_start__);
  text_end = ORIGIN(m_text) + LENGTH(m_text);
  ASSERT(__DATA_END <= text_end, "region m_text overflowed with text and data")

  USB_RAM_GAP = DEFINED(__usb_ram_size__) ? __usb_ram_size__ : 0x800;
  /* Uninitialized data section */
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss section */
    . = ALIGN(4);
    __START_BSS = .;
    __bss_start__ = .;
    *(.bss)
    *(.bss*)
    . = ALIGN(512);
    USB_RAM_START = .;
    . += USB_RAM_GAP;
    *(COMMON)
    . = ALIGN(4);
    __bss_end__ = .;
    __END_BSS = .;
  } > m_data

  .heap :
  {
    . = ALIGN(8);
    __end__ = .;
    PROVIDE(end = .);
    __HeapBase = .;
    . += HEAP_SIZE;
    __HeapLimit = .;
    __heap_limit = .; /* Add for _sbrk */
  } > m_data_2

  .stack :
  {
    . = ALIGN(8);
    . += STACK_SIZE;
  } > m_data_2

  m_usb_bdt USB_RAM_START (NOLOAD) :
  {
    *(m_usb_bdt)
    USB_RAM_BDT_END = .;
  }

  m_usb_global USB_RAM_BDT_END (NOLOAD) :
  {
    *(m_usb_global)
  }

  /* Initializes stack on the end of block */
  __StackTop   = ORIGIN(m_data_2) + LENGTH(m_data_2);
  __StackLimit = __StackTop - STACK_SIZE;
  PROVIDE(__stack = __StackTop);

  .ARM.attributes 0 : { *(.ARM.attributes) }

  ASSERT(__StackLimit >= __HeapLimit, "region m_data_2 overflowed with stack and heap")
}

В этой реализации загрузчик не загружает приложение и перезапускается. Я предполагаю, что ошибка связана с ошибочной картой памяти в моем .bin.

Карта памяти должна соответствовать следующему: enter image description here

Файл startup_XXX.sя в настоящее время использую:

    .syntax unified
    .arch armv7-m

    .section .isr_vector, "a"
    .align 2
    .globl __isr_vector
__isr_vector:
    .long   __StackTop                                      /* Top of Stack */
    .long   Reset_Handler                                   /* Reset Handler */
    .long   NMI_Handler                                     /* NMI Handler*/
    .long   HardFault_Handler                               /* Hard Fault Handler*/
    .long   MemManage_Handler                               /* MPU Fault Handler*/
    .long   BusFault_Handler                                /* Bus Fault Handler*/
    .long   UsageFault_Handler                              /* Usage Fault Handler*/
    .long   0                                               /* Reserved*/
    .long   0                                               /* Reserved*/
    .long   0                                               /* Reserved*/
    .long   0                                               /* Reserved*/
    .long   SVC_Handler                                     /* SVCall Handler*/
    .long   DebugMon_Handler                                /* Debug Monitor Handler*/
    .long   0                                               /* Reserved*/
    .long   PendSV_Handler                                  /* PendSV Handler*/
    .long   SysTick_Handler                                 /* SysTick Handler*/

                                                            /* External Interrupts*/
    .long   DMA0_DMA16_IRQHandler                           /* DMA Channel 0, 16 Transfer Complete*/
    .long   DMA1_DMA17_IRQHandler                           /* DMA Channel 1, 17 Transfer Complete*/
    .long   DMA2_DMA18_IRQHandler                           /* DMA Channel 2, 18 Transfer Complete*/
    .long   DMA3_DMA19_IRQHandler                           /* DMA Channel 3, 19 Transfer Complete*/
    .long   DMA4_DMA20_IRQHandler                           /* DMA Channel 4, 20 Transfer Complete*/
    .long   DMA5_DMA21_IRQHandler                           /* DMA Channel 5, 21 Transfer Complete*/
    .long   DMA6_DMA22_IRQHandler                           /* DMA Channel 6, 22 Transfer Complete*/
    .long   DMA7_DMA23_IRQHandler                           /* DMA Channel 7, 23 Transfer Complete*/
    .long   DMA8_DMA24_IRQHandler                           /* DMA Channel 8, 24 Transfer Complete*/
    .long   DMA9_DMA25_IRQHandler                           /* DMA Channel 9, 25 Transfer Complete*/
    .long   DMA10_DMA26_IRQHandler                          /* DMA Channel 10, 26 Transfer Complete*/
    .long   DMA11_DMA27_IRQHandler                          /* DMA Channel 11, 27 Transfer Complete*/
    .long   DMA12_DMA28_IRQHandler                          /* DMA Channel 12, 28 Transfer Complete*/
    .long   DMA13_DMA29_IRQHandler                          /* DMA Channel 13, 29 Transfer Complete*/
    .long   DMA14_DMA30_IRQHandler                          /* DMA Channel 14, 30 Transfer Complete*/
    .long   DMA15_DMA31_IRQHandler                          /* DMA Channel 15, 31 Transfer Complete*/
    .long   DMA_Error_IRQHandler                            /* DMA Error Interrupt*/
    .long   MCM_IRQHandler                                  /* Normal Interrupt*/
    .long   FTFE_IRQHandler                                 /* FTFE Command complete interrupt*/
    .long   Read_Collision_IRQHandler                       /* Read Collision Interrupt*/
    .long   LVD_LVW_IRQHandler                              /* Low Voltage Detect, Low Voltage Warning*/
    .long   LLWU_IRQHandler                                 /* Low Leakage Wakeup Unit*/
    .long   WDOG_EWM_IRQHandler                             /* WDOG Interrupt*/
    .long   RNG_IRQHandler                                  /* RNG Interrupt*/
    .long   I2C0_IRQHandler                                 /* I2C0 interrupt*/
    .long   I2C1_IRQHandler                                 /* I2C1 interrupt*/
    .long   SPI0_IRQHandler                                 /* SPI0 Interrupt*/
    .long   SPI1_IRQHandler                                 /* SPI1 Interrupt*/
    .long   I2S0_Tx_IRQHandler                              /* I2S0 transmit interrupt*/
    .long   I2S0_Rx_IRQHandler                              /* I2S0 receive interrupt*/
    .long   Reserved46_IRQHandler                           /* Reserved interrupt 46*/
    .long   UART0_RX_TX_IRQHandler                          /* UART0 Receive/Transmit interrupt*/
    .long   UART0_ERR_IRQHandler                            /* UART0 Error interrupt*/
    .long   UART1_RX_TX_IRQHandler                          /* UART1 Receive/Transmit interrupt*/
    .long   UART1_ERR_IRQHandler                            /* UART1 Error interrupt*/
    .long   UART2_RX_TX_IRQHandler                          /* UART2 Receive/Transmit interrupt*/
    .long   UART2_ERR_IRQHandler                            /* UART2 Error interrupt*/
    .long   UART3_RX_TX_IRQHandler                          /* UART3 Receive/Transmit interrupt*/
    .long   UART3_ERR_IRQHandler                            /* UART3 Error interrupt*/
    .long   ADC0_IRQHandler                                 /* ADC0 interrupt*/
    .long   CMP0_IRQHandler                                 /* CMP0 interrupt*/
    .long   CMP1_IRQHandler                                 /* CMP1 interrupt*/
    .long   FTM0_IRQHandler                                 /* FTM0 fault, overflow and channels interrupt*/
    .long   FTM1_IRQHandler                                 /* FTM1 fault, overflow and channels interrupt*/
    .long   FTM2_IRQHandler                                 /* FTM2 fault, overflow and channels interrupt*/
    .long   CMT_IRQHandler                                  /* CMT interrupt*/
    .long   RTC_IRQHandler                                  /* RTC interrupt*/
    .long   RTC_Seconds_IRQHandler                          /* RTC seconds interrupt*/
    .long   PIT0_IRQHandler                                 /* PIT timer channel 0 interrupt*/
    .long   PIT1_IRQHandler                                 /* PIT timer channel 1 interrupt*/
    .long   PIT2_IRQHandler                                 /* PIT timer channel 2 interrupt*/
    .long   PIT3_IRQHandler                                 /* PIT timer channel 3 interrupt*/
    .long   PDB0_IRQHandler                                 /* PDB0 Interrupt*/
    .long   USB0_IRQHandler                                 /* USB0 interrupt*/
    .long   USBDCD_IRQHandler                               /* USBDCD Interrupt*/
    .long   Reserved71_IRQHandler                           /* Reserved interrupt 71*/
    .long   DAC0_IRQHandler                                 /* DAC0 interrupt*/
    .long   MCG_IRQHandler                                  /* MCG Interrupt*/
    .long   LPTMR0_IRQHandler                               /* LPTimer interrupt*/
    .long   PORTA_IRQHandler                                /* Port A interrupt*/
    .long   PORTB_IRQHandler                                /* Port B interrupt*/
    .long   PORTC_IRQHandler                                /* Port C interrupt*/
    .long   PORTD_IRQHandler                                /* Port D interrupt*/
    .long   PORTE_IRQHandler                                /* Port E interrupt*/
    .long   SWI_IRQHandler                                  /* Software interrupt*/
    .long   SPI2_IRQHandler                                 /* SPI2 Interrupt*/
    .long   UART4_RX_TX_IRQHandler                          /* UART4 Receive/Transmit interrupt*/
    .long   UART4_ERR_IRQHandler                            /* UART4 Error interrupt*/
    .long   Reserved84_IRQHandler                           /* Reserved interrupt 84*/
    .long   Reserved85_IRQHandler                           /* Reserved interrupt 85*/
    .long   CMP2_IRQHandler                                 /* CMP2 interrupt*/
    .long   FTM3_IRQHandler                                 /* FTM3 fault, overflow and channels interrupt*/
    .long   DAC1_IRQHandler                                 /* DAC1 interrupt*/
    .long   ADC1_IRQHandler                                 /* ADC1 interrupt*/
    .long   I2C2_IRQHandler                                 /* I2C2 interrupt*/
    .long   CAN0_ORed_Message_buffer_IRQHandler             /* CAN0 OR'd message buffers interrupt*/
    .long   CAN0_Bus_Off_IRQHandler                         /* CAN0 bus off interrupt*/
    .long   CAN0_Error_IRQHandler                           /* CAN0 error interrupt*/
    .long   CAN0_Tx_Warning_IRQHandler                      /* CAN0 Tx warning interrupt*/
    .long   CAN0_Rx_Warning_IRQHandler                      /* CAN0 Rx warning interrupt*/
    .long   CAN0_Wake_Up_IRQHandler                         /* CAN0 wake up interrupt*/
    .long   SDHC_IRQHandler                                 /* SDHC interrupt*/
    .long   ENET_1588_Timer_IRQHandler                      /* Ethernet MAC IEEE 1588 Timer Interrupt*/
    .long   ENET_Transmit_IRQHandler                        /* Ethernet MAC Transmit Interrupt*/
    .long   ENET_Receive_IRQHandler                         /* Ethernet MAC Receive Interrupt*/
    .long   ENET_Error_IRQHandler                           /* Ethernet MAC Error and miscelaneous Interrupt*/
    .long   LPUART0_IRQHandler                              /* LPUART0 status/error interrupt*/
    .long   TSI0_IRQHandler                                 /* TSI0 interrupt*/
    .long   TPM1_IRQHandler                                 /* TPM1 fault, overflow and channels interrupt*/
    .long   TPM2_IRQHandler                                 /* TPM2 fault, overflow and channels interrupt*/
    .long   USBHSDCD_IRQHandler                             /* USBHSDCD, USBHS Phy Interrupt*/
    .long   I2C3_IRQHandler                                 /* I2C3 interrupt*/
    .long   CMP3_IRQHandler                                 /* CMP3 interrupt*/
    .long   USBHS_IRQHandler                                /* USB high speed OTG interrupt*/
    .long   CAN1_ORed_Message_buffer_IRQHandler             /* CAN1 OR'd message buffers interrupt*/
    .long   CAN1_Bus_Off_IRQHandler                         /* CAN1 bus off interrupt*/
    .long   CAN1_Error_IRQHandler                           /* CAN1 error interrupt*/
    .long   CAN1_Tx_Warning_IRQHandler                      /* CAN1 Tx warning interrupt*/
    .long   CAN1_Rx_Warning_IRQHandler                      /* CAN1 Rx warning interrupt*/
    .long   CAN1_Wake_Up_IRQHandler                         /* CAN1 wake up interrupt*/
    .long   DefaultISR                                      /* 116*/
    .long   DefaultISR                                      /* 117*/
    .long   DefaultISR                                      /* 118*/
    .long   DefaultISR                                      /* 119*/
    .long   DefaultISR                                      /* 120*/
    .long   DefaultISR                                      /* 121*/
    .long   DefaultISR                                      /* 122*/
    .long   DefaultISR                                      /* 123*/
    .long   DefaultISR                                      /* 124*/
    .long   DefaultISR                                      /* 125*/
    (...)
    .long   DefaultISR                                      /* 245*/
    .long   DefaultISR                                      /* 246*/
    .long   DefaultISR                                      /* 247*/
    .long   DefaultISR                                      /* 248*/
    .long   DefaultISR                                      /* 249*/
    .long   DefaultISR                                      /* 250*/
    .long   DefaultISR                                      /* 251*/
    .long   DefaultISR                                      /* 252*/
    .long   DefaultISR                                      /* 253*/
    .long   DefaultISR                                      /* 254*/
    .long   0xFFFFFFFF                                      /*  Reserved for user TRIM value*/

    .size    __isr_vector, . - __isr_vector

/* Flash Configuration */
    .section .FlashConfig, "a"
    .long 0xFFFFFFFF
    .long 0xFFFFFFFF
    .long 0xFFFFFFFF
    .long 0xFFFFFFFE

    .text
    .thumb

/* Reset Handler */

    .thumb_func
    .align 2
    .globl   Reset_Handler
    .weak    Reset_Handler
    .type    Reset_Handler, %function
Reset_Handler:
    cpsid   i               /* Mask interrupts */
    .equ    VTOR, 0xE000ED08
    ldr     r0, =VTOR
    ldr     r1, =__isr_vector
    str     r1, [r0]
    ldr     r2, [r1]
    msr     msp, r2
#ifndef __NO_SYSTEM_INIT
    ldr   r0,=SystemInit
    blx   r0
#endif
/*     Loop to copy data from read only memory to RAM. The ranges
 *      of copy from/to are specified by following symbols evaluated in
 *      linker script.
 *      __etext: End of code section, i.e., begin of data sections to copy from.
 *      __data_start__/__data_end__: RAM address range that data should be
 *      copied to. Both must be aligned to 4 bytes boundary.  */

    ldr    r1, =__etext
    ldr    r2, =__data_start__
    ldr    r3, =__data_end__

#if 1
/* Here are two copies of loop implemenations. First one favors code size
 * and the second one favors performance. Default uses the first one.
 * Change to "#if 0" to use the second one */
.LC0:
    cmp     r2, r3
    ittt    lt
    ldrlt   r0, [r1], #4
    strlt   r0, [r2], #4
    blt    .LC0
#else
    subs    r3, r2
    ble    .LC1
.LC0:
    subs    r3, #4
    ldr    r0, [r1, r3]
    str    r0, [r2, r3]
    bgt    .LC0
.LC1:
#endif

#ifdef __STARTUP_CLEAR_BSS
/*     This part of work usually is done in C library startup code. Otherwise,
 *     define this macro to enable it in this startup.
 *
 *     Loop to zero out BSS section, which uses following symbols
 *     in linker script:
 *      __bss_start__: start of BSS section. Must align to 4
 *      __bss_end__: end of BSS section. Must align to 4
 */
    ldr r1, =__bss_start__
    ldr r2, =__bss_end__

    movs    r0, 0
.LC2:
    cmp     r1, r2
    itt    lt
    strlt   r0, [r1], #4
    blt    .LC2
#endif /* __STARTUP_CLEAR_BSS */

    cpsie   i               /* Unmask interrupts */
#ifndef __START
#define __START _start
#endif
#ifndef __ATOLLIC__
    ldr   r0,=__START
    blx   r0
#else
    ldr   r0,=__libc_init_array
    blx   r0
    ldr   r0,=main
    bx    r0
#endif
    .pool

[Не удалось вставить весь файл]

Моя попытка решить проблему исходит из этого руководства .

Ответы [ 2 ]

1 голос
/ 05 ноября 2019

Вы должны поместить функцию запуска в положение 0x80000, чтобы загрузчик мог выполнить ее правильно.

Другая проблема - прерывания. Поскольку у вас есть загрузчик, и я думаю, что он работает всю жизнь программы, вы не должны заменять вектор прерывания. В загрузчике, вероятно, есть некоторые функции для установки прерываний, поэтому вы должны использовать их вместо перемещения вектора ISR.


Размещение функции запуска по известному адресу:

Поскольку вы используете MCUXpresso и KDS, я полагаю, что вы используете набор инструментов, предоставленный NXP, базирующийся в GCC.

Если это так, вам нужно будет использовать sections, чтобы установитьфункция по определенному адресу. В SDK функция запуска находится в файле startup_XXX.S, а в моем файле (я не знаю, используют ли они всегда одинаковые имена), она называется Reset_Handler. Вы также можете найти его по вектору ISR, являющемуся второй записью (запись сброса).

В моем случае это определяется следующим образом:

.section .reset_handler_section, "a"  //EDIT 3: This is the line added
.thumb_func
    .align 2
    .globl   Reset_Handler
    .weak    Reset_Handler
    .type    Reset_Handler, %function
Reset_Handler:
    //Actual reset code follows

У вас должно быть что-тоаналогично вашему ASM-коду.

Теперь, когда вы знаете, какая у вас функция запуска, поместите ее в 0x80000. Это делается в вашем файле компоновщика, в разделе SECTIONS.

Но сначала ваша новая карта памяти должна включать в себя только память, которую вы можете изменять, это раздел под названием «Область приложения» визображение, которое вы приложили.

Итак, карта памяти для нашего приложения должна быть:

MEMORY
{
  m_text                (RX)  : ORIGIN = 0x00080000, LENGTH = 0x00080000
  m_data                (RWX)  : ORIGIN = 0x20000000, LENGTH = 0x00030000
}

ВНИМАНИЕ: Вы должны знать, где ваши данные (m_data) могут начинаться в ОЗУ, так как вы не хотитепереопределить данные загрузчика. Вы не показывали его на своем изображении, поэтому я просто выбрал ORIGIN в ОЗУ, но вы должны проверить это.

Обратите внимание, что нет ни прерываний, ни разделов flash_config. Я предполагаю, что загрузчик уже имеет их, поэтому вам не нужно добавлять их снова.

Как только вы определили свою карту памяти, вы можете добавить в нее всю свою программу:

SECTIONS
{
  /* The startup code*/
    .startup_text :
  {
    . = ALIGN(4);
    KEEP(*(.reset_handler_section)) /* Startup data */ /*EDIT 3: This is the modification*/
    KEEP(*(.isr_vector))     /* EDIT 6: Startup code. It is needed in order to avoid modifying source files. It is not used, since the reset vector is the defined in the Bootloader build */
    *(.text)                 /* .text sections (code) */
    *(.text*)                /* .text* sections (code) */
    *(.rodata)               /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)              /* .rodata* sections (constants, strings, etc.) */
    *(.glue_7)               /* glue arm to thumb code */
    *(.glue_7t)              /* glue thumb to arm code */
    KEEP (*(.init))  /*EDIT 2: The init section. If there are more 
                      * sections like this, just keep adding them here.
                      */
  } > m_text

    /*EDIT 5. Added entire section*/
  .ARM :
  {
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
  } > m_text

  __DATA_ROM = .;          /* Symbol is used by startup for data initialization */ /*EDIT 7: This symbol must be placed at the end of the text sections, so the data can follow all the code in ROM*/
  __etext = .;    /* define a global symbol at end of code */ /*EDIT 4*/

  /*The application variables and other data in RAM*/
  .data : AT(__DATA_ROM)
  {
    . = ALIGN(4);
    __DATA_RAM = .;
    __data_start__ = .;      /* create a global symbol at data start */
    *(.data)                 /* .data sections */
    *(.data*)                /* .data* sections */
    KEEP(*(.jcr*))
    KEEP(*(.ramSection))
    . = ALIGN(4);
    __data_end__ = .;        /* define a global symbol at data end */
  } > m_data

  /* Uninitialized data section */
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss section */
    . = ALIGN(4);
    __START_BSS = .;
    __bss_start__ = .;
    *(.bss)
    *(.bss*)
    *(COMMON)
    . = ALIGN(4);
    __bss_end__ = .;
    __END_BSS = .;
  } > m_data

}

В качестве небольшого пояснения мы говорим компоновщику поместить все в раздел ".startup_text" (это может быть любое имя) в память m_text, всегда в порядке. Таким образом, в первом адресе m_text (это 0x80000) будет помещен Reset_Handler. После этого будут размещены все остальные функции (.text) и постоянные данные (rodata).

Мы также определим символ __DATA_ROM, который будет в последнем адресе раздела. После всех постоянных данных мы также добавляем инициализированные данные. Эти данные имеют постоянные значения, которые будут помещаться в ПЗУ, но компоновщик также должен зарезервировать для них память в ОЗУ, чтобы иметь возможность их изменять. Это то, что делается в разделе data.


Редактировать 1: Чтобы компоновщик знал, где запустить вашу программу, и, таким образом, чтобы он мог посмотреть, какой код понадобится, вы должны указатьэто точка запуска вашей программы, так как компоновщик не понимает аппаратное обеспечение конкретного чипа (например, запись вектора сброса). Это делается путем добавления этого в начало файла компоновщика, перед разделом MEMORY:

/* Entry Point */
ENTRY(Reset_Handler)

STACK_SIZE = 0x0400;
M_VECTOR_RAM_SIZE = 0x0400;

Я не знаю, действительно ли нужны определения размера, но на всякий случай я также разместил их здесь.

0 голосов
/ 11 ноября 2019

Добавление к решению:

Изменение файла компоновщика в моем вопросе действительно было правильным.

MEMORY
{
  m_interrupts          (RX)  : ORIGIN = 0x00080000, LENGTH = 0x00000400
  m_flash_config        (RX)  : ORIGIN = 0x00080400, LENGTH = 0x00000010
  m_text                (RX)  : ORIGIN = 0x00080410, LENGTH = 0x001FFBF0
  m_data                (RW)  : ORIGIN = 0x1FFF0000, LENGTH = 0x00030000
  m_data_2              (RW)  : ORIGIN = 0x20000000, LENGTH = 0x00030000
}

Проблема не загрузки программы возникла из-за того, что она работает в операционной системе реального времени. Поэтому позже я понял, что решение моей проблемы было не в файле компоновщика, а в перезапуске часов SysTick, которые, казалось, влияли на ОСРВ и, следовательно, не запустили загруженное приложение.

Если вы используете реальныйВремя работы операционной системы, обязательно сбросьте системные часы перед загрузкой приложения из загрузчика. Это казалось, чтобы решить мои проблемы.

Однако предлагаемое решение для файла компоновщика работает, но проблема возникла из другого источника.

...