推荐一款 求职面试、刷题学习 的神器:👉*点击跳转* ,快来看看吧!
Use Linker Script File to build an STM32 project from scratch
链接脚本文件,用于控制链接过程,关于编译和链接,可以参考相关文档。以stm32在Linux环境下编译作为示例,项目链接git库地址:
tangquan/test.ld_file.proghttps://gitee.com/tq797/test.ld_file.prog
各种原因,视频参考教程的地址在文件startup_stm32f401xc.c里面。Makefile语法参考文章:
ARM处理器的裸机代码编译可以使用armcc编译器(MDK,收费)或者gcc编译器(免费)。我使用的是arm-none-eabi-gcc,百度一下就能下载。交叉编译器的命名规则比较迷,这里arm表示处理器架构,none表示未指定制造商,eabi表示遵循嵌入式应用二进制接口标准,未指定操作系统。链接脚本的语法参考视频教程。
Makefile:
PROJECT = bare_metal_arm
TARGET = $(PROJECT)
TARGET_ELF = $(PROJECT).elf
TARGET_BIN = $(PROJECT).bin
TARGET_HEX = $(PROJECT).hex
TARGET_MAP = $(PROJECT).map
MACH = cortex-m4
ROOT_DIR = .
OBJ_DIR = $(ROOT_DIR)/obj
OUT_DIR = $(ROOT_DIR)/out
SOURCE_PATH ?= $(ROOT_DIR)
OBJECT_PATH ?= $(OBJ_DIR)
INCLUDE_PATH :=
LINKER_SCRIPT = $(ROOT_DIR)/link.ld
LINKER_SPECS = nano.specs
SOURCES := $(foreach tmp,$(SOURCE_PATH),$(wildcard $(tmp)/*.c $(tmp)/*.cpp))
OBJECTS := $(addsuffix .o,$(addprefix $(OBJECT_PATH)/,$(basename $(notdir $(SOURCES)))))
DEPENDS := $(addsuffix .d,$(OBJECTS))
# $(info SOURCES: $(SOURCES))
# $(info OBJECTS: $(OBJECTS))
# $(info DEPENDS: $(DEPENDS))
CC := arm-none-eabi-gcc
# LD := arm-none-eabi-ld
LD := arm-none-eabi-gcc # use gcc as the linker which can automatically find the dependent libraries
OBJCOPY := arm-none-eabi-objcopy
CFLAGS := -c -mcpu=$(MACH) -mthumb -std=gnu11 -Wall -O0
# CFLAGS += -ffunction-sections
LDFLAG := -mcpu=$(MACH) -mthumb -T link.ld -Wl,-Map=$(OUT_DIR)/$(TARGET_MAP) --specs=$(LINKER_SPECS) -mfloat-abi=soft
# LDFLAG += -Wl,--gc-sections
# LDFLAG += -L/c/gcc-arm-none-eabi-10.3/arm-none-eabi/lib
# LDFLAG += -L/c/gcc-arm-none-eabi-10.3/lib/gcc/arm-none-eabi/10.3.1
all : $(TARGET_ELF)
$(info Build "$(PROJECT)" finished)
$(TARGET_ELF): $(OBJECTS)
# $(info LD $@)
$(LD) $(LDFLAG) -o $(OUT_DIR)/$@ $^
$(OBJCOPY) -O binary -R .note -R .comment -S $(OUT_DIR)/$@ $(OUT_DIR)/$(TARGET_BIN)
-include $(DEPENDS)
$(foreach tmp,$(SOURCES),\
$(eval $(addprefix $(OBJECT_PATH)/,$(addsuffix .o,$(basename $(notdir $(tmp))))):; \
${CC} ${CFLAGS} $(INCLUDE_PATH) \
-MMD -MF $(OBJECT_PATH)/$(basename $(notdir $(tmp))).o.d \
-c -o $(OBJECT_PATH)/$(basename $(notdir $(tmp))).o $(tmp)))
.PHONY : clean setenv
clean:
rm *.o ${TARGET}.* obj/* out/* -rf
linker script file:
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20005000; /* end of 20K RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0; /* required amount of heap */
_Min_Stack_Size = 0x100; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
FLASH(rx):ORIGIN =0x08000000,LENGTH =64K
SRAM(rwx):ORIGIN =0x20000000,LENGTH =20K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .;
_exit = _etext;
}> FLASH
_la_data = LOADADDR(.data);
.data :
{
. = ALIGN(4);
_sdata = .;
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .;
}> SRAM AT> FLASH
.bss :
{
_sbss = .;
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
__bss_end__ = _ebss;
}> SRAM
PROVIDE ( end = _ebss ); /* head starts after the .bss section */
PROVIDE ( _end = _ebss );
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(4);
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(4);
} >SRAM
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
}
编译出来的文件:
关于elf文件和bin文件的区别参考前面的文章:
elf文件可以用于仿真调试,bin文件就可以下载到MCU中去,segger j-flash有linux版本:
SEGGER - The Embedded Experts - Downloads - J-Link / J-Tracehttps://www.segger.com/downloads/jlink/使用JFlash命令可以打开UI界面,和windows上的j-flash是一样的:
下载运行,使用的是STM32F401CCU,调试器为JLink使用SWD接口。使用openocd调试软件,参考文章:
openocd.exe -f interface/jlink.cfg -c "transport select swd" -f target/stm32f4x.cfg
注意使用 -c "transport select swd" 选择端口为SWD,不然连接不上。连接上芯片之后openocd会创建一个服务,使用gdb或者telnet可以连接上openocd,这里我使用gdb。重新打开一个Terminal:
1、打开GDB调试器:
$ arm-none-eabi-gdb
2、连接至openocd服务:
(gdb) target remote 127.0.0.1:3333
3、打开之前生成的elf文件(注意编译的时候需要加上-g选项添加调试信息)
(gdb) file a.elf
4、下载至芯片
(gdb) load a.elf
5、continue执行程序
(gdb) c
推荐一款 求职面试、刷题学习 的神器:👉*点击跳转* ,快来看看吧!