我正在为一个课程项目从头开始编写一个实时操作系统。我将代码下载到芯片后想知道代码的结束地址,因为我打算使用空闲内存来获取堆栈空间,我需要确保不会覆盖现有代码。
我听说GCC提供的__end变量是代码的结尾,但我不知道__end是什么意思以及如何在我的代码中使用它。任何人都可以解释一下或提供一些材料的链接,因为我不能google __end?
非常感谢。
答案 0 :(得分:3)
正如Adam Rosenfeld指出的那样,您需要使用链接器控制文件为您定义一个或多个符号,这些符号位于精确正确的位置。
对于gcc和binutils,您将使用ld的链接器脚本语法。有关我在此处遗漏的所有详细信息,请参阅ld的手册。它有点不透明,但是如果你要在嵌入式世界中花费大量精力,你应该花一些时间。它会为你带来回报。
在链接描述文件中,您希望在.text段之前定义一个符号,然后在。
之后定义符号 Adam提到了PROVIDE()
语法,它将起作用。但是,如果您可以保证您的名称是唯一的,则可能不需要在PROVIDE中包含该定义。请注意,这是您必须能够做到的保证,否则您将在以后面临很多混乱。
在我的脚本中,我只使用类似的东西:
__SDRAM_CS1 = 0x10000000;
定义带有常量地址的符号(在这种情况下)指向我们认为SDRAM控制器将映射SDRAM存储器的位置,并在C中声明它如下:
extern unsigned char __SDRAM_CS1[];
这样它就可以用在需要知道SDRAM实际位置的代码中。
对于定位.text段结尾的符号,您将在链接描述文件中使用以下内容
SECTIONS
{
...
.text {
_start_text = .;
*(.text);
...
_end_text = .;
}
...
}
并将开始和结束符号声明为
extern unsigned char _start_text[];
extern unsigned char _end_text[];
C中的然后,起始地址只是_start_text
,文本段的字节长度为_end_text - _start_text
。
请注意,我遗漏了很多细节。您可能有一些名为.text以外的部分,必须将它们视为文本段中的部分。一个主要的例子是只读数据,它们通常可以安全地位于文本段中,因为它已知为const
,而在嵌入式系统中,如果您没有,则不希望将其复制到有价值的RAM中至。此外,数据段的初始值设定项和内部生成的全局对象构造函数列表都位于文本段附近。
在图像尺寸中包含这些内容是否是在了解了它们的用途之后需要做出的设计决定。
答案 1 :(得分:2)
您可以使用链接描述文件。在您的C代码中,声明:
// call this whatever you want; the linker will fill this in with the address
// of the end of code
extern uint32_t endOfCode;
然后,在链接描述文件中,在.text
部分的定义后立即添加以下内容:
PROVIDE(endOfCode = .);
我对链接器脚本不是很熟悉,所以我无法提供完整的工作示例。您必须使用默认链接器脚本(我不确定如何获取)并按上述方法对其进行修改,然后使用链接器的-T
选项指定它。祝你好运!
答案 2 :(得分:0)
而不是把它放在最后,你能不能只声明一个大的静态数组并使用它,没有花哨的编译器或链接器技巧?
答案 3 :(得分:-2)
嗯,我不熟悉GCC,但也许你可以这样做:
long foo()
{
int anything[0];
return *(&anything - 1);
}
long endOfProgram()
{
return stackPointer();
}
我在这里要做的是:
我的一些语法可能有误,但我希望你能得到我想要做的事情的要点。
编辑:
...或者只是获取一个指向endOfProgram的函数指针的值。我想这也有用。