Files
2026-08-03 16:37:10 +08:00

267 lines
8.0 KiB
Makefile

# Betaflight N6 OpenBootloader build.
#
# Architecture:
# - Skeleton sources here: main.c (boot decision), system_stm32n6xx_obl.c,
# stm32n6xx_hal_msp.c, stm32n6xx_it.c, startup, linker, flash driver.
# - The OBL DFU stack (CubeN6 Middlewares/ST/OpenBootloader + USB Device
# Library + the Application/OpenBootloader/USB_Device glue) is pulled
# in via VPATH from the submodule, NOT modified or copied — so re-
# pulling CubeN6 keeps us up to date. Currently disabled (dfu_stub.c
# stands in) until task #6 wires it up.
#
# Usage:
# make produce obl.elf and obl.bin (skeleton only)
# make signed re-sign into prebuilt/obl_signed.stm32
# make OBL_FLASH_DRIVER=mx66uw1g45g pick driver source (default)
# make clean
ROOT := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))/../../../..)
TOOLCHAIN_BIN := $(ROOT)/tools/arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi/bin
PREFIX := $(if $(wildcard $(TOOLCHAIN_BIN)/arm-none-eabi-gcc),$(TOOLCHAIN_BIN)/,)arm-none-eabi-
CC := $(PREFIX)gcc
AS := $(PREFIX)gcc -x assembler-with-cpp
LD := $(PREFIX)gcc
OBJCOPY := $(PREFIX)objcopy
SIZE := $(PREFIX)size
OBL_FLASH_DRIVER ?= mx66uw1g45g
HAL_DIR := $(ROOT)/lib/modules/STM32N6/Drivers/STM32N6xx_HAL_Driver
CMSIS_ST := $(ROOT)/lib/modules/STM32N6/Drivers/CMSIS/Device/ST/STM32N6xx/Include
CMSIS := $(ROOT)/lib/modules/STM32N6/Drivers/CMSIS/Include
OBL_MW := $(ROOT)/lib/modules/STM32N6/Middlewares/ST/OpenBootloader
OBL_USBLIB := $(OBL_MW)/STM32_USB_Device_Library
OBL_PROJ := $(ROOT)/lib/modules/STM32N6/Projects/STM32N6570-DK/Applications/OpenBootloader
INCLUDES := \
-I. \
-Iflash \
-I$(ROOT)/src/platform/STM32/include \
-I$(HAL_DIR)/Inc \
-I$(CMSIS_ST) \
-I$(CMSIS) \
-I$(OBL_MW)/Core \
-I$(OBL_MW)/Util \
-I$(OBL_MW)/Modules/Mem \
-I$(OBL_MW)/Modules/USB \
-I$(OBL_MW)/Modules/USART \
-I$(OBL_USBLIB)/Core/Inc \
-I$(OBL_USBLIB)/Class/DFU/Inc \
-I$(OBL_PROJ)/Core/Inc \
-I$(OBL_PROJ)/OpenBootloader/App \
-I$(OBL_PROJ)/OpenBootloader/Target \
-I$(OBL_PROJ)/USB_Device/App \
-I$(OBL_PROJ)/USB_Device/Target
DEFINES := \
-DSTM32N657xx \
-DUSE_HAL_DRIVER \
-DHSE_VALUE=48000000
# Bring-up override: make OBL_FORCE_DFU=1 to build an OBL that always
# enters DFU regardless of nor0 contents.
ifdef OBL_FORCE_DFU
DEFINES += -DOBL_FORCE_DFU
endif
# Bring-up override: make OBL_FORCE_RECOVERY=1 to build an OBL that
# always enters Recovery mode (exposes nor0 from 0x70000000 so OBL+BF
# can be reinstalled). RAM-load only — never sign and flash this.
ifdef OBL_FORCE_RECOVERY
DEFINES += -DOBL_FORCE_RECOVERY
endif
# OBL is the only S-state code on the device, so build it with the Cortex-M
# Security Extensions enabled. -mcmse sets __ARM_FEATURE_CMSE=3, which makes
# the ST CMSIS headers select the secure-alias peripheral base addresses
# (RCC, RIFSC, GPIOx, DBGMCU, TAMP, PWR, RTC, EXTI, GPDMA1, HPDMA1, ...). All
# peripheral access in OBL therefore goes through the S aliases naturally
# via the CMSIS struct pointers instead of hand-coded addresses.
ARCH_FLAGS := -mthumb -mcpu=cortex-m55 -mfloat-abi=hard -mfpu=fpv5-d16 -mcmse
CFLAGS := \
$(ARCH_FLAGS) \
-Os -g3 \
-ffunction-sections -fdata-sections \
-Wall -Wextra \
-Wno-unused-parameter \
-std=gnu11 \
$(INCLUDES) $(DEFINES)
ASFLAGS := $(ARCH_FLAGS) -g3 $(INCLUDES) $(DEFINES)
LDSCRIPT := STM32N657XX_OBL.ld
LDFLAGS := \
$(ARCH_FLAGS) \
-T$(LDSCRIPT) \
-nostartfiles \
-specs=nano.specs -specs=nosys.specs \
-Wl,--gc-sections \
-Wl,-Map=obl.map \
-Wl,--print-memory-usage
LOCAL_C_SRCS := \
main.c \
obl_app.c \
app_openbootloader.c \
stm32n6xx_hal_msp.c \
stm32n6xx_it.c \
system_stm32n6xx_obl.c \
external_memory_interface.c \
otp_interface.c \
usbd_conf.c \
usbd_desc.c \
usbd_dfu.c \
usbd_dfu_if.c \
flash/$(OBL_FLASH_DRIVER).c
HAL_C_SRCS := \
stm32n6xx_hal.c \
stm32n6xx_hal_cortex.c \
stm32n6xx_hal_rcc.c \
stm32n6xx_hal_rcc_ex.c \
stm32n6xx_hal_pwr.c \
stm32n6xx_hal_pwr_ex.c \
stm32n6xx_hal_gpio.c \
stm32n6xx_hal_xspi.c \
stm32n6xx_hal_dma.c \
stm32n6xx_hal_dma_ex.c \
stm32n6xx_hal_iwdg.c \
stm32n6xx_hal_pcd.c \
stm32n6xx_hal_pcd_ex.c \
stm32n6xx_ll_usb.c
# OBL middleware (protocol-agnostic core, memory mgr, USB transport bindings,
# utilities). Pulled in unchanged from the CubeN6 submodule.
OBL_MW_C_SRCS := \
Core/openbl_core.c \
Util/openbl_util.c \
Modules/Mem/openbl_mem.c \
Modules/USB/openbl_usb_cmd.c
# USB Device Library (DFU class + core). Note: usbd_dfu.c is overridden
# locally (see LOCAL_C_SRCS) — the Betaflight copy patches the per-alt
# iInterface descriptor lookup so all alts use DfuInterface->pStrDesc.
OBL_USB_C_SRCS := \
Core/Src/usbd_core.c \
Core/Src/usbd_ctlreq.c \
Core/Src/usbd_ioreq.c
# Application-level glue from the reference OBL project. We provide our
# own external_memory_interface.c (above), so that submodule file is NOT
# listed here.
OBL_APP_C_SRCS := \
OpenBootloader/Target/common_interface.c \
OpenBootloader/Target/iwdg_interface.c \
OpenBootloader/Target/ram_interface.c \
OpenBootloader/Target/usb_interface.c \
USB_Device/App/usb_device.c
LOCAL_OBJS := \
main.o \
obl_app.o \
app_openbootloader.o \
stm32n6xx_hal_msp.o \
stm32n6xx_it.o \
system_stm32n6xx_obl.o \
external_memory_interface.o \
otp_interface.o \
usbd_conf.o \
usbd_desc.o \
usbd_dfu.o \
usbd_dfu_if.o \
flash/$(OBL_FLASH_DRIVER).o \
startup_stm32n657xx_obl.o
HAL_OBJS := $(HAL_C_SRCS:.c=.hal.o)
OBL_MW_OBJS := $(notdir $(OBL_MW_C_SRCS:.c=.mw.o))
OBL_USB_OBJS:= $(notdir $(OBL_USB_C_SRCS:.c=.usbd.o))
OBL_APP_OBJS:= $(notdir $(OBL_APP_C_SRCS:.c=.app.o))
OBJS := $(LOCAL_OBJS) $(HAL_OBJS) $(OBL_MW_OBJS) $(OBL_USB_OBJS) $(OBL_APP_OBJS)
ELF := obl.elf
BIN := obl.bin
SIGNING_TOOL ?= STM32_SigningTool_CLI
SIGNED_BLOB := prebuilt/obl_$(OBL_FLASH_DRIVER)_signed.stm32
# Build fails loudly if the OBL output exceeds the linker-declared RAM
# region. Matches LENGTH in STM32N657XX_OBL.ld.
OBL_SIZE_LIMIT := 65536 # 64 KiB
.PHONY: all signed size_check clean
all: $(BIN) size_check
$(BIN): $(ELF)
$(OBJCOPY) -O binary $< $@
$(SIZE) $<
$(ELF): $(OBJS) $(LDSCRIPT)
$(LD) $(LDFLAGS) $(OBJS) -o $@
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
%.o: %.s
$(AS) $(ASFLAGS) -c $< -o $@
flash/%.o: flash/%.c
$(CC) $(CFLAGS) -c $< -o $@
%.hal.o: $(HAL_DIR)/Src/%.c
$(CC) $(CFLAGS) -c $< -o $@
# Pattern rules for the OBL middleware / USB Device Library / application
# glue. Each rule strips the suffix used to disambiguate object files
# (.mw.o, .usbd.o, .app.o) and finds the .c by leaf-name search across
# the upstream subdirectories. notdir + foreach keeps the rule chain
# manageable without listing every nested directory in VPATH.
OBL_MW_DIRS := \
$(OBL_MW)/Core \
$(OBL_MW)/Util \
$(OBL_MW)/Modules/Mem \
$(OBL_MW)/Modules/USB \
$(OBL_MW)/Modules/USART
OBL_USB_DIRS := \
$(OBL_USBLIB)/Core/Src \
$(OBL_USBLIB)/Class/DFU/Src
OBL_APP_DIRS := \
$(OBL_PROJ)/OpenBootloader/App \
$(OBL_PROJ)/OpenBootloader/Target \
$(OBL_PROJ)/USB_Device/App \
$(OBL_PROJ)/USB_Device/Target
vpath %.c $(OBL_MW_DIRS) $(OBL_USB_DIRS) $(OBL_APP_DIRS)
%.mw.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
%.usbd.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
%.app.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
# Hard size cap — keeps OBL fit-for-@FSBL-DFU even as middleware grows.
size_check: $(BIN)
@bin_size=$$(stat -c %s $(BIN)); \
if [ $$bin_size -gt $(OBL_SIZE_LIMIT) ]; then \
echo "ERROR: $(BIN) is $$bin_size bytes, exceeds $(OBL_SIZE_LIMIT) byte cap (boot ROM @FSBL alt limit)"; \
exit 1; \
else \
echo "OBL size OK: $$bin_size / $(OBL_SIZE_LIMIT) bytes"; \
fi
signed: $(SIGNED_BLOB)
$(SIGNED_BLOB): $(BIN) | prebuilt
$(SIGNING_TOOL) -bin $< -nk -of 0x80000000 -t ssbl -hv 2.3 -align -o $@ -s
prebuilt:
mkdir -p $@
clean:
rm -f $(LOCAL_OBJS) $(HAL_OBJS) $(ELF) $(BIN) obl.map