首先,我希望我不是在问以前已经问过的东西。我已经尽可能多地搜索了,但我没有找到针对我的具体问题的答案或有用的东西。
我正在开发运行 Cortex M0+ 内核的 FRDM-KL82Z 板。我正在使用 MCUXpresso IDE v10.0.2 和 Segger J-Link 程序员,尽管我认为这与这个问题无关。
该项目将需要一个自定义引导加载程序和由不同开发人员编写的应用程序,每个块都有自己的闪存空间:引导加载程序为 8K,应用程序为 120K(这可能会在未来发生变化,但目前没什么大不了的)。
一旦引导加载程序完成,它将管理到应用程序空间的跳转,应用程序将更改向量表偏移寄存器 (VTOR),以便中断向量表从引导 IVT 更改为应用程序 IVT。这已经成功地测试过了。
我的目标是设置链接器脚本文件,以便应用程序开发人员可以在引导加载程序完成之前在板上构建和调试他们的项目,因为它们将同时被开发。这样做的原因是他们可以使用应用程序空间,因为它将在最终版本中。
我认为重置向量和配置位必须位于它们的默认位置,因为硬件每次需要读取它们时都会转到相同的位置。
我的第一个想法是禁用自动链接器脚本生成并修改MyProject_Debug.ld文件。
脚本自动生成的内容:
INCLUDE "LEDTest_Debug_library.ld"
INCLUDE "LEDTest_Debug_memory.ld"
ENTRY(ResetISR)
SECTIONS
{
/* MAIN TEXT SECTION */
.text : ALIGN(4)
{
FILL(0xff)
__vectors_start__ = ABSOLUTE(.) ;
KEEP(*(.isr_vector))
/* Global Section Table */
. = ALIGN(4) ;
__section_table_start = .;
__data_section_table = .;
LONG(LOADADDR(.data));
LONG( ADDR(.data));
LONG( SIZEOF(.data));
LONG(LOADADDR(.data_RAM2));
LONG( ADDR(.data_RAM2));
LONG( SIZEOF(.data_RAM2));
__data_section_table_end = .;
__bss_section_table = .;
LONG( ADDR(.bss));
LONG( SIZEOF(.bss));
LONG( ADDR(.bss_RAM2));
LONG( SIZEOF(.bss_RAM2));
__bss_section_table_end = .;
__section_table_end = . ;
/* End of Global Section Table */
*(.after_vectors*)
/* Kinetis Flash Configuration data */
. = 0x400 ;
PROVIDE(__FLASH_CONFIG_START__ = .) ;
KEEP(*(.FlashConfig))
PROVIDE(__FLASH_CONFIG_END__ = .) ;
ASSERT(!(__FLASH_CONFIG_START__ == __FLASH_CONFIG_END__), "Linker Flash Config Support Enabled, but no .FlashConfig section provided within application");
/* End of Kinetis Flash Configuration data */
} >PROGRAM_FLASH
.text : ALIGN(4)
{
*(.text*)
*(.rodata .rodata.* .constdata .constdata.*)
. = ALIGN(4);
} > PROGRAM_FLASH
/*
* for exception handling/unwind - some Newlib functions (in common
* with C++ and STDC++) use this.
*/
.ARM.extab : ALIGN(4)
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > PROGRAM_FLASH
__exidx_start = .;
.ARM.exidx : ALIGN(4)
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > PROGRAM_FLASH
__exidx_end = .;
_etext = .;
/* USB_RAM */
.m_usb_data (NOLOAD) :
{
*(m_usb_bdt)
*(m_usb_global)
} > USB_RAM
/* possible MTB section for USB_RAM */
.mtb_buffer_RAM2 (NOLOAD) :
{
KEEP(*(.mtb.$RAM2*))
KEEP(*(.mtb.$USB_RAM*))
} > USB_RAM
/* DATA section for USB_RAM */
.data_RAM2 : ALIGN(4)
{
FILL(0xff)
PROVIDE(__start_data_RAM2 = .) ;
*(.ramfunc.$RAM2)
*(.ramfunc.$USB_RAM)
*(.data.$RAM2*)
*(.data.$USB_RAM*)
. = ALIGN(4) ;
PROVIDE(__end_data_RAM2 = .) ;
} > USB_RAM AT>PROGRAM_FLASH
/* MAIN DATA SECTION */
/* Default MTB section */
.mtb_buffer_default (NOLOAD) :
{
KEEP(*(.mtb*))
} > SRAM
.uninit_RESERVED : ALIGN(4)
{
KEEP(*(.bss.$RESERVED*))
. = ALIGN(4) ;
_end_uninit_RESERVED = .;
} > SRAM
/* Main DATA section (SRAM) */
.data : ALIGN(4)
{
FILL(0xff)
_data = . ;
*(vtable)
*(.ramfunc*)
*(.data*)
. = ALIGN(4) ;
_edata = . ;
} > SRAM AT>PROGRAM_FLASH
/* BSS section for USB_RAM */
.bss_RAM2 : ALIGN(4)
{
PROVIDE(__start_bss_RAM2 = .) ;
*(.bss.$RAM2*)
*(.bss.$USB_RAM*)
. = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */
PROVIDE(__end_bss_RAM2 = .) ;
} > USB_RAM
/* MAIN BSS SECTION */
.bss : ALIGN(4)
{
_bss = .;
*(.bss*)
*(COMMON)
. = ALIGN(4) ;
_ebss = .;
PROVIDE(end = .);
} > SRAM
/* NOINIT section for USB_RAM */
.noinit_RAM2 (NOLOAD) : ALIGN(4)
{
*(.noinit.$RAM2*)
*(.noinit.$USB_RAM*)
. = ALIGN(4) ;
} > USB_RAM
/* DEFAULT NOINIT SECTION */
.noinit (NOLOAD): ALIGN(4)
{
_noinit = .;
*(.noinit*)
. = ALIGN(4) ;
_end_noinit = .;
} > SRAM
.heap : ALIGN(4)
{
_pvHeapStart = .;
. += 0x1000;
. = ALIGN(4);
_pvHeapLimit = .;
} > SRAM
.heap2stackfill :
{
. += 0x1000;
} > SRAM
.stack ORIGIN(SRAM) + LENGTH(SRAM) - 0x1000 - 0: ALIGN(4)
{
_vStackBase = .;
. = ALIGN(4);
_vStackTop = . + 0x1000;
} > SRAM
}
我试图在本指南中找到有关 de GNU 链接器的信息,但我的想法到目前为止还没有奏效。我试过的:
在 Config Words 之后将位置计数器设置为不同的值,并复制在文本部分之前剪切的 ISR_vector 代码:
... /* End of Kinetis Flash Configuration data */ } >PROGRAM_FLASH .text : ALIGN(4) { /* MODIFIED CODE */ . = 0x2000; /* First position of App code */ FILL(0xff) __vectors_start__ = ABSOLUTE(.) ; KEEP(*(.isr_vector)) /* END OF MODIFIED CODE */ *(.text*) *(.rodata .rodata.* .constdata .constdata.*) . = ALIGN(4); } > PROGRAM_FLASH ...
当我这样做并打开 .hex 文件时,配置字 (0x400) 和应用程序空间 (0x2000) 的开头之间的空间实际上是空的(充满 0xFF),但 0x2000 之后的代码与 IVT 表完全不同.
如果我在 IVT 代码行之前将位置计数器移动到 0x2000 ,它会有效地将 IVT 地址移动到 0x2000 位置。为此,我将 Config Words 部分移到 IVT 部分之前,因为定位计数器不能向后移动。
我已经尝试在内存映射中创建一个 Bootloader 部分,具有正确的起始和长度位置,并将默认情况下放置在 PROGRAM_FLASH 部分中的每一行复制到一个新的去 BOOTLOADER(与 ">BOOTLOADER 相同的代码“ 在最后)。在这种情况下,de IVT 仅出现在引导空间中。
链接描述文件是否有可能仅将 de IVT 放置在指示它的第一个位置,然后忽略所有其他调用?我究竟做错了什么?我应该尝试另一种方法来实现这一目标吗?
非常感谢,我知道它很长!