3、Makefile 和 链接脚本

当前需要修改代码目录如下,通过makefile来编译,build.sh中指定toolchain,调用make,runqemu.sh 和 rungdb.sh 用于运行 elf 和调试。

root@iZj6ccyu2ndokc2ujnox0tZ:~/workspace/code/baremetal/baremetal-m3# tree
.
├── bm.lds
├── build.sh
├── Makefile
├── README.md
├── rungdb.sh
├── runqemu.sh
└── src
        ├── board
        ├── core
        │   └── start.S
        └── test

3.1 Makefile

参考: https://makefile-study.readthedocs.io/zh_CN/latest/

# ------------------------
# Generic Makefile
# ------------------------

# Project name
Target = target
ELF = ${Target}.elf

CPU = cortex-m3
TARGET_ARCH     = -mcpu=$(CPU)

# Compile command and flag
CC = arm-none-eabi-gcc
CFLAG = -Wall -mthumb
ASFLAGS =

# Linker command and flag
LINKER = arm-none-eabi-gcc
LDFLAGS = -nostdlib -e 0x0 -Ttext=0x0 -mcpu=cortex-m3

DUMP = arm-none-eabi-objdump
OBJCOPY = arm-none-eabi-objcopy

# Dir
SRC_DIR = src
OBJ_DIR = obj
BIN_DIR = output

# Source directorys, find all source directory ,like src/board src/common
SRC_DIRS        = $(shell find src -maxdepth 3 -type d)

# OBJ_DIRS, change src to obj, match the source directorys, like obj/board obj/common
OBJ_DIRS        := $(foreach dir,$(SRC_DIRS),$(subst src,obj,$(dir)))

# INCLUDES, add source directorys to include, like -Isrc/board -Isrc/common
INCLUDES        = $(foreach dir, $(SRC_DIRS),-I$(dir))

# Source files, c srouce files and asmeble source files. like src/board/test.c src/board/test.S
C_SRC   += $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.c))
S_SRC   := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.S))

# OBJ files, object files. like obj/board/test.o obj/board/test.o
OBJ_S_FILES     := $(foreach file,$(S_SRC),$(patsubst %.S,%.o,$(subst src,obj,$(file))))
OBJ_C_FILES     := $(foreach file,$(C_SRC),$(patsubst %.c,%.o,$(subst src,obj,$(file))))
OBJ_FILES       := $(OBJ_S_FILES) $(OBJ_C_FILES)

# 1. Create obj directorys and bin directory
# 2. Comple all OBJ_FILES, from .c .S to .o
# 3. Link all .o to binary target
$(BIN_DIR)/$(ELF) : $(OBJ_DIRS) $(BIN_DIR) $(OBJ_FILES)
        $(LINKER)  $(LDFLAGS) -o $@ $(OBJ_FILES)
        $(DUMP) -xD $@ > $(BIN_DIR)/$(Target).asm
        $(OBJCOPY) -O binary  $@  $(BIN_DIR)/$(Target).bin
        xxd $(BIN_DIR)/$(Target).bin > $(BIN_DIR)/$(Target).hex
        @echo "Linking complete!"

# Compile .c to .o
obj/%.o : src/%.c
        @echo Compiling $< to $@
        $(CC) $(CFLAG) $(INCLUDES) $(TARGET_ARCH) -c $< -o $@

# Compile .S to .o
obj/%.o : src/%.S
        @echo $@ Compiling $< to $@
        $(CC) $(ASFLAGS) -c $(TARGET_ARCH) $< -o $@


PHONY: clean
clean :
        rm -rf $(BIN_DIR) $(OBJ_DIR)
        @echo "Cleanup complete!"

$(OBJ_DIRS):
        mkdir -p $@

$(BIN_DIR):
        mkdir -p $@

Note

Makefile 基本思路是查找src目录下所有 .c .S 文件,先各自编译成 .o, 再链接成 elf。

3.2 链接脚本

之前我们是在链接时,直接指定参数 -e 0x0 -Ttext=0x0 来告诉gcc 代码段和入口地址的。现在我们需要把这部分用链接脚本来实现。
新建bm.lsd文件。
__RAM_BASE = 0x0;
__RAM_SIZE = 0x10000;


MEMORY
{
        RAM (rwx) : ORIGIN = __RAM_BASE, LENGTH = __RAM_SIZE
}

ENTRY(Reset_Handler)

SECTIONS
{
        .text :
        {
                *(.text*)
        } > RAM
}
#LDFLAGS        = -nostdlib -e 0x0 -Ttext=0x0 -mcpu=cortex-m3
LDFLAGS = -nostdlib -mcpu=cortex-m3 -T bm.lds

Note

只有一个section,把代码段放入到ram中,注意这个entry定义了入口,Reset_Handler需要在start.S中定义为globl( .globl Reset_Handler)。

基于现在的代码框架,编译和调试都用shell命令来管理,比较方便了。

./build.sh a
./runqemu.sh --gdb
./rungdb.sh