AVR G++:执行超过 128 Kb ROM 边界的函数
AVR G++: Executing a function that is past the 128 Kb ROM boundary
AVR g++ 的指针大小为 16 位。但是,我的特定芯片(ATMega2560)有 256 KB 的 RAM。为了支持这一点,编译器会在与当前执行代码相同的 ROM 部分中自动生成蹦床部分,然后包含扩展的汇编代码以跳入高内存或返回。为了生成蹦床,您必须获取位于高端内存中的地址。
在我的场景中,我有一个我编写的引导加载程序位于高端内存中。应用程序代码需要能够调用引导加载程序中的函数。我知道这个函数的地址,需要能够通过在我的代码中硬编码地址来直接寻址它。
如何让 compiler/linker 为任意地址生成适当的蹦床?
编译器和链接器只会在远地址是符号地址而不是代码中已有的常量数字时生成蹦床代码。类似的东西(假设你想跳转到的地址是 0x20000)。
extern void (*farfun)() = 0x20000;
farfun ();
肯定不会工作,它不会导致链接器做任何事情,因为地址已经解析。
您应该能够像这样在链接器命令行中注入符号地址:
extern void farfun ();
farfun ();
编译"normally"并链接
-Wl,--defsym,farfun=0x20000
我认为很明显,您需要确保自己在 farfun
.
处有一些合理的东西
您很可能还需要 --relax
。
编辑
我自己从未尝试过,但也许:
您可能会尝试将函数地址存储在高端内存中的 table 中并像这样声明它:
extern void (*farfunctable [10])();
(farfunctable [0])();
并使用完全相同的链接器命令来解析外部符号(现在您的 table 位于 0x20000(在引导加载程序中)需要如下所示:
extern void func1();
extern void func2();
void ((*farfunctab [10])() = {
func1,
func2,....
};
我建议将 func1() ... func10()
放在与 farfunctab
不同的模块中,以使链接器知道它必须生成 trampolins。
AVR g++ 的指针大小为 16 位。但是,我的特定芯片(ATMega2560)有 256 KB 的 RAM。为了支持这一点,编译器会在与当前执行代码相同的 ROM 部分中自动生成蹦床部分,然后包含扩展的汇编代码以跳入高内存或返回。为了生成蹦床,您必须获取位于高端内存中的地址。
在我的场景中,我有一个我编写的引导加载程序位于高端内存中。应用程序代码需要能够调用引导加载程序中的函数。我知道这个函数的地址,需要能够通过在我的代码中硬编码地址来直接寻址它。
如何让 compiler/linker 为任意地址生成适当的蹦床?
编译器和链接器只会在远地址是符号地址而不是代码中已有的常量数字时生成蹦床代码。类似的东西(假设你想跳转到的地址是 0x20000)。
extern void (*farfun)() = 0x20000;
farfun ();
肯定不会工作,它不会导致链接器做任何事情,因为地址已经解析。
您应该能够像这样在链接器命令行中注入符号地址:
extern void farfun ();
farfun ();
编译"normally"并链接
-Wl,--defsym,farfun=0x20000
我认为很明显,您需要确保自己在 farfun
.
您很可能还需要 --relax
。
编辑
我自己从未尝试过,但也许:
您可能会尝试将函数地址存储在高端内存中的 table 中并像这样声明它:
extern void (*farfunctable [10])();
(farfunctable [0])();
并使用完全相同的链接器命令来解析外部符号(现在您的 table 位于 0x20000(在引导加载程序中)需要如下所示:
extern void func1();
extern void func2();
void ((*farfunctab [10])() = {
func1,
func2,....
};
我建议将 func1() ... func10()
放在与 farfunctab
不同的模块中,以使链接器知道它必须生成 trampolins。