# RK0 NUCLEO-F103RB demo build system

PLATFORM ?= nucleof103rb
ifdef platform
PLATFORM := $(platform)
endif

NUCLEO_F103RB_PLATFORMS := nucleof103rb nucleo-f103rb nucleo_f103rb stm32f103rb stm32f103xb
ifneq ($(filter $(PLATFORM),$(NUCLEO_F103RB_PLATFORMS)),)
else
$(error "This demo package only builds the NUCLEO-F103RB board. Use plain make or make flash.")
endif

override ARCH := armv7m

CPU   := cortex-m3
FLOAT := soft
MCU_FLAGS := -mcpu=$(CPU) -mfloat-abi=$(FLOAT) -mthumb
EXTRA_DEFS ?=
EXTRA_CFLAGS ?=

# Project layout.
ARCH_DIR   := arch/$(ARCH)/kernel
CORE_DIR   := core
APP_DIR    := app
LINKER_DIR := arch/$(ARCH)
DRIVERS    := Drivers

# Toolchain.
CC       := arm-none-eabi-gcc
AS       := arm-none-eabi-gcc
LD       := arm-none-eabi-gcc
OBJCOPY  := arm-none-eabi-objcopy
SIZE     := arm-none-eabi-size
SHELL    := /bin/bash

# Platform source selection.
CORE_SRCS := $(wildcard $(CORE_DIR)/src/*.c)
ARCH_C_SRCS := $(wildcard $(ARCH_DIR)/src/*.c)

NUCLEO_F103RB_APP_SRCS := \
	$(APP_DIR)/src/application.c \
	$(APP_DIR)/src/logger.c \
	$(APP_DIR)/src/main_stm32f103rb.c \
	$(APP_DIR)/src/stm32f103rb_uart.c \
	$(APP_DIR)/src/stm32f1xx_hal_msp.c \
	$(APP_DIR)/src/system_stm32f1xx.c

BUILD_DIR := build/nucleof103rb
LINKER_SCRIPT := $(LINKER_DIR)/nucleof103rb.ld
INC_DIRS := \
	-I$(DRIVERS)/CMSIS/Device/ST/STM32F1xx/Include \
	-I$(DRIVERS)/CMSIS/Include \
	-I$(DRIVERS)/STM32F1xx_HAL_Driver/Inc \
	-I$(ARCH_DIR)/inc \
	-I$(CORE_DIR)/inc \
	-I$(APP_DIR)/inc
STM32F1_HAL_SRCS := $(wildcard $(DRIVERS)/STM32F1xx_HAL_Driver/Src/*.c)
C_SRCS := \
	$(CORE_SRCS) \
	$(filter-out $(ARCH_DIR)/src/startup.c,$(ARCH_C_SRCS)) \
	$(NUCLEO_F103RB_APP_SRCS) \
	$(STM32F1_HAL_SRCS)
ASM_SRCS := \
	$(ARCH_DIR)/src/klow.S \
	$(ARCH_DIR)/src/startup_stm32f103xb.S
# Trace stays enabled by kconfig.h; trim optional spill buffers for 20 KB SRAM.
PLATFORM_DEFS := -DSTM32F103xB -DUSE_HAL_DRIVER -DRK_PLATFORM_NUCLEO_F103RB \
                 -DRK_CONF_SYSCORECLK=0 -DRK_CONF_N_USRTASKS_MAX=8 \
                 -DRK_CONF_TRACE_FRAME_BUFFER_DEPTH=0 \
                 -DRK_CONF_TRACE_OVERFLOW_BACKLOG=0
C_STD := -std=gnu11
WARN_FLAGS := -Wall -Wextra

OBJS := $(patsubst %.c,$(BUILD_DIR)/%.o,$(C_SRCS)) \
        $(patsubst %.S,$(BUILD_DIR)/%.o,$(ASM_SRCS))

DEPS := $(OBJS:.o=.d)

# Output.
TARGET ?= rk0_demo
ELF    := $(BUILD_DIR)/$(TARGET).elf
BIN    := $(BUILD_DIR)/$(TARGET).bin
HEX    := $(BUILD_DIR)/$(TARGET).hex
MAP    := $(ELF:.elf=.map)

CPPCHECK ?= cppcheck
CPPCHECK_SUPPRESSIONS := cppcheck.suppressions
CPPCHECK_REPORT_DIR ?= build/cppcheck
CPPCHECK_REPORT := $(CPPCHECK_REPORT_DIR)/cppcheck-nucleof103rb.txt
CPPCHECK_FLAGS := --quiet --enable=all --check-level=exhaustive \
                  --std=c11 --language=c --inline-suppr \
                  --suppressions-list=$(CPPCHECK_SUPPRESSIONS) \
                  --error-exitcode=1 --platform=unix32
CPPCHECK_DEFS := -D__GNUC__ -D'__has_builtin(x)=0' -D__ARM_ARCH_7M__ $(PLATFORM_DEFS)

OPENOCD_PROBE ?= stlink
OPENOCD_SPEED ?= 100

ifeq ($(OPENOCD_PROBE),jlink)
OPENOCD_FLASH_CFG := -f interface/jlink.cfg \
                     -c "transport select swd" \
                     -f target/stm32f1x.cfg \
                     -c "reset_config srst_only srst_nogate connect_assert_srst"
else ifeq ($(OPENOCD_PROBE),stlink)
OPENOCD_FLASH_CFG := -f board/st_nucleo_f103rb.cfg
else
$(error "Unsupported OPENOCD_PROBE=$(OPENOCD_PROBE). Use OPENOCD_PROBE=jlink or OPENOCD_PROBE=stlink.")
endif

OPT := -O0
STACK_USAGE_FLAG := -fstack-usage

CFLAGS := $(C_STD) $(MCU_FLAGS) $(PLATFORM_DEFS) \
          $(WARN_FLAGS) -ffunction-sections -fdata-sections \
          $(STACK_USAGE_FLAG) -g $(OPT) $(INC_DIRS) $(EXTRA_DEFS) \
          $(EXTRA_CFLAGS)
ASFLAGS := $(MCU_FLAGS) $(PLATFORM_DEFS) -D__KDEF_STACKOVFLW \
           -x assembler-with-cpp -Wall -ffunction-sections -fdata-sections \
           -g $(EXTRA_DEFS)
LDFLAGS := -nostartfiles -T $(LINKER_SCRIPT) $(MCU_FLAGS) \
           -Wl,-Map=$(MAP),--cref -Wl,--gc-sections \
           -specs=nano.specs -lc

# Targets.
all: $(BIN) $(HEX) sizes

$(ELF): $(OBJS) $(LINKER_SCRIPT)
	@echo "Linking $(notdir $@)"
	$(LD) $(LDFLAGS) -o $@ $(OBJS)
	$(SIZE) $@

$(BUILD_DIR)/%.o: %.c
	@mkdir -p $(dir $@)
	$(CC) $(CFLAGS) -c $< -o $@ -MMD -MP -MF $(@:.o=.d)

$(BUILD_DIR)/%.o: %.S
	@mkdir -p $(dir $@)
	$(AS) $(ASFLAGS) -c $< -o $@ -MMD -MP -MF $(@:.o=.d)

$(BIN): $(ELF)
	$(OBJCOPY) -O binary -S $< $@

$(HEX): $(ELF)
	$(OBJCOPY) -O ihex -S $< $@

flash: $(BIN)
	openocd \
		$(OPENOCD_FLASH_CFG) \
		-c "adapter speed $(OPENOCD_SPEED)" \
		-c "init; reset halt;" \
		-c "flash write_image erase $(BIN) 0x08000000" \
		-c "verify_image $(BIN) 0x08000000" \
		-c "reset run; shutdown"

clean:
	rm -rf build

cppcheck:
	@$(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_DEFS) $(INC_DIRS) $(C_SRCS)

cppcheck-report:
	@mkdir -p $(CPPCHECK_REPORT_DIR)
	@{ \
		echo "Cppcheck report"; \
		echo "BOARD=NUCLEO-F103RB"; \
		echo "Generated: $$(date -u '+%Y-%m-%dT%H:%M:%SZ')"; \
		echo; \
	} > $(CPPCHECK_REPORT)
	@if $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_DEFS) $(INC_DIRS) $(C_SRCS) >> $(CPPCHECK_REPORT) 2>&1; then \
		echo "Result: PASS (no unsuppressed cppcheck findings)" >> $(CPPCHECK_REPORT); \
	else \
		rc=$$?; \
		echo "Result: FAIL (cppcheck exit code $$rc)" >> $(CPPCHECK_REPORT); \
		exit $$rc; \
	fi

sizes:
	@for f in $(OBJS); do \
		if [ -f $$f ]; then \
			set -- $$($(SIZE) $$f | awk 'NR==2'); \
			TEXT=$$1; DATA=$$2; BSS=$$3; TOTAL=$$4; \
			OBJNAME=$$(basename $$f); \
			echo "$$OBJNAME: TEXT=$$TEXT DATA=$$DATA BSS=$$BSS TOTAL=$$TOTAL"; \
		else \
			echo "Missing: $$f"; \
		fi; \
	done

-include $(DEPS)

help:
	@echo "  make                              : build NUCLEO-F103RB ELF/BIN/HEX with debug symbols"
	@echo "  make flash                        : build and flash NUCLEO-F103RB over stock ST-LINK"
	@echo "  make OPENOCD_PROBE=jlink flash    : flash over J-Link/OpenOCD"
	@echo "  make clean                        : remove build directory"
	@echo "  make cppcheck                     : run cppcheck for the NUCLEO-F103RB build"
	@echo "  make cppcheck-report              : write cppcheck report under build/cppcheck"

.PHONY: all clean sizes flash cppcheck cppcheck-report help
