GNU 链接器,同一内存区域的不同寻址
GNU linker, different adressing for same memory region
所以我有一个用于我的 stm32f7 mcu 的简单链接描述文件
MEMORY{
ROM_AXIM (rx) : ORIGIN = 0x08000000, LENGTH = 1M
ROM_ITCM (rx) : ORIGIN = 0x00200000, LENGTH = 1M
RAM_ITCM (rwx): ORIGIN = 0x00000000, LENGTH = 16K
RAM_DTCM (rwx): ORIGIN = 0x20000000, LENGTH = 64K
SRAM (rwx): ORIGIN = 0x20010000, LENGTH = 240K
SRAM2 (rwx): ORIGIN = 0x2004C000, LENGTH = 16K
}
_estack = LENGTH(RAM_DTCM) + ORIGIN(RAM_DTCM);
SECTIONS{
.isr_vector : {
KEEP(*(.isr_vector))
} /* Placed at 0x0 */
.text : {
. = ALIGN(4);
*(.text)
} >ROM_ITCM
.data : {
. = ALIGN(4);
_sdata = .;
*(.data)
. = ALIGN(4);
_sdata = .;
} >SRAM2 AT>ROM_AXIM
.bss : {
. = ALIGN(4);
_sbss = .;
*(.bss)
. = ALIGN(4);
_ebss = .;
} >SRAM2
}
想法是将文本部分放置到 ROM_ITCM,因为使用 ART 加速器可以加速指令获取。但问题是ROM_AXIM和ROM_ITCM是同一个闪存。如何告诉链接器这是物理上相同的存储但在不同的总线上访问。所以它像两条独立的总线一样链接,但文本部分实际上应该紧跟在内存中。isr_vector 并考虑偏移量
例如,这里是我将要写入闪存的 bin 文件:
00000000 00 00 01 20 01 00 20 00 00 00 00 00 00 00 00 00 |... .. .........|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00200000 00 20 70 47 |. pG|
00200004
如您所见,很多闪存被浪费了,它也会尝试将此 bin 写入闪存边界之外。
对比:
00000000 00 00 01 20 09 00 00 08 00 20 70 47
0000000c
这个 hexdump,是我正在寻找的,但是,如您所见,Reset_Handler 有 AXIM 总线的地址。我想要做的是使用上面提供的链接描述文件来获得如下输出:
00000000 00 00 01 20 09 00 20 00 00 20 70 47
0000000c
这里的区别在于它将使用 0x00200008 来查找我的重置处理程序。
到目前为止我已经尝试过:
.text : {
. = ALIGN(4);
*(.text)
} >ROM_ITCM AT>ROM_AXIM
这个可以工作,但问题是它会给出这个输出
00000000 00 00 01 20 01 00 20 00 00 20 70 47 |... .. .. pG|
0000000c
这将在 0x00200000 处加载指令,并通过这样做将加载向量 table(堆栈指针)的第一个条目作为指令
我通过查阅 gnu 链接器页面设法解决了一个问题。我所做的是指定 运行 像这样的部分的时间偏移量。
.text (0x00200000 + SIZEOF(.isr_vector)): {
. = ALIGN(4);
*(.text)
} AT>ROM_AXIM
它的作用是:
.text (0x00200000 + SIZEOF(.isr_vector))
指定 运行 时间地址,偏移量为 table 大小。我的指针现在已正确解析
AT>ROM_AXIM
将代码放在首先产生偏移量的向量 table 之后。和上面的行修复它。
-
所以我有一个用于我的 stm32f7 mcu 的简单链接描述文件
MEMORY{
ROM_AXIM (rx) : ORIGIN = 0x08000000, LENGTH = 1M
ROM_ITCM (rx) : ORIGIN = 0x00200000, LENGTH = 1M
RAM_ITCM (rwx): ORIGIN = 0x00000000, LENGTH = 16K
RAM_DTCM (rwx): ORIGIN = 0x20000000, LENGTH = 64K
SRAM (rwx): ORIGIN = 0x20010000, LENGTH = 240K
SRAM2 (rwx): ORIGIN = 0x2004C000, LENGTH = 16K
}
_estack = LENGTH(RAM_DTCM) + ORIGIN(RAM_DTCM);
SECTIONS{
.isr_vector : {
KEEP(*(.isr_vector))
} /* Placed at 0x0 */
.text : {
. = ALIGN(4);
*(.text)
} >ROM_ITCM
.data : {
. = ALIGN(4);
_sdata = .;
*(.data)
. = ALIGN(4);
_sdata = .;
} >SRAM2 AT>ROM_AXIM
.bss : {
. = ALIGN(4);
_sbss = .;
*(.bss)
. = ALIGN(4);
_ebss = .;
} >SRAM2
}
想法是将文本部分放置到 ROM_ITCM,因为使用 ART 加速器可以加速指令获取。但问题是ROM_AXIM和ROM_ITCM是同一个闪存。如何告诉链接器这是物理上相同的存储但在不同的总线上访问。所以它像两条独立的总线一样链接,但文本部分实际上应该紧跟在内存中。isr_vector 并考虑偏移量
例如,这里是我将要写入闪存的 bin 文件:
00000000 00 00 01 20 01 00 20 00 00 00 00 00 00 00 00 00 |... .. .........|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00200000 00 20 70 47 |. pG|
00200004
如您所见,很多闪存被浪费了,它也会尝试将此 bin 写入闪存边界之外。
对比:
00000000 00 00 01 20 09 00 00 08 00 20 70 47
0000000c
这个 hexdump,是我正在寻找的,但是,如您所见,Reset_Handler 有 AXIM 总线的地址。我想要做的是使用上面提供的链接描述文件来获得如下输出:
00000000 00 00 01 20 09 00 20 00 00 20 70 47
0000000c
这里的区别在于它将使用 0x00200008 来查找我的重置处理程序。
到目前为止我已经尝试过:
.text : {
. = ALIGN(4);
*(.text)
} >ROM_ITCM AT>ROM_AXIM
这个可以工作,但问题是它会给出这个输出
00000000 00 00 01 20 01 00 20 00 00 20 70 47 |... .. .. pG|
0000000c
这将在 0x00200000 处加载指令,并通过这样做将加载向量 table(堆栈指针)的第一个条目作为指令
我通过查阅 gnu 链接器页面设法解决了一个问题。我所做的是指定 运行 像这样的部分的时间偏移量。
.text (0x00200000 + SIZEOF(.isr_vector)): {
. = ALIGN(4);
*(.text)
} AT>ROM_AXIM
它的作用是:
.text (0x00200000 + SIZEOF(.isr_vector))
指定 运行 时间地址,偏移量为 table 大小。我的指针现在已正确解析AT>ROM_AXIM
将代码放在首先产生偏移量的向量 table 之后。和上面的行修复它。
-