我正在编写一个运行裸机的程序。我试图从自定义链接器脚本中获取变量以在C中使用这是我尝试过的。
来自C:
extern unsigned long* __START_OF_PROG_MEMORY;
volatile unsigned long *StartOfProgram = (unsigned long*) (&__START_OF_PROG_MEMORY);
链接脚本:
SECTIONS
{
. = 0x80000;
PROVIDE(__START_OF_PROG_MEMORY = .);
.text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
PROVIDE(_data = .);
.data : { *(.data .data.* .gnu.linkonce.d*) }
.bss (NOLOAD) : {
. = ALIGN(16);
__bss_start = .;
*(.bss .bss.*)
*(COMMON)
__bss_end = .;
}
_end = .;
PROVIDE(__END_OF_PROG_MEMORY = .);
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
}
__bss_size = (__bss_end - __bss_start)>>3;
获取链接描述文件中定义的变量内容的正确方法是什么?
答案 0 :(得分:3)
通常它就像
一样// Volatile is normally not needed but it seems you have a special case
extern volatile unsigned char __START_OF_PROG_MEMORY[];
volatile unsigned char * const StartOfProgram = &__START_OF_PROG_MEMORY;
答案 1 :(得分:1)
请参阅本页底部的示例: https://sourceware.org/binutils/docs/ld/Source-Code-Reference.html
因此,当您在源代码中使用链接器脚本定义的符号时,应始终获取符号的地址,并且切勿尝试使用其值。例如,假设您要将一个名为.ROM的内存段的内容复制到一个名为.FLASH的段中,并且链接脚本包含以下声明:
start_of_ROM = .ROM;
end_of_ROM = .ROM + sizeof (.ROM);
start_of_FLASH = .FLASH;
然后执行复制的C源代码为:
extern char start_of_ROM, end_of_ROM, start_of_FLASH;
memcpy (& start_of_FLASH, & start_of_ROM, & end_of_ROM - & start_of_ROM);
请注意使用“&”运算符。这些是正确的。另外,也可以将符号视为向量或数组的名称,然后代码将再次按预期工作:
(我的首选方法):
extern char start_of_ROM[], end_of_ROM[], start_of_FLASH[];
memcpy (start_of_FLASH, start_of_ROM, end_of_ROM - start_of_ROM);
请注意,使用此方法不需要使用'&'运算符。
因此,如果我想获取链接程序变量__START_OF_PROG_MEMORY
的值以在我的C程序中使用,我会这样做:
#include <stdint.h>
extern uint32_t __START_OF_PROG_MEMORY[]; // linkerscript variable; NOT an array; `[]` is required to access a linkerscript variable like a normal variable--see here: https://sourceware.org/binutils/docs/ld/Source-Code-Reference.html
uint32_t start_of_program = (uint32_t)__START_OF_PROG_MEMORY;
获取程序存储器(例如闪存,即程序开始位置)起始地址的另一种技巧是简单地获取g_pfnVectors
全局ISR向量表数组的地址,这是在您的启动程序集文件中定义的(例如:“ startup_stm32f746xx.s”)。为此,请执行以下操作:
extern uint32_t g_pfnVectors[]; // true array (vector table of all ISRs), from the startup assembly .s file
uint32_t application_start_address = (uint32_t)&g_pfnVectors[0]; // Get the address of the first element of this array and cast it to a 4-byte unsigned integer
Voilá!太神奇了:)。