良许Linux教程网 干货合集 Linux下开发STM32:使用gcc-arm-none-eabi工具链编译生成bin、hex文件

Linux下开发STM32:使用gcc-arm-none-eabi工具链编译生成bin、hex文件

1. 选择gcc-arm-none-eabi的缘由

当涉及到STM32微控制器的开发时,关于编译工具的问题就浮出水面。我们为什么不直接使用gcc,而是倾向于采用gcc-arm-none-eabi呢?原因就在于Linux环境下的交叉编译需求。由于我们的目标是在个人电脑上生成能够在ARM架构处理器上运行的代码,直接使用gcc所得到的结果是为PC机环境设计的执行文件。为了解决这个不匹配问题,我们转而采用gcc-arm-none-eabi这一工具链来执行交叉编译

2. 关于gcc-arm-none-eabi工具链的概述与安装指南

gcc-arm-none-eabi是专为ARM Cortex-M和Cortex-A系列处理器设计的一个开源工具链,它集成了GNU编译器集(GCC)和GDB调试器,支持在Windows,Linux,以及MacOS平台上进行交叉编译工作。

尽管在Ubuntu的软件仓库中可以找到gcc-arm-none-eabi的软件包,但仓库中的版本可能相对滞后:

image-20231226200748835
image-20231226200748835

在此我们从ARM官方下载链接选择合适的版本下载(这里我选择Linux64):

image-20231226200752580
image-20231226200752580

解压下来是tar.ba2格式包,使用命令tar -jxf 解压到我们要安装的目录:

image-20231226200755545
image-20231226200755545

为了以后使用方便,将文件夹重命名:

图片
图片

它下面的bin目录就是我们要使用的编译工具链:

image-20231226200800449
image-20231226200800449

share目录的doc下包含了大量的使用帮助文档,可以先略读一二,特别是readme.txt

图片
图片

接下来我们要将bin目录添加到环境变量,这样可以直接在命令行输入要使用的工具名,然后系统就可以找到该工具,在此我们仅为当前用户添加环境变量,使用vim ~/.bashrc编辑当前用户配置文件,在最后添加export PATH=$PATH:/home/mculover666/gcc-arm-none-eabi/bin

image-20231226200807500
image-20231226200807500

然后使用命令source ~/.bashrc更新系统路径,使添加的环境变量立即生效:

image-20231226200810311
image-20231226200810311

然后输入命令arm-none,然后按三下Tab(一定不要输入全部),检查系统是否可以自动补全:

image-20231226200814572
image-20231226200814572

如果系统可以提示,说明环境变量配置成功,可以开心的使用arm-none-eabi工具链啦~

3.从裸机工程开始

3.1.硬件说明

这里我使用的是野火霸道开发板,板载芯片为STM32F103ZET6,下载器使用e-link,这个下载器使用CMSIS-DAP下载程序,同时并带有一个串口,非常好用~

image-20231226200818004
image-20231226200818004

板载RGB-LED的原理图如图所示:

image-20231226200821577
image-20231226200821577

3.2.新建空的裸机工程

首先新建一个文件夹mkdir 00-template-reg用来存放整个工程,然后整个工程包含三个文件:

  • startup_stm32f10x_hd.s:从固件库中拷贝,注意不是arm文件夹下的,因为truestudio使用的是gcc编译器,所以我们选择truestudio文件夹下的启动文件;
  • stm32f10x.h:空文件;
  • main.c:代码如下:
#include "stm32f10x.h"

int main()
{
    /* 开启GPIOB时钟 */
    *(unsigned int*)(0x40021000+0x18) |= 1while(1);
}
void SystemInit(void)
{

}

4.编译

接下来就是激动人心的编译步骤了~编译的时候有两种文件,一种是汇编启动文件,一种是c源文件,接下来分别编译:
首先需要说明一些编译任何一个文件都需要带上的参数:

参数 说明
-mthumb 表明使用的指令集(必需)
-mcpu=cortex-m3 表明芯片内核(必需)
-g 产生调试信息

4.1.启动文件编译

启动文件一般是由汇编写成,此处需要注意的是,汇编文件的格式有.S.s之分:

  • 大写S:表明文件中含有预处理指令(比如#define),需要先进行处理
  • 小写s:表明文件不需要处理,可以直接编译;

之前我们添加的启动文件是小写.s,所以直接进行编译,另外说一下,如果使用的是.S文件,那么需要带上-x assembler-with-cpp参数。

接下来说明一些汇编文件gcc编译器使用的参数:

参数 说明
-x assembler-with-cpp 先对文件进行预处理
-Wa,option 向汇编器Assembler传递参数

注:可以向汇编器传递的参数:

参数 说明
-W或–no-warn 关闭所有告警
–fatal-warnings 将所有的警告提示为错误
–warn 正常提示告警信息

所以,接下来我们可以使用如下的参数组合来编译启动文件(不进行预处理,并且正常提示告警信息):

arm-none-eabi-gcc -c -mthumb -mcpu=cortex-m3 -g -Wa,--warn -o startup_stm32f10x_hd.o startup_stm32f10x_hd.s
image-20231226200825964
image-20231226200825964

4.2.C文件编译

因为main.c中没有特殊的东西,只是两个函数,所以简单的编译一下就可以了:

参数 描述
-Wall 允许输出所有警告
arm-none-eabi-gcc -c -mthumb -mcpu=cortex-m3 -g -Wall -o main.o main.c

5.链接

链接重要的部分有两点:链接文件传递给链接器的参数
链接文件在固件库中给的示例工程中有,在下面这个目录:

image-20231226200828322
image-20231226200828322

其中stm32_flash.ld是针对于STM32F103ZE的链接文件,如果是别的芯片,需要进行修改,将它复制到我们的工程中去:

图片
图片

然后就要让链接器开始根据stm32_flash.ld这个文件对startup_stm32f10x_hd.omain.o这两个文件开始链接,生成包含了调试信息的elf文件,同时,我们还需要给链接器传递一些参数:

参数 描述
-T 指定链接文件
arm-none-eabi-gcc -o test.elf main.o startup_stm32f10x_hd.o -mthumb -mcpu=cortex-m3 -T stm32_flash.ld -specs=nosys.specs -static -Wl,-cref,-u,Reset_Handler -Wl,-Map=test.map -Wl,--gc-sections -Wl,--defsym=malloc_getpagesize_P=0x80 -Wl,--start-group -lc -lm -Wl,--end-group

6.生成bin文件和hex文件

利用arm-none-eabi-objcopy工具可以将elf文件转化为适合于单片机的bin文件和hex文件,其中参数-O(大写o)用于指定输出文件的格式(默认是bin格式)

arm-none-eabi-objcopy test.elf test.bin
arm-none-eabi-objcopy test.elf -Oihex test.hex

7.编写一个makefile雏形

TARGET=test
CC=arm-none-eabi-gcc
OBJCOPY=arm-none-eabi-objcopy
RM=rm -f
CORE=3
CPUFLAGS=-mthumb -mcpu=cortex-m$(CORE)
LDFLAGS = -T stm32_flash.ld -Wl,-cref,-u,Reset_Handler -Wl,-Map=$(TARGET).map -Wl,--gc-sections -Wl,--defsym=malloc_getpagesize_P=0x80 -Wl,--start-group -lc -lm -Wl,--end-group
CFLAGS=-g -o
$(TARGET):startup_stm32f10x_hd.o main.o
    $(CC) $^ $(CPUFLAGS) $(LDFLAGS) $(CFLAGS) $(TARGET).elf
startup_stm32f10x_hd.o:startup_stm32f10x_hd.s
    $(CC) -c $^ $(CPUFLAGS) $(CFLAGS) $@
main.o:main.c
    $(CC) -c $^ $(CPUFLAGS) $(CFLAGS) $@

bin:
    $(OBJCOPY) $(TARGET).elf $(TARGET).bin
hex:
    $(OBJCOPY) $(TARGET).elf -Oihex $(TARGET).hex
clean:
    $(RM) *.o $(TARGET).*
  • 使用命令make编译生成elf文件;
  • 使用命令make bin将elf文件转化生成bin文件;
  • 使用命令make hex将elf文件转化生成hex文件;
  • 使用命令make clean即可清除掉所有编译产生的文件。

以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !

137e00002230ad9f26e78-265x300
本文由 良许Linux教程网 发布,可自由转载、引用,但需署名作者且注明文章出处。如转载至微信公众号,请在文末添加作者公众号二维码。
良许

作者: 良许

良许,世界500强企业Linux开发工程师,公众号【良许Linux】的作者,全网拥有超30W粉丝。个人标签:创业者,CSDN学院讲师,副业达人,流量玩家,摄影爱好者。
上一篇
下一篇

发表评论

联系我们

联系我们

公众号:良许Linux

在线咨询: QQ交谈

邮箱: yychuyu@163.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部