一、先搭建好環境:
二、需要的文件:
(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)鏈接
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
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
即可清除掉所有編譯產生的文件。
九、下載燒錄
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
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
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 命令即可下載,如圖,下載成功
參考: