如何从静态库链接向量表用于嵌入式项目

问题描述 投票:0回答:1

我想从头开始为SAMD21制作一个固件项目。该项目背后的想法类似于 RepRapFirmware 的组织方式:它分为“核心”静态库和主项目。核心库包含所有低级内容,例如 ASF 库和自定义驱动程序,最终将移植到其他处理器。主项目包含更高级别的内容,大部分与处理器无关。 “核心”库包含基本向量表定义以及

Reset_Handler
Dummy_Handler
的定义。其他处理程序被声明为弱并使用 Dummy 别名。那些真正需要的应该在主项目中定义。我编译静态库,存档文件包含向量表中的所有符号。但是,当我尝试编译主项目并将其作为静态库链接到“核心”时,生成的 .elf 和 .map 文件没有向量表中的任何符号,除了
Reset_Handler
之外。当我尝试将所有内容编译为单个项目时,生成的文件具有所有符号,甚至是那些未明确定义的符号,并且固件正常运行。我认为缺少处理程序是问题的根源。或者可能是其他原因造成的?如果问题确实是缺少处理程序,如何强制链接整个向量表? Copilot 没有帮助,它的所有建议都在下面列出的内容中。

附加信息:

  • 静态库编译标志:

    -O0 -g3 -mcpu=cortex-m0plus -mthumb -nostdlib -fno-rtti -fexceptions -ffunction-sections -fdata-sections

  • 主要项目编译标志:

    -O0 -g3 -mcpu=cortex-m0plus -mthumb -nostdlib -fno-rtti -fno-exceptions -ffunction-sections -fdata-sections

  • 链接器标志:

    -T/my_path/ATSAMD21J18A.ld -mcpu=cortex-m0plus --specs=nano.specs -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,-Map=/my_path/my_file.map

  • ld 脚本是 ASF 的标准脚本

  • 也尝试过不使用

     -ffunction-sections -fdata-sections

  • 还尝试在库中的处理程序声明中使用

     __attribute__((weak, alias("Dummy_Handler"), used))

  • 甚至按照副驾驶的建议尝试了这一点:

extern "C" const DeviceVectors exception_table;

int main() {
    // Use the vector_table symbol somewhere in your code, to prevent the linker
    // from discarding it. This could be a dummy use that doesn't actually affect
    // the behavior of your program.
    if ((int)&exception_table == 0) {
        while(1);
    }

    // Rest of your main program...
}

来自调试器的调用堆栈:

??@0xfffffffe (Unknown Source:0) 
<signal handler called>@0xfffffff9 (Unknown Source:0) 
_sfixed@0x00000000 (Unknown Source:0)

谢谢!

c++ c arm embedded
1个回答
0
投票

这些事情往往会变得相当复杂。其他指针/建议:

  • 确实,您需要首先确保向量表已链接。编译器可能不明白程序使用它,因此,要么通过链接描述文件显式告诉它“必须”链接向量表,要么使其“”,这至少不会造成任何损害。像代码中那样“触摸”表格只是一个肮脏的黑客行为,我们不需要。

    此外,向量表也应该是

    volatile
  • 以保证它最终在闪存中。因此,如果您基于函数指针数组制作它,您将得到类似的东西
  • const

    请注意,这意味着指针本身是 

    typedef void isr_t (void); volatile isr_t* const vector_table[] = { ... };
    ,因为它是在 
    const

    的右侧键入的。 (此外,您还会在这里看到一长串

    *
    粘液,但您已经了解了基本概念。)
    
    
    您需要确保向量表最终位于地址 0x0000,这可能意味着在链接器脚本中创建一个自定义部分,然后(在类似 gcc 的编译器上)编写类似 

    __attribute__
  • 的内容将其放置在那里(与任何其他内容一起)您已用于弱链接的属性)。
  • 默认的 ASF 链接器脚本很可能假设

    它们的
    名称用于向量表和所有 ISR,因此如果您以不同的方式命名它们但没有更改链接器脚本,那么这就是问题所在。

    ISR 需要是“拇指功能”,因此您需要确保这一点。我不记得

    __attribute__((section(".vectors")))
  • 是否足够或者是否需要额外的调整。您可以查看它们最终在 .map 文件或调试器中的地址。
  • 我一般建议避免使用 ASF,它臃肿、有 bug,总体写得不好。当您编写自己的驱动程序时,请务必使用他们的寄存器映射并查看代码,但一定要编写自己的驱动程序。您可能不需要使用任何给定硬件外设的每一个功能。请注意,在使用 C++ 进行编码时,您可能无法使用预制的寄存器映射,因为该语言不支持联合类型双关。

  • 使用

    -mthumb
  • 编译嵌入式系统,特别是如果您已经在使用
  • -ffreestanding

    。不幸的是,如果您使用 C++,则无法按照行业标准声明

    -nostdlib
    ,但您必须制定一些解决方法。
    
    
    从上面你可能会注意到,C++ 非常不适合与硬件相关的编程。查看 

    是否有一些我可以用 C 做但不能用 C++ 做的事情?
  • 考虑移植到 C,它对微控制器编程有更好的支持。

© www.soinside.com 2019 - 2024. All rights reserved.