Ubuntu 环境下交叉编译运行正点原子的程序

Ubuntu 环境下交叉编译运行正点原子的程序

在校学生,求职过程中对方要求在Ubuntu环境下交叉编译stm32的程序,我觉得很有意思,因为之前就听说过可以在Linux环境下运行stm32的程序,因此我决定试一试。
此贴并不是教程,只是记录下作者做这个实验的全过程,如果此贴能帮助别人,作者甚是欣慰。

1.环境搭建

环境的搭建建议大家下载一个虚拟机而不是给电脑装双系统,并在虚拟机中安装Ubuntu。这里往上有很多的教程且不是本文的重点,因此不赘述。本文使用配置为:
主机:win10
虚拟机:VM15
Ubuntu :16.04(插一句话,个人觉得Ubuntu是最像的Windows的Linux系统)
注意:在Ubuntu环境下进入root权限需要在终端输入 sudo su 。密码不变。

2.基本配置

  1. 建议先安装VMtools,这在后面复制文件、调整界面大小方便很多,方法百度。
  2. 环境搭建完之后,我们需要用到gcc-arm-none-eabi这个软件,具体过程可参考gcc-arm-none-eabi的安装,这个是实现交叉编译的核心步骤,里面主要是编译文件的命令。注意:在此博客中有这一步骤: “打开profile文件后我们在其末尾添加路径 ” 在执行这一步骤时,先进入到bin文件,可使用PWD直接获得路径并复制在profile文件中,可保证路径的正确。
  3. 下载器的安装 有人用STLINK,有人用JTAK,那就不如直接用openocd下载程序,可以理解它就是个万精油,什么下载器都可以下载程序,下载教程为openocd的下载安装 。 注意:安装的时候要在root下进行,以及在后序下载程序的时候也要在root下载

3.项目的创建

如标题所言,我想直接把正点原子的程序放到Ubuntu环境运行。我身边只有F429的板子,因此就以就以F429的跑马灯为例。

  1. 在Ubuntu中的document中新建一个文件夹
    Ubuntu 环境下交叉编译运行正点原子的程序_第1张图片
  2. 打开正点原子的跑马灯程序,把所有的文件夹复制进去,对是所有。其实user中的.uvprojx文件可以不要,因为这个是用keil打开的。
  3. 除此之外,我们还需要几个文件,首先是startup_stm32f429_439xx.s启动文件,也许你会疑惑,这个文件在正点原子文件里有啊,怎么还要添加。事实上,打开正点原子这个startup后你会看到Ubuntu 环境下交叉编译运行正点原子的程序_第2张图片
    这个文件仅仅是在MDK环境下才有效,而我们要在gcc下交叉编译就不能用这个文件。所使用的的startup文件以及其他文件在下面的百度云。另一个文件是STM32F429IGTx_FLASH.ld连接文件,还有cmsis_gcc.h(带gcc就知道什么意思了,放在CORE中)。
  4. 修改sys.c 在sys.c文件的最后 把代码改成`
//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文件。
此时,文件夹里的文件应该是这样
Ubuntu 环境下交叉编译运行正点原子的程序_第3张图片

4.makefile的编写

makefile的编写是重中之重中之重中之重!!!makefile可以编译文件,生成hex ,bin文件,下载代码,删除中间文件等。上文引用的贴中给出了makefile的代码,但是缺少了启动文件,显然是不完整的。我也是借用别人的模板,加以修改。撰写makefile过程如下:

  1. 在上述文件位置右击-newdocument-emptydocument,之后重命名为makefile,打开后找到右下角的文件类型,选择Makefile。这样就可以生成一个makefile文件了;
  2. 代码如下:
# 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. 把当前路径定义为TOP,这样在后面可直接拿来用。
  2. BUILD_DIR 是生成的中间文件以及最终的hex等文件的存储位置,这里是OBJ,也可换成其他的文件夹。
  3. ASM_SOURCES 就是startup文件了,如果用F1的板子,就把这里换成F1的启动文件。
  4. MUC 是板子的配置,这里是m4,如果F1就是m3,其他配置可百度。
  5. LDSCRIPT 是连接文件,和startup同理。
  6. C_DEFS 很重要,用keil打开跑马灯工程Ubuntu 环境下交叉编译运行正点原子的程序_第4张图片
    点击上面的魔术棒会出来这个界面,其中Define中的定义就是C_DEFS 要定义的,直接复制就行了。下面的includ path 就是 C_INCLUDES ,这应该很好理解。
  7. 上述步骤已经把要编译的文件准备好了,如果一切顺利就会生成hex文件,接下来就是下载程序。在最后的makefile中的flash命令中,先配置了stlink,再用stlink下载程序。如果用jlink只需换一下就行了。这里每个人的路径可能不一样。可以先在Ubuntu home下搜索tcl定位到路径后 再终端输入pwd获得路径。
    注意: 在makefile中,换行符 \ 后面不能有空格,每个命令要用tab键开始,目前,要修改的地方就这些了,如果想要看懂全部代码可百度。

5.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,设置如下:Ubuntu 环境下交叉编译运行正点原子的程序_第5张图片之前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文件。

6 总结

在使用Ubuntu的过程中,有几个点说明一下:

  1. 主机复制文件到虚拟机最好一次复制一个文件,可将多个文件压缩成一个压缩包再进行复制,否则虚拟机会卡死,只能重启。
  2. 之前就知道Linux有很高的可移植性,可具体体现在哪呢?原来是这样啊。
  3. 2020.6.9完成跑马灯,以后如果有什么问题会补充。
  4. 我们都是在沙滩上捡贝壳的孩子,如果有问题可以评论。

你可能感兴趣的:(Ubuntu 环境下交叉编译运行正点原子的程序)