c - 了解 C 运行时环境 (ARM) - 从哪里开始

标签 c arm

我是一名嵌入式开发人员,主要使用 ARM Cortex-M 设备。最近我切换到 Linux 并决定更多地了解构建/组装/链接过程,如何编写 makefile 等,因为我使用的是 IDE(IAR、Keil、Eclipse 等),其中很多东西都是自动化的,用户实际上不知道后台发生了什么。目标是更多地了解这个低级过程,如何正确使用这些工具,而不仅仅是依赖 IDE 默认设置。

在编写了一个 makefile 之后,我就能够构建我的应用程序了。但是,我决定通过直接调用链接器(而不是通过编译器)来手动执行链接过程,结果出人意料地出现了问题!对 libc 的 undefined reference 、__libc_init_array 中的 _init 函数、_exit 等是问题所在。经过一整天的调查,我能够手动包含所有目标文件(crt0.o、crti.o)和库(libnosys.a)。显然,编译器正在自动执行这些操作。

在克服了这些麻烦之后我发现,我对这些内部结构一无所知。为什么我需要一些 ctr0.o、crti.o 等。这些来自哪里等。它是否链接到编译器/链接器或 C 运行时库或系统?

我想了解更多关于这些内部结构的信息,但是,我不确定,我到底在寻找什么。它是一个库、系统、编译器吗?

我明白,系统 (MCU) 需要初始化 RAM 中的变量和其他东西,但是我错过了完整的画面。你能告诉我一本好书/手册,阅读这些东西吗?我到底在寻找什么?

编辑:

在这里与您讨论后,我很可能想出了我需要什么,所以我会按照以下方式重新表述我的问题:

1) 我收到了一个 MCU(比如说 STM32F4xx),我应该创建一个闪烁的 LED 示例。所有这些都应该从头开始,自己的启动代码,不使用外部库等。

2) 第二步,有人告诉我这一切其他人已经完成了(GCC 工具链/标准库、MCU 供应商启动文件等)。因此,我只需要了解/将我的工作与已完成的工作联系起来并比较差异,他们为什么那样做等等。

@mbjoe 回答了所有这些问题 + 我发现了一些有趣的读物: https://www.amazon.com/Embedded-Shoestring-experience-designing-software/dp/0750676094

感谢大家的帮助和指导我正确的方法!

最佳答案

您所指的模块(ctr0.o、crti.o、_init、__libc_init_array、_exit)是由 IAR 和/或 Keil 预构建的库/目标文件/函数。正如您所说,在运行 main() 函数之前需要它们来初始化环境(全局变量初始化、中断 vector 表等)。

在这些库/目标文件中的某些时候,C 或汇编中会有这样一个函数:

void startup(void)
{ 
    ... init code ...

    main();

    while(1);   // or _exit()
}

您可以查看这些从头开始构建启动代码的示例:

http://www.embedded.com/design/mcus-processors-and-socs/4007119/Building-Bare-Metal-ARM-Systems-with-GNU-Part-1--Getting-Started

https://github.com/payne92/bare-metal-arm

关于c - 了解 C 运行时环境 (ARM) - 从哪里开始,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43650493/

相关文章:

c++ - 在 Linux 上从 UART 进行阻塞 read()

gcc - ARM + gcc : global destructors not called after main() returns, 但构造函数是

macos - Visual Studio 可以在带有 ARM 处理器(Apple Silicon)的 Mac 上运行吗

c - 通过 scanf() 提取输入字符串的一部分

c - C 中的 WinAPI 文本输出

architecture - Docker - 在 Mac 上构建 rpi 镜像

arm - Buildroot包管理

c - 调试劣质进程

c - 为什么除法结果是零而不是小数?

c - 用于表示图的高效数据结构