keil常用工具链与编译原理
本文介绍了ARM架构下嵌入式系统的编译流程。从C代码(.c)到目标文件(.o),再到可执行文件(.axf/.elf),最后生成机器码(.bin/.hex)的过程,重点解析了.sct分散加载文件的作用及修改方法。通过Keil工具链演示了编译各阶段,包括armcc编译、armasm汇编、armlink链接等步骤,并比较了不同文件格式的特点:.axf/.elf包含调试信息适合直接烧录,而.bin/.he
大家在使用keil等IDE进行烧录调试的时候,是否有思考过烧录进mcu的是什么东西呢,或者使用串口烧录又是什么格式呢?
如果想要理解底层驱动开发、IAP升级等,理解嵌入式系统的工具链与编译原理必不可少。
实际上在编写的c代码变为可烧录的机器码之前,经历很多步骤,以下是ARM架构的编译工具链流程图

为了更形象的展示实际导向,我直接用keil来演示步骤
.c -< .o
使用keil开发时,当你按下Build键,经常会看到如下的信息

其中Using Compiler表示你使用的工具链,也可以在魔术棒中查看;后面的armcc则表示实际把你编写的源文件(.c、.h)编译为目标文件(.o)

而汇编文件(.s),例如startup文件则是通过armasm汇编器,变成目标文件(.o)
.o -< .axf、elf
至此,出现了第一个关键信息即axf文件,那么先简单介绍一下什么是axf、elf文件。
从技术底层来看,.axf (ARM Executable Format) 和 .elf (Executable and Linkable Format) 通常都是基于 ELF 标准构建的可执行链接格式文件。其生成主要目的就是可执行的文件,而.axf文件是特殊的elf文件,其本质上也是elf文件,由ARM工具链生成的,主要强调用于ARM处理器的elf文件。
此时.o文件要和.sct文件共同连接变为.axf文件
那么什么是.sct文件呢
.sct文件实际上分散加载文件,链接器根据这个文件的配置来分配各个节区的地址空间,并且生成分散加载代码,因此我们只要修改分散加载文件,链接器就能自动帮我们确定代码、变量等这些内容在内存中(Flash和RAM上)的地址。

该文件中一般都是类似这样的格式,可以自己编写,方便代码储存,如图所示,上部分是FLASH中的数据分配起始地址的整体范围(可以在keil中更改),下部分是SRAM中的数据分配起始地址的整体范围(可以在keil中更改),具体FLASH和SRAM大小需要根据mcu的格局分配。
如何测试呢?
注意先包含一个自己的.sct文件的路径,可以直接复制工程本身的.sct文件,类似我这样写。

然后可以简单写两个打印不同log的函数来区分,然后用来定义该函数的范围
__attribute__ ((used, section ("myflash")))

注意!!!调用该函数一定要用volatile关键字,不然会编译器优化,不会每一次访问变量都去对于存储介质中访问。
![]()
最后通过RTOS的任务调度中你就会看到这两个不同介质中的函数,打印不同的log信息,至此说明你自己写的.sct文件成功运行。
工程本身.sct文件其一般在MDK-ARM中。

继续编译流程,然后.o文件和.sct文件就会通过armlink链接器连接在一起,就生成了我们通过keil平台用烧录器直接烧录调试的.axf文件。
到此,大家都已经初步了解了ARM架构编译原理了,如果对这些感兴趣可以深入了解这些工具是如何工作的,这些工具都生存在以下目录中,且大家还可以深入了解每个阶段做了什么事情、什么文件参与。

.axf、elf -< .bin、hex
这些可执行镜像文件通过fromelf工具生成bin、hex文件,而此时这些包含文件头、代码段与数据段、重定位信息、符号表、调试信息等的axf文件就变为了冰凉的机器码bin文件,所以由于bin文件是纯数据流,纯粹的机器码,所以文件大小大大减少,更适合IAP升级的固件包,但是也因为符号、调试信息的缺失,无法逆向还原。
结论,平常我们直接烧录调试的时候都是使用的.axf、.elf文件,只是因为编译器的不同,部分区分,如果要使用Bootloader进行串口、远程OTA升级,就需要更小的bin、hex文件。以下给出更为详细的流程图。

最后通过该文章希望能帮到读者,此文章只是初步探讨编译原理、实际应用,欢迎指出不足和更深入讨论。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)