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

发布者:SereneWhisper最新更新时间:2024-09-19 来源: elecfans关键字:Linux  STM32  hex文件 手机看文章 扫描二维码
随时随地手机看文章

1.为什么不是gcc

在开发stm32的时候,编译工具链要使用gcc-arm-none-eabi,为什么不是gcc呢?这就要说到linux下的交叉编译了,因为我们要在PC机上编译出可以运行在ARM上的程序,使用gcc编译出的是在PC上运行的程序,所以我们要使用gcc-arm-none-eabi进行交叉编译~


2.gcc-arm-none-eabi toolchain 介绍及安装

gcc-arm-none-eabi是一个开源的ARM开发工具链,适用于Arm Cortex-M和Coretex-A系列处理器,包括GNU编译器(GCC),以及GDB,可用于Windows,Linux,MacOS上的交叉编译。
gcc-arm-none-eabi在ubuntu软件源仓库中就有,但是版本比较陈旧:

在此我们从[ARM官方下载链接](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads)选择合适的版本下载(这里我选择Linux64):

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

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

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

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

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

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

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

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

3.从裸机工程开始

3.1.硬件说明

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


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

3.2.新建空的裸机工程

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

startup_stm32f10x_hd.s:从固件库中拷贝,注意不是arm文件夹下的,因为truestudio使用的是gcc编译器,所以我们选择truestudio文件夹下的启动文件;

stm32f10x.h:空文件;

main.c:代码如下:

#include'stm32f10x.h' intmain() { /*开启GPIOB时钟*/ *(unsignedint*)(0x40021000+0x18)|=1<<3;     /* 配置PB0为推挽输出 */     *(unsigned int*)(0x40010c00+0x00) |= 1<<(4*0);     /* PB0输出低电平,点亮绿色LED */     *(unsigned int*)(0x40010c00+0x0c) &= ~(1<<0);     while(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-ostartup_stm32f10x_hd.ostartup_stm32f10x_hd.s

4.2.C文件编译

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

参数描述
-Wall允许输出所有警告


arm-none-eabi-gcc-c-mthumb-mcpu=cortex-m3-g-Wall-omain.omain.c

5.链接

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


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


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

参数描述
-T指定链接文件



arm-none-eabi-gcc-otest.elfmain.ostartup_stm32f10x_hd.o-mthumb-mcpu=cortex-m3-Tstm32_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-objcopytest.elftest.bin arm-none-eabi-objcopytest.elf-Oihextest.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=-Tstm32_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.omain.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即可清除掉所有编译产生的文件。


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

上一篇:STM32F4_TIM输出PWM波形 (可调频率、占空比)
下一篇:探秘STM32U5安全特性|硬件加解密引擎与软件算法对比

推荐阅读最新更新时间:2024-11-12 14:09

STM32 UART DMA实现未知数据长度接收
串口通信是经常使用到的功能,在STM32中UART具有DMA功能,并且收发都可以使用DMA,使用DMA发送基本上大家不会遇到什么问题,因为发送的时候会告知DMA发送的数据长度,DMA按照发送的长度直接发送就OK了,但是使用DMA接收时候就不同了,因为有时候数据接收并不是每一次都是定长的,但是DMA只在接收数据长度和设定数据长度相同的时候才可以触发中断,告诉MCU数据接收完毕,针对这个问题,解决方法如下,有一点复杂,但是很管用。 UART在传输一个字节的时候,首先拉低,传输起始位,然后在是LSB MSB,最后是停止位,停止位是高电平 超时时间 搞过串口通信的都知道,如果串口有协议,一般都是有个超时时间的,超时时间是定义两个帧之间的间
[单片机]
一个单片机ADC的挖坑填坑之旅
本文来解析一个盆友在使用STM32采集电池电压踩过的坑。以STM32F4 的ADC属于逐次逼近SAR 型ADC为例进行分析,参考STM32F405xx Datasheet,对于如何编写ADC程序就不做描述了。 先描述一下坑 采集电池电压,利用两个电阻将电池电压分压,然后送入单片机,当电阻如上分别取4M欧/1M欧时,ADC采集到的ADC值与万用表测得的ADC输入端相差很大,取30K欧以及10k欧时,则相差变小。 盆友咨询我这是为什么?我给出了建议,先卖个关子,先来看看应用最为广泛的STM32单片机的一些特性。 STM32 ADC: STM32 12位ADC是逐次逼近型的模数转换器。它有多达19个多路复用通道,允许它测量来
[单片机]
一个单片机ADC的挖坑填坑之旅
linux-2.6.30.4移植至2440开发板
一、下载linux-2.6.30.4源码,并解压 ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.30.4.tar.gz tar zxvf linux-2.6.30.4.tar.gz 二、在系统中添加对ARM的支持 $vim Makefile 193#ARCH ?= $(SUBARCH) 194#CROSS_COMPILE ?= 195 ARCH=arm 196 CROSS_COMPILE=arm-linux- 三、修改系统时钟 $vim arch/arm/mach-s3c2440/mach-smdk2440.c 系统的外部时钟为12MHz 16
[单片机]
STM32外部中断控制LED
单片机源程序如下: #include stm32f10x.h #include button.h #include led.h #include delay.h #include exti_config.h #define key GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0) int main() { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0) ; button_init(); led_init(); exti_config(); nvic_config(); while(1) {
[单片机]
读取stm32 产品的唯一身份的寄存器
读取stm32 产品的唯一身份的寄存器 voidGet_ChipID(void) { uint32_t temp0,temp1,temp2; temp0 = *(__IO uint32_t*)(0x1FFF7A10); temp1 = *(__IO uint32_t*)(0x1FFF7A14); temp2 = *(__IO uint32_t*)(0x1FFF7A18); // temp0=(*( uint32_t *)0x1FFF7A10); //产品唯一身份标识寄存器(96位) // temp1=(*( uint32_t *)0x1FFF7A14); // temp2=(*( ui
[单片机]
STM32外部中断大问题
问题:一直进入中断,没有触发信号,也一直进入。 描述:开PA0为外部中断,刚刚很好,一个触发信号一个中断,中断函数没有丢,也没有抢跑,开PA1为外部中断也是,都很好,只要能开到3个外部中断以上,就会出现这种情况,明明没有触发外部中断,可是中断服务函数还是不断的++。 问题一:电气噪声和抖动 电气噪声和抖动是常见的问题,可能会导致STM32的外部中断不断触发,即使没有明显的触发信号。以下是一些处理电气噪声和抖动的方法: 1.添加电容滤波器:在外部中断引脚上添加适当大小的电容,以平滑信号并抑制高频噪声。电容的值应根据信号频率和噪声特性进行选择。 2.使用滤波器电路:在外部信号引脚前添加滤波器电路,如低通滤波器,以滤除高频噪
[单片机]
基于STM32定时器的红外遥控数据接收设计原理
一、原理 1、红外发射协议 红外发射协议已经在之前的文章中写过,在此就不赘述。 2、定时器计数和输入捕获 定时器就是按照一个特定的频率对计数值进行加一或减一操作,当数值溢出时则产生一个标志或中断。 定时器的输入捕获就是可以测量输入信号的脉冲宽度。 本次就是通过普通计数和输入捕获的结合来实现的。 3、实现方法 利用定时器记录输入信号高脉冲的时间,通过该时间来判断数据是否是同步头信息、数据 1 或者数据 0。 二、实现 1、配置 定时器2 输入捕获通道 示例代码中使用 PA1 管脚,配置为上拉输入模式,复用功能为定时器2的通道2。 定时器采用普通定时器,定时器2,该定时器具有输入捕获功能。 配置定时器的两种工作模式,一个是普通
[单片机]
基于<font color='red'>STM32</font>定时器的红外遥控数据接收设计原理
ARM-Linux使用SD卡根文件系统
因此指导学员在arm-Linux使用JPT-7模块来跑GPS应用.Nand Flash 空间太小,而且所用的板经常烧不了根文件系统.所以决定用SD卡来跑根文件系统. 1.PC机上格式化SD卡 在桌面的PC机上用SD读卡器操作SD卡: 一般情况下PC机上第一个U盘整体设备结点是/dev/sda,第二个是 /dev/sdb,在RHEL5下它会被自动mount到/media/disk和 /media/disk_1 目录. U盘/dev/sdb上第一个分区是 /dev/sdb1,第二是/dev/sdb2 依此类推. 根文件系统采用符号链接等特性,用FAT32是不行的,这里直接采用标准的ext3的文件系统.在实测时,
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved