在校学生,求职过程中对方要求在Ubuntu环境下交叉编译stm32的程序,我觉得很有意思,因为之前就听说过可以在Linux环境下运行stm32的程序,因此我决定试一试。
此贴并不是教程,只是记录下作者做这个实验的全过程,如果此贴能帮助别人,作者甚是欣慰。
环境的搭建建议大家下载一个虚拟机而不是给电脑装双系统,并在虚拟机中安装Ubuntu。这里往上有很多的教程且不是本文的重点,因此不赘述。本文使用配置为:
主机:win10
虚拟机:VM15
Ubuntu :16.04(插一句话,个人觉得Ubuntu是最像的Windows的Linux系统)
注意:在Ubuntu环境下进入root权限需要在终端输入 sudo su 。密码不变。
如标题所言,我想直接把正点原子的程序放到Ubuntu环境运行。我身边只有F429的板子,因此就以就以F429的跑马灯为例。
//THUMB指令不支持汇编内联
//采用如下方法实现执行汇编指令WFI
void WFI_SET (void)
{
__asm__ __volatile__("WFI");
}
//关闭所有中断(但是不包括fault和NMI中断)
void INTX_DISABLE(void)
{
__asm__ __volatile__("CPSID I");
__asm__ __volatile__("BX LR");
}
//开启所有中断
void INTX_ENABLE(void)
{
__asm__ __volatile__("CPSIE I");
__asm__ __volatile__("BX LR");
}
//设置栈顶地址
//addr:栈顶地址
void MSR_MSP(u32 addr)
{
__asm__ __volatile__("MSR MSP, r0");
__asm__ __volatile__("BX r14");
}
到此为止,文件的准备工作已经完成。总结一下就是添加startup、STM32F429IGTx_FLASH.ld、cmsis_gcc.h文件,以及修改sys.c文件。
此时,文件夹里的文件应该是这样
makefile的编写是重中之重中之重中之重!!!makefile可以编译文件,生成hex ,bin文件,下载代码,删除中间文件等。上文引用的贴中给出了makefile的代码,但是缺少了启动文件,显然是不完整的。我也是借用别人的模板,加以修改。撰写makefile过程如下:
# F429led_test
######################################
# target the name of project
######################################
TARGET = LED_test
# get current path ,Defined as TOP
TOP=$(shell pwd)
######################################
# building variables
######################################
# debug build?
DEBUG = 1
# optimization
OPT = -O0
#######################################
# paths
#######################################
# source path
# firmware library path
PERIFLIB_PATH =
# Build path Storage location of intermediate files and target files
BUILD_DIR = $(TOP)/OBJ
######################################
# source
######################################
# C sources find all .C files
C_SOURCES = $(shell find ./ -name '*.c')
# ASM sources fidn startup file
ASM_SOURCES = \
startup_stm32f429_439xx.s
######################################
# firmware library
######################################
PERIFLIB_SOURCES =
#######################################
# binaries, Define compile command
#######################################
BINPATH = /home/baishun/Documents/gcc-arm-none-eabi-5_4-2016q3/bin
PREFIX = arm-none-eabi-
CC = $(BINPATH)/$(PREFIX)gcc
AS = $(BINPATH)/$(PREFIX)gcc -x assembler-with-cpp
CP = $(BINPATH)/$(PREFIX)objcopy
AR = $(BINPATH)/$(PREFIX)ar
SZ = $(BINPATH)/$(PREFIX)size
HEX = $(CP) -O ihex
BIN = $(CP) -O binary -S
#######################################
# CFLAGS
#######################################
# cpu
CPU = -mcpu=cortex-m4
# fpu
FPU = -mfpu=fpv4-sp-d16
# float-abi
FLOAT-ABI = -mfloat-abi=hard
# mcu
MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)
# macros for gcc
# AS defines
AS_DEFS =
# C defines
C_DEFS = \
-DSTM32F429xx\
-DUSE_HAL_DRIVER\
# AS includes
AS_INCLUDES =
# C includes
C_INCLUDES = -I $(TOP)/CORE \
-I $(TOP)/HALLIB/STM32F4xx_HAL_Driver/Inc \
-I $(TOP)/HARDWARE \
-I $(TOP)/SYSTEM \
-I $(TOP)/USER \
# compile gcc flags
ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
CFLAGS = $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
ifeq ($(DEBUG), 1)
CFLAGS += -g -gdwarf-2
endif
# Generate dependency information
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)"
#######################################
# LDFLAGS
#######################################
# link script
LDSCRIPT = STM32F429IGTx_FLASH.ld
# libraries
LIBS = -lc -lm -lnosys
LIBDIR =
LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections,--defsym=malloc_getpagesize_P=0x80
# default action: build all
all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin
#######################################
# build the application
#######################################
# list of objects
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
vpath %.c $(sort $(dir $(C_SOURCES)))
# list of ASM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
vpath %.s $(sort $(dir $(ASM_SOURCES)))
$(BUILD_DIR)/%.o: %.c | $(BUILD_DIR)
$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@
$(BUILD_DIR)/%.o: %.s | $(BUILD_DIR)
$(AS) -c $(CFLAGS) $< -o $@
$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS)
$(CC) $(OBJECTS) $(LDFLAGS) -o $@
$(SZ) $@
$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
$(HEX) $< $@
$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
$(BIN) $< $@
$(BUILD_DIR):
mkdir $@
#######################################
# clean up
#######################################
clean:
-rm -fR .dep $(BUILD_DIR)
flash:
openocd -f /home/baishun/Documents/openocd-0.10.0/tcl/interface/stlink-v2.cfg -f /home/baishun/Documents/openocd-0.10.0/tcl/target/stm32f4x.cfg -c init -c halt -c "flash write_image erase $(TOP)/OBJ/LED_test.hex" -c reset -c shutdown
#######################################
# dependencies
#######################################
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
# *** EOF ***
这个makefile看不懂没关系,只需要把一些地方改改就能用了,其他的暂时不需要了解,接下来就是要修改的地方。
1. 编译程序
至此,界面里的文件应该如此
右击打开终端,输入make运行,如果一切顺利的话,代码一直在跑,看着很爽,最后成功之后是这样的
/home/baishun/Documents/gcc-arm-none-eabi-5_4-2016q3/bin/arm-none-eabi-size /home/baishun/Documents/stm32f429_led/OBJ/LED_test.elf
text data bss dec hex filename
7320 12 1948 9280 2440 /home/baishun/Documents/stm32f429_led/OBJ/LED_test.elf
/home/baishun/Documents/gcc-arm-none-eabi-5_4-2016q3/bin/arm-none-eabi-objcopy -O ihex /home/baishun/Documents/stm32f429_led/OBJ/LED_test.elf /home/baishun/Documents/stm32f429_led/OBJ/LED_test.hex
/home/baishun/Documents/gcc-arm-none-eabi-5_4-2016q3/bin/arm-none-eabi-objcopy -O binary -S /home/baishun/Documents/stm32f429_led/OBJ/LED_test.elf /home/baishun/Documents/stm32f429_led/OBJ/LED_test.bin
可以看到hex bin文件已经生成,接下来就是下载。
2. 下载程序
我用STLINK下载器,需要用到USB,打开VM的设置,找到USB,设置如下:之前USB兼容性选择3.0,每次连接STLINK虚拟机会卡死,不得不重启电脑。这里改成2.0就行了。插线后 选择 虚拟机-可移动设备-STLINK-连接虚拟机。之后会看到右下角已连接STLINK然后,在root权限下,输入make flash ,这意思是运行makefile下面的flash命令,成果后
root@baishun-virtual-machine:/home/baishun/Documents/stm32f429_led# make flash
openocd -f /home/baishun/Documents/openocd-0.10.0/tcl/interface/stlink-v2.cfg -f /home/baishun/Documents/openocd-0.10.0/tcl/target/stm32f4x.cfg -c init -c halt -c "flash write_image erase /home/baishun/Documents/stm32f429_led/OBJ/LED_test.hex" -c reset -c shutdown
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select ' .
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 2000 kHz
adapter_nsrst_delay: 100
none separate
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : clock speed 1800 kHz
Info : STLINK v2 JTAG v24 API v2 SWIM v4 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 3.228135
Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints
target halted due to debug-request, current mode: Handler HardFault
xPSR: 0x01000003 pc: 0xfffffffe msp: 0xffffffd8
auto erase enabled
Info : device id = 0x20016419
Info : flash size = 1024kbytes
Info : Single Bank 1024 kiB STM32F42x/43x/469/479 found
target halted due to breakpoint, current mode: Handler HardFault
xPSR: 0x61000003 pc: 0x20000046 msp: 0xffffffd8
wrote 16384 bytes from file /home/baishun/Documents/stm32f429_led/OBJ/LED_test.hex in 1.438171s (11.125 KiB/s)
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
adapter speed: 1800 kHz
shutdown command invoked
可以看到,这里显示了芯片的ID,flash大小等信息,说明连接成果,Info : Unable to match requested speed 2000 kHz, using 1800 kHz 的意思是无法匹配2000KHZ,已换成1800KHz,这个不是错误,可以忽略。
3. 清空文件
此时,打开OBJ文件,会发现里面有很多.o文件,可以运行 make clean删除OBJ文件。
在使用Ubuntu的过程中,有几个点说明一下: