【嵌入式常识篇】一个C项目工程在IDE中是怎么一步步编译成一个固件包的

news/2025/1/15 1:31:07/

前言:初学C语言的时候是在Linux环境下,那时候只知道需要通过GCC工具编译成可执行文件才可以在运行,后来进入到了嵌入式行业发现需要IDE将一个C项目工程编译成一个固件包,那时候经常会产生一个疑问:一个C项目工程在IDE中是怎么一步步编译成一个固件包的呢?下面就解答一下这个疑问。时光荏苒,也算是给当年刚入行的自己一个答案。


1️⃣,流程简述

将一个 C 项目工程源代码 编译成 固件包(hex、bin、elf 等) 的过程,涉及 编译工具链IDE 的工作原理。一般来说,固件编译流程分为以下关键步骤:

这个过程通常由 编译工具链(如 GCCIARKeilClang 等)完成,而 IDE(如 Keil、STM32CubeIDE、IAR 等)负责调用这些工具链,并提供一个图形化的界面来简化开发流程

源码 (C/ASM/头文件) ↓
预处理器 (Preprocessor) ↓
编译器 (Compiler) ↓
汇编器 (Assembler) ↓
链接器 (Linker) ↓
固件包 (HEX/BIN/ELF 文件)

对应的执行流程框图如下: 


2️⃣,预处理(Preprocessing)

预处理器会在编译前对源代码进行 文本替换和展开,主要包括:

  • 处理 #include 头文件的引用。
  • 替换宏定义(#define)。
  • 处理条件编译指令(#ifdef#ifndef#endif 等)。
  • 移除注释。

举个例子:下面的这个是源代码

#include "my_header.h"
#define LED_PIN 13void main() {int pin = LED_PIN;
}

当预处理之后:

void main() {int pin = 13;
}

对应的预处理工具与命令:(最经典的就是GCC,当然如果是其他的芯片环境平台可能就需要用到交叉编译工具了)

GCC: gcc -E main.c -o main.i


3️⃣,编译(Compilation)

预处理完成的 .i 文件(纯文本 C 代码)会被编译器转换成 汇编代码

  • 编译器的任务
    • 语法分析,检查代码的语法和语义。
    • 生成对应的汇编代码(.s 文件)

同样是上面的例子:编译后的汇编代码:

mov r0, #13
str r0, [sp, #4]

 编译工具:

  • GCC: gcc -S main.i -o main.s

4️⃣,链接(Linking)

链接器的任务是将多个 目标文件(.o 文件)库文件(.a 或 .lib 文件)启动文件(startup 文件) 合并成一个 可执行的固件文件(.elf/.bin/.hex)

  • 链接的工作内容
    • 解析和解决函数、变量的外部引用。
    • 合并不同模块的目标文件。
    • 分配内存地址(根据链接脚本 linker script)。
    • 生成可执行文件(如 .elf.bin.hex)。

链接工具:

  • GCC: gcc main.o -o main.elf -T linker_script.ld

示例:

如果有多个文件:

main.o      // 主程序
startup.o   // 启动代码
libc.a      // 标准库

链接后的 ELF 文件:

main.elf

📋 ELF 文件包含的信息

  • 可执行机器指令。
  • 符号表、调试信息。
  • 内存布局(.text、.data、.bss、堆栈等段)。

5️⃣,转换(Conversion)

编译完成后生成的 ELF 文件,可能还需要转换成 HEXBIN 格式,便于烧录到芯片中。

  • .elf 文件是包含调试信息的可执行文件,通常用于开发和调试阶段。
  • .hex 文件是Intel HEX 格式的固件包,通常用于烧录工具。
  • .bin 文件是纯二进制格式的固件包

转换工具:

  • objcopy 工具可以将 ELF 文件转换成 HEX/BIN 文件。
# 转换成 HEX 文件
arm-none-eabi-objcopy -O ihex main.elf main.hex# 转换成 BIN 文件
arm-none-eabi-objcopy -O binary main.elf main.bin

🛠️ IDE 的编译流程

常用的 IDE(如 Keil、IAR、STM32CubeIDE)会自动调用编译工具链,按以下步骤完成编译:

  1. 解析项目文件project.uvprojx.cproject 等)。

  2. 调用编译器,对每个源文件进行预处理、编译、汇编,生成 .o 文件。

  3. 调用链接器,根据链接脚本生成 .elf 文件。

  4. 调用转换工具,生成 .hex.bin 文件。

  5. 调用烧录工具,将固件烧录到芯片中(如果配置了烧录选项)。


📌 链接脚本(Linker Script)

链接脚本控制着固件的内存布局,包括:

  • 代码段(.text) 放在 Flash 中。
  • 初始化数据段(.data) 放在 RAM 中。
  • 未初始化数据段(.bss) 放在 RAM 中。
  • 堆栈和堆的分配

典型的链接脚本片段:

MEMORY
{FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512KRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
}SECTIONS
{.text : {*(.text)*(.rodata)} > FLASH.data : {*(.data)} > RAM AT > FLASH.bss : {*(.bss)} > RAM
}


http://www.ppmy.cn/news/1563186.html

相关文章

Selenium 进行网页自动化操作的一个示例,绕过一些网站的自动化检测。python编程

初级教程 selenium 教程和视频教程s原理与安装 - 白月黑羽 https://www.byhy.net/auto/selenium/01/#chrome%201 Selenium 自动化环境安装_哔哩哔哩_bilibili Selenium 自动化环境安装是Python Selenium Web自动化 2024版 - 自动化测试 爬虫的第2集视频,该合集共…

【Python】Python之Selenium基础教程+实战demo:提升你的测试+测试数据构造的效率!

这里写目录标题 什么是Selenium?Selenium基础用法详解环境搭建编写第一个Selenium脚本解析脚本脚本执行结果常用的元素定位方法常用的WebDriver方法等待机制 Selenium高级技巧详解页面元素操作处理弹窗和警告框截图和日志记录多窗口和多标签页操作 一个实战的小demo…

【YOLOv5】源码(train.py)

train.py是YOLOv5中用于模型训练的脚本文件,其主要功能是读取配置文件、设置训练参数、构建模型结构、加载数据、训练/验证模型、保存模型权重文件、输出日志等 参考笔记: 【YOLOv3】源码(train.py)_yolo原始代码-CSDN博客 【y…

docker 自建rustdesk服务器测试

参考https://blog.csdn.net/tootsy_you/article/details/130010564 注意: docker-compose.yml version: 3networks:rustdesk-net:external: falseservices:hbbs:container_name: hbbsports:- 21115:21115- 21116:21116- 21116:21116/udp- 21118:21118image: rust…

【Linux】统信UOS服务器安装MySQL8.0(RPM)

目录 一、下载安装包 二、安装MySQL 2.1hive适配 2.2ranger适配 3.2DolphinScheduler适配 一、下载安装包 官网下载安装包:MySQL :: MySQL Downloads 选择社区版本下载 点击MySQL Community Server 选择对应系统的MySQL版本号 统信1060a 操作系统对应 redhat8…

HTTP 范围Range请求

引言 在现代Web应用中,HTTP范围请求是一种重要的技术,允许客户端请求资源的部分内容,而不是整个资源。这对于大型文件的传输尤其有用,如视频流、断点续传下载等。本文将深入探讨HTTP范围请求的工作原理、实现方法和应用场景。 H…

图解Git——分支的新建与合并《Pro Git》

⭐分支的新建与合并 先引入一个实际开发的工作流: 开发某个网站。为实现某个新的需求,创建一个分支。在这个分支上开展工作。 正在此时,你突然接到一个电话说有个很严重的问题需要紧急修补。你将按照如下方式来处理: 切换到你…

iOS手势shouldBeRequiredToFailByGestureRecognizer 机制

我们在iOS的手势代理方法中看到这样三个方法 (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecogni…