一、先搭建好环境:
二、需要的文件:
(1)启动文件:startup_stm32f10x_hd.s
(2)链接文件:stm32_flash.ld
(3)c源码文件:main.c
(4)头文件:stm32f10x.h
(5)Makefile
完整工程文件下载:Linux下STM32编译、烧录示例工程
打开下载的标准库:STM32F10x_StdPeriph_Lib_V3.5.0,STM32F10x标准库V3.5(CSDN)因为truestudio使用的是gcc编译器,所以我们使用其文件夹的文件。
三、启动文件
所在目录:STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\TrueSTUDIO
四、链接文件
所在目录:STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Template\TrueSTUDIO
文件夹下是各种官方开发板的例子:
STM3210B-EVAL | Linker script for STM32F103VB Device with 128KByte FLASH, 20KByte RAM |
STM3210C-EVAL | Linker script for STM32F107VC Device with 256KByte FLASH, 64KByte RAM |
STM3210E-EVAL | Linker script for STM32F103ZE Device with 512KByte FLASH, 64KByte RAM |
STM3210E-EVAL_XL | Linker script for STM32F103ZG Device with 1MByte FLASH, 96KByte RAM |
STM32100B-EVAL | Linker script for STM32F100VB Device with 128KByte FLASH, 8KByte RAM |
STM32100E-EVAL | Linker script for High-density value line Devices (STM32F100xE) with 512KByte FLASH, 32KByte RAM |
stm32f10x_flash_extsram.ld | Linker script for STM32F10x XL-density Devices with 1MByte FLASH, 96KByte RAM |
如果没有对应的芯片,需要根据使用的芯片修改 stm32_flash.ld 文件,可以修改RAM、ROM、堆栈大小等。
五、main.c
一个简单的操作寄存器点灯程序:
#include "stm32f10x.h"
int main(void)
{
// 开启GPIOB 端口时钟
RCC_APB2ENR |= (1<<3);
//清空控制PB0的端口位
GPIOB_CRL &= ~( 0x0F<< (4*0));
// 配置PB0为通用推挽输出,速度为10M
GPIOB_CRL |= (1<<4*0);
// PB0 输出 低电平
GPIOB_ODR &= ~(1<<0);
while(1);
}
// 函数为空,目的是为了骗过编译器不报错
void SystemInit(void)
{
}
六、stm32f10x.h
寄存器地址及结构体定义
/*本文件用于添加寄存器地址及结构体定义*/
/*片上外设基地址 */
#define PERIPH_BASE ((unsigned int)0x40000000)
/*APB2 总线基地址 */
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
/* AHB总线基地址 */
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
/*GPIOB外设基地址*/
#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00)
/* GPIOB寄存器地址,强制转换成指针 */
#define GPIOB_CRL *(unsigned int*)(GPIOB_BASE+0x00)
#define GPIOB_CRH *(unsigned int*)(GPIOB_BASE+0x04)
#define GPIOB_IDR *(unsigned int*)(GPIOB_BASE+0x08)
#define GPIOB_ODR *(unsigned int*)(GPIOB_BASE+0x0C)
#define GPIOB_BSRR *(unsigned int*)(GPIOB_BASE+0x10)
#define GPIOB_BRR *(unsigned int*)(GPIOB_BASE+0x14)
#define GPIOB_LCKR *(unsigned int*)(GPIOB_BASE+0x18)
/*RCC外设基地址*/
#define RCC_BASE (AHBPERIPH_BASE + 0x1000)
/*RCC的AHB1时钟使能寄存器地址,强制转换成指针*/
#define RCC_APB2ENR *(unsigned int*)(RCC_BASE+0x18)
七、编译步骤
在 gcc-arm-none-eabi/share/doc/gcc-arm-none-eabi 文件夹的readme.txt 有详细的指令说明。
(1)启动文件编译(不进行预处理,并且正常提示告警信息)
arm-none-eabi-gcc -c -mthumb -mcpu=cortex-m3 -g -Wa,--warn -o startup_stm32f10x_hd.o startup_stm32f10x_hd.s
-mthumb:编译全编译成thumb指令集
-mcpu=cortex-m3 :cpu内核选择
-Wa,--warn 向汇编器Assembler传递参数,正常提示告警信息
-W或–no-warn | 关闭所有告警 |
–fatal-warnings | 将所有的警告提示为错误 |
–warn | 正常提示告警信息 |
启动文件一般是由汇编写成,汇编文件的格式有.S和.s之分:
- .S:表明文件中含有预处理指令(比如#define),需要先进行处理;
- .s:表明文件不需要处理,可以直接编译;
之前添加的启动文件是小写.s,所以直接进行编译。如果使用的是.S文件,需要带上-x assembler-with-cpp参数先进行预处理。
编译后生成 startup_stm32f10x_hd.o 文件
(2)c源文件编译
arm-none-eabi-gcc -c -mthumb -mcpu=cortex-m3 -g -Wall -o main.o main.c
-wall | 输出所有警告 |
编译后生成 main.o 文件
(3)链接
详细参数说明参考 gcc-arm-none-eabi\share\doc\gcc-arm-none-eabi\pdf 文件夹下的 ld.pdf 。
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
链接器根据 stm32_flash.ld 文件链接 startup_stm32f10x_hd.o 和 main.o 两个文件,生成包含调试信息的elf文件。
-T | 指定链接文件 |
链接后生成 test.elf 和 test.map 文件
(4)生成 bin 和 hex 文件
arm-none-eabi-objcopy test.elf test.bin
arm-none-eabi-objcopy test.elf -Oihex test.hex
利用arm-none-eabi-objcopy
工具可以将elf文件转化为适合于单片机的bin文件和hex文件,其中参数-O
(大写o)用于指定输出文件的格式(默认是bin格式)
生成 test.hex 和 test.bin 文件
八、Makefile
集合以上的步骤编写Makefile
TARGET=test
CROSS_COMPILE ?= arm-none-eabi-
CC := $(CROSS_COMPILE)gcc
OBJCOPY := $(CROSS_COMPILE)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
即可清除掉所有编译产生的文件。
九、下载烧录
ST-LINK:
使用的命令
- openocd -f
<接口配置文件>
-f<目标芯片配置文件>(绝对路径)
- telnet localhost 4444
- >halt
- >flash write_image erase
<烧录文件>(绝对路径)
- >reset
(1)配置使用 stlink 连接到 stm32f1x 芯片
openocd -f /usr/local/share/openocd/scripts/interface/stlink-v2.cfg -f /usr/local/share/openocd/scripts/target/stm32f1x.cfg
(2)使用telnet连接到openocd
打开另外一个终端(上一个终端不要关闭),输入以下命令:
telnet localhost 4444
(3)使用以下命令烧录
命令 | 描述 |
---|---|
halt | 芯片挂起,相当于关机 |
flash write_image erase <烧录文件> | 将文件下载到芯片flash(使用绝对路径) |
reset | 芯片复位 |
flash write_image erase /home/pjw/STM32/project/LED
(4)第一个终端会相应输出信息:
九、修改Makefile,实现一键下载
(1)修改Makefile:
定义openocd 的路径,烧录器,芯片型号:
TARGET=test
CROSS_COMPILE ?= arm-none-eabi-
CC := $(CROSS_COMPILE)gcc
OBJCOPY := $(CROSS_COMPILE)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
INTERRFACE_CFG=/usr/local/share/openocd/scripts/interface/stlink-v2.cfg
TARGET_CFG=/usr/local/share/openocd/scripts/target/stm32f1x.cfg
PWD=$(shell pwd)
$(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).*
downlad:
openocd -f $(INTERRFACE_CFG) -f $(TARGET_CFG) -c init -c halt -c "flash write_image erase $(PWD)/$(TARGET).bin" -c reset -c shutdown
(2)使用 make download 命令即可下载,如图,下载成功
参考: