我有一个 TCP/IP 堆栈,需要在引导分区和应用程序分区之间共享。堆栈在引导代码中初始化,引导和应用程序都使用堆栈。两个分区都驻留在同一个闪存模块中,但位于不同的闪存部分中,因此它们不会相互擦除。为了共享堆栈,我创建了一个常量函数结构,该结构放置在闪存中的指定内存位置。我正在使用的编译器是飞思卡尔的 Embedded PowerPC 工具。在我的引导代码中,它看起来像这样:
以太网.h
typedef Ethernet_Struct = {
int (*enet_init) (void);
void (*enet_release) (void);
int (*enet_bind)(...);
int (*enet_recvfrom)(...);
}
extern const Ethernet_Struct enet;
以太网.c
const Ethernet_Struct enet = {
enet_init,
enet_release,
enet_bind,
enet_recvfrom
}
然后链接器将此目标文件放置在 0x1ffc0(闪存),并且在我的映射文件中一切看起来都很好。引用此位置的链接器符号是 _ENET_STRUCT_。在我的应用程序中,我这样做:
应用程序.c
#include "ethernet.h"
extern uint32 _ENET_STRUCT_;
const Ethernet_Struct *enet = (Ethernet_Struct *) &_ENET_STRUCT_;
void main() {
enet->enet_init(); /* In the assembly, it's trying to
branch to a location that is not even in flash */
}
我认为 enet 会像在引导代码中一样放置在 .rodata 中,但它实际上是放在 .sdata 中。不用担心,当我将 sdata 部分从 ROM 复制到 RAM 时,enet 指向 0x1ffc0。调试器甚至显示正确的位置。但是随后程序集显示它正在尝试分支到甚至不在闪存或 RAM 中的某个地方。关于这里发生的事情,我最好的猜测是编译器不知道 enet 指向哪里,因为它依赖链接器来获取该地址。
这实际上是有效的,尽管我不喜欢有一个明确的地址值:
#define enet ((Ethernet_Struct *) 0x1ffc0)
那么,在分区之间创建接口的正确方法是什么?