cmake_minimum_required(VERSION 3.20)

# 跳过编译器链接测试（裸机 ARM 无系统调用 _exit/_sbrk 等）
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

project(blink C)

# 输出固件带 .elf 后缀，pyOCD 自动识别格式
set(CMAKE_EXECUTABLE_SUFFIX ".elf")

# ── 路径检测：环境变量 → 自动扫描 ────────────────────────────────
function(auto_find var_name pattern)
    if(NOT ${var_name} OR NOT EXISTS "${${var_name}}")
        foreach(drv C D E)
            if(EXISTS "${drv}:/ti")
                file(GLOB _found "${drv}:/ti/${pattern}")
                if(_found)
                    list(GET _found 0 ${var_name})
                    set(${var_name} "${${var_name}}" PARENT_SCOPE)
                endif()
            endif()
        endforeach()
    endif()
endfunction()

set(SDK_DIR        "$ENV{MSPM0_SDK_ROOT}" CACHE PATH "MSPM0 SDK root")
set(SYSCONFIG_CLI  "$ENV{SYSCONFIG_CLI_PATH}" CACHE FILEPATH "SysConfig CLI path")

auto_find(SDK_DIR       "mspm0_sdk_*")
auto_find(SYSCONFIG_CLI "sysconfig_*/sysconfig_cli.bat")

if(NOT SDK_DIR)
    message(FATAL_ERROR "MSPM0 SDK not found. Set MSPM0_SDK_ROOT env var.")
endif()
if(NOT SYSCONFIG_CLI OR NOT EXISTS "${SYSCONFIG_CLI}")
    message(FATAL_ERROR "SysConfig CLI not found. Set SYSCONFIG_CLI_PATH env var.")
endif()

set(DEVICE         "MSPM0G350X")
set(PACKAGE        "LQFP-64(PM)")

# ── SysConfig code generation ──────────────────────────────────────
set(SYSCFG_OUTPUT_DIR "${CMAKE_BINARY_DIR}/syscfg")

add_custom_command(
    OUTPUT
        "${SYSCFG_OUTPUT_DIR}/ti_msp_dl_config.c"
        "${SYSCFG_OUTPUT_DIR}/ti_msp_dl_config.h"
        "${SYSCFG_OUTPUT_DIR}/device_linker.lds"
        "${SYSCFG_OUTPUT_DIR}/device.opt"
        "${SYSCFG_OUTPUT_DIR}/device.lds.genlibs"
    COMMAND cmd /c "${SYSCONFIG_CLI}"
        --compiler gcc
        --product "${SDK_DIR}/.metadata/product.json"
        --device "${DEVICE}"
        --package "${PACKAGE}"
        --output "${SYSCFG_OUTPUT_DIR}"
        "${CMAKE_SOURCE_DIR}/blink.syscfg"
    DEPENDS "${CMAKE_SOURCE_DIR}/blink.syscfg"
    COMMENT "Running SysConfig..."
)

# ── Source files ────────────────────────────────────────────────────
set(GEN_DIR ${SYSCFG_OUTPUT_DIR})

add_executable(${PROJECT_NAME}
    src/main.c
    "${GEN_DIR}/ti_msp_dl_config.c"
    "${SDK_DIR}/source/ti/devices/msp/m0p/startup_system_files/gcc/startup_mspm0g350x_gcc.c"
)

# SysConfig outputs are dependencies
add_dependencies(${PROJECT_NAME} syscfg_gen)
add_custom_target(syscfg_gen DEPENDS "${GEN_DIR}/ti_msp_dl_config.c")

# ── Include directories ─────────────────────────────────────────────
target_include_directories(${PROJECT_NAME} PRIVATE
    "${CMAKE_SOURCE_DIR}/include"
    "${CMAKE_SOURCE_DIR}/src"
    "${GEN_DIR}"
    "${SDK_DIR}/source"
    "${SDK_DIR}/source/third_party/CMSIS/Core/Include"
)

# ── Compile definitions & flags ─────────────────────────────────────
target_compile_definitions(${PROJECT_NAME} PRIVATE
    __MSPM0G3507__
    __USE_SYSCONFIG__
)

target_compile_options(${PROJECT_NAME} PRIVATE
    -mcpu=cortex-m0plus
    -march=armv6-m
    -mthumb
    -mfloat-abi=soft
    -std=c99
    -O2
    -ffunction-sections
    -fdata-sections
    -g
    -Wall
    -gstrict-dwarf
)

# ── Linker flags ────────────────────────────────────────────────────
# Override SysConfig's linker script with G3507 (128KB Flash / 32KB SRAM)
set(LINKER_SCRIPT "${SDK_DIR}/source/ti/devices/msp/m0p/linker_files/gcc/mspm0g3507.lds")

target_link_options(${PROJECT_NAME} PRIVATE
    -mcpu=cortex-m0plus
    -march=armv6-m
    -mthumb
    -mfloat-abi=soft
    -nostartfiles
    -static
    -Wl,--gc-sections
    -Wl,-Map,${PROJECT_NAME}.map
    -T${LINKER_SCRIPT}
    -T${GEN_DIR}/device.lds.genlibs
    -L${SDK_DIR}/source
    --specs=nano.specs
    --specs=nosys.specs
    -lgcc
    -lc
    -lm
)
