Files
stm8loader/Makefile
2025-12-25 21:41:35 +08:00

184 lines
6.0 KiB
Makefile

# Toolchain and programmer paths
TOOLCHAIN ?= /opt/Developer/sdcc/bin
ISPTOOL ?= /opt/Developer/stm8flash
# MCU configuration
MCU = stm8s103f3
ARCH = stm8
# Compilation settings
F_CPU ?= 2000000
TARGET ?= $(lastword $(subst /, ,$(CURDIR)))
# Bootloader mode control
ENABLE_OPTION_BOOTLOADER ?= 1
# Directory structure
BUILD_DIR = objects
SRC_DIR = src
BSP_DIR = bsp
SCRIPTS_DIR = scripts
BSP_INC_DIR = $(BSP_DIR)/inc
SRC_INC_DIR = $(SRC_DIR)/inc
# Source files
SRCS := $(wildcard $(SRC_DIR)/*.c) $(wildcard $(BSP_DIR)/*.c)
ASRCS := $(wildcard $(SRC_DIR)/*.s) $(wildcard $(BSP_DIR)/*.s)
OPT_SRCS := $(wildcard $(SCRIPTS_DIR)/*.opt)
# Compiler tools
CC = $(TOOLCHAIN)/sdcc
LD = $(TOOLCHAIN)/sdld
AS = $(TOOLCHAIN)/sdasstm8
OBJCOPY = $(TOOLCHAIN)/sdobjcopy
# Compiler flags
ASFLAGS = -plosgff
CFLAGS = -m$(ARCH) -p$(MCU) --std-sdcc11
CFLAGS += -DF_CPU=$(F_CPU)UL -I$(SRC_INC_DIR) -I$(BSP_INC_DIR)
CFLAGS += --stack-auto --noinduction --use-non-free
## Disable lospre (workaround for bug 2673)
#CFLAGS += --nolospre
LDFLAGS = -m$(ARCH) -l$(ARCH) --out-fmt-ihx
OPTION_BOOT := 0x480D
RAM_BOOT := 0x0253
OPTFLAGS = -Wl-bOPTION=0x4800 -Wl-bOPTION_BOOT=$(OPTION_BOOT)
B2FLAGS = -Wl-bRAM_BOOT=$(RAM_BOOT)
# Conditionally add ENABLE_OPTION_BOOTLOADER macro
ifneq ($(ENABLE_OPTION_BOOTLOADER),0)
CFLAGS += -DENABLE_OPTION_BOOTLOADER
BOOT_SUFFIX = _boot
else
BOOT_SUFFIX =
endif
# Object files
OBJS = $(patsubst %.c,$(BUILD_DIR)/%.rel,$(notdir $(SRCS))) \
$(patsubst %.s,$(BUILD_DIR)/%.rel,$(notdir $(ASRCS)))
OPT_OBJS = $(patsubst %.opt,$(BUILD_DIR)/%.rel,$(notdir $(OPT_SRCS)))
# Source file search paths
vpath %.c $(sort $(dir $(SRCS)))
vpath %.s $(sort $(dir $(ASRCS)))
vpath %.opt $(sort $(dir $(OPT_SRCS)))
# Default target: build main application and option bytes
all: $(BUILD_DIR)/$(TARGET)$(BOOT_SUFFIX).bin $(BUILD_DIR)/option.bin size
# Compile C files
$(BUILD_DIR)/%.rel: %.c | $(BUILD_DIR)
@mkdir -p $(dir $@)
$(CC) -c $(CFLAGS) $< -o $@
# Compile assembly files
$(BUILD_DIR)/%.rel: %.s | $(BUILD_DIR)
@mkdir -p $(dir $@)
$(AS) $(ASFLAGS) $<
@mv $(SRC_DIR)$*.lst $(SRC_DIR)$*.rel $(SRC_DIR)$*.sym $(BUILD_DIR)/ 2>/dev/null || true
# Compile option byte files
$(BUILD_DIR)/%.rel: %.opt | $(BUILD_DIR)
@mkdir -p $(dir $@)
$(AS) $(ASFLAGS) $<
$(eval SRC_DIR := $(dir $<))
@mv $(SRC_DIR)$*.lst $(SRC_DIR)$*.rel $(SRC_DIR)$*.sym $(BUILD_DIR)/ 2>/dev/null || true
# Link main application
$(BUILD_DIR)/$(TARGET).hex: $(OBJS)
$(CC) $(LDFLAGS) $(OBJS) -o $@
$(BUILD_DIR)/$(TARGET).bin: $(BUILD_DIR)/$(TARGET).hex
$(OBJCOPY) -I ihex --output-target=binary $< $@
# Adjust vector table for bootloader mode (swap reset and trap vectors)
ifeq ($(ENABLE_OPTION_BOOTLOADER),1)
$(BUILD_DIR)/$(TARGET)$(BOOT_SUFFIX).bin: $(BUILD_DIR)/$(TARGET).bin
@echo "Adjusting vector table for bootloader mode..."
@# Extract reset vector (bytes 2-4)
@dd if=$< of=$(BUILD_DIR)/reset.bin bs=1 skip=1 count=3 2>/dev/null
@# Extract trap vector (bytes 5-8)
@dd if=$< of=$(BUILD_DIR)/trap.bin bs=1 skip=4 count=4 2>/dev/null
@# Swap vectors and change first byte of trap vector to 0xAC (JPF)
@# 1. Write trap vector to output (becomes new reset vector)
@cat $(BUILD_DIR)/trap.bin > $@
@# 2. Write reset vector to output (load in wrap vector)
@printf "\xAC" >> $@
@cat $(BUILD_DIR)/reset.bin >> $@
@# 3. Append the rest of the file
@dd if=$< bs=1 skip=8 >> $@ 2>/dev/null
@# Clean up temporary files
@echo " Reset vector moved to trap position with JPF (0xAC) instruction"
@echo " Created bootloader-ready binary: $@"
endif
# Link option bytes separately at address 0x4800
$(BUILD_DIR)/option.hex: $(OPT_OBJS)
$(CC) $(LDFLAGS) $(OPTFLAGS) $(OPT_OBJS) -o $@
$(BUILD_DIR)/option.bin: $(BUILD_DIR)/option.hex
$(OBJCOPY) -I ihex --output-target=binary $< $@
boot2: $(SCRIPTS_DIR)/boot2.s | $(BUILD_DIR)
$(AS) $(ASFLAGS) $<
@mv $(SCRIPTS_DIR)/boot2.lst $(SCRIPTS_DIR)/boot2.rel $(SCRIPTS_DIR)/boot2.sym $(BUILD_DIR)/ 2>/dev/null || true
$(CC) $(LDFLAGS) $(B2FLAGS) $(BUILD_DIR)/boot2.rel -o $(BUILD_DIR)/boot2.hex
$(OBJCOPY) -I ihex --output-target=binary $(BUILD_DIR)/boot2.hex $(SCRIPTS_DIR)/boot2.bin
@# Check boot2 load address
@B2SIZE=$$(wc -c < $(SCRIPTS_DIR)/boot2.bin); \
SIZE1K=$$(($$B2SIZE+$(RAM_BOOT)+(0x4840-$(OPTION_BOOT)-3))); \
if [ $$SIZE1K -ne 1024 ]; then \
echo ""; \
echo "!!! boot2 ram address error!!!"; \
NEW_RAM_BOOT=$$((1024-$$SIZE1K+$(RAM_BOOT))); \
echo " RAM_BOOT: $(RAM_BOOT) -> 0x$$(printf "%X" $$NEW_RAM_BOOT)"; \
fi
# Show sizes of generated binaries
size: $(BUILD_DIR)/$(TARGET)$(BOOT_SUFFIX).bin $(BUILD_DIR)/option.bin
@echo "=== Main application size ==="
@wc -c $(BUILD_DIR)/$(TARGET)$(BOOT_SUFFIX).bin
@echo ""
@echo "=== Option bytes size ==="
@wc -c $(BUILD_DIR)/option.bin
# Create build directory
$(BUILD_DIR):
mkdir -p $@
# Clean build directory
clean:
rm -fR $(BUILD_DIR)
# Flash main application and option bytes via ST-Link
flash: $(BUILD_DIR)/$(TARGET)$(BOOT_SUFFIX).bin $(BUILD_DIR)/option.bin
@echo "Flashing main application..."
$(ISPTOOL) -c stlinkv2 -p $(MCU) -w $(BUILD_DIR)/$(TARGET)$(BOOT_SUFFIX).bin
@echo ""
@echo "Flashing option bytes..."
$(ISPTOOL) -c stlinkv2 -p $(MCU) -s opt -w $(BUILD_DIR)/option.bin
# Flash only option bytes
flash-opt: $(BUILD_DIR)/option.bin
$(ISPTOOL) -c stlinkv2 -p $(MCU) -s opt -w $(BUILD_DIR)/option.bin
# Flash only main application
flash-app: $(BUILD_DIR)/$(TARGET)$(BOOT_SUFFIX).bin
$(ISPTOOL) -c stlinkv2 -p $(MCU) -w $(BUILD_DIR)/$(TARGET)$(BOOT_SUFFIX).bin
# Show help information
help:
@echo "Available targets:"
@echo " all - Build main application and option bytes (default)"
@echo " clean - Remove build directory"
@echo " flash - Flash main application and option bytes"
@echo " flash-app - Flash only main application"
@echo " flash-opt - Flash only option bytes"
@echo " boot2 - Build boot2 application"
@echo " size - Show sizes of generated binaries"
@echo " help - Show this help"
.PHONY: clean all flash flash-opt flash-app size boot2 help