##############################################################################
# XIAO-C5 bare-metal HAL 2.0 project for STM32CubeIDE
##############################################################################
cmake_minimum_required(VERSION 3.20)

# Optimization per build type: prefer size (-Os) for Release, the
# debug-friendly -Og for Debug. These seed the CMake cache on first
# configure (clear the build dir to change them).
set(CMAKE_C_FLAGS_RELEASE_INIT "-Os -DNDEBUG")
set(CMAKE_C_FLAGS_DEBUG_INIT   "-Og -g3")

set(PROJECT_NAME "xiao_c5_project")

set(STM32C5_SDK_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/SDK/STM32CubeC5" CACHE PATH
    "Path to the bundled STM32CubeC5 SDK files")
get_filename_component(CUBE_REPO "${STM32C5_SDK_ROOT}" ABSOLUTE)
set(DRIVERS   "${CUBE_REPO}/stm32c5xx_drivers")
set(DFP       "${CUBE_REPO}/stm32c5xx_dfp")
set(CMSIS     "${CUBE_REPO}/arch/cmsis")

set(STM32C5_REQUIRED_PATHS
    "${DFP}/Source/Templates/system_stm32c5xx.c"
    "${DRIVERS}/hal/stm32c5xx_hal.c"
    "${CMSIS}/CMSIS/Core/Include/core_cm33.h"
)
foreach(REQUIRED_PATH IN LISTS STM32C5_REQUIRED_PATHS)
    if(NOT EXISTS "${REQUIRED_PATH}")
        message(FATAL_ERROR
            "STM32CubeC5 SDK dependency is incomplete: ${REQUIRED_PATH}\n"
            "Expected bundled SDK root: ${CUBE_REPO}\n"
            "Re-extract the complete xiao_c5_project package.")
    endif()
endforeach()

set(MCPU   "-mcpu=cortex-m33")
set(MFPU   "-mfpu=fpv5-sp-d16")
set(LINKER_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/STM32C5A3CGTX_FLASH.ld")

set(PROJECT_SOURCES
    Sources/main.c
    Sources/board.c
    Sources/uart_io.c
    Sources/tests.c
    Sources/runtime.c
    Sources/stm32c5xx_it.c
    Sources/syscalls.c
    Sources/sysmem.c
    Startup/startup_stm32c5a3cgtx.s
    ${DFP}/Source/Templates/system_stm32c5xx.c
    ${DRIVERS}/hal/stm32c5xx_hal.c
    ${DRIVERS}/hal/stm32c5xx_hal_cortex.c
    ${DRIVERS}/hal/stm32c5xx_hal_gpio.c
    ${DRIVERS}/hal/stm32c5xx_hal_rcc.c
    ${DRIVERS}/hal/stm32c5xx_hal_pwr.c
    ${DRIVERS}/hal/stm32c5xx_hal_flash.c
    ${DRIVERS}/hal/stm32c5xx_hal_flash_itf.c
    ${DRIVERS}/hal/stm32c5xx_hal_uart.c
    ${DRIVERS}/hal/stm32c5xx_hal_i2c.c
    ${DRIVERS}/hal/stm32c5xx_hal_adc.c
    ${DRIVERS}/hal/stm32c5xx_hal_tim.c
    ${DRIVERS}/hal/stm32c5xx_hal_fdcan.c
    ${DRIVERS}/hal/stm32c5xx_hal_dma.c
)

set(PROJECT_INCLUDES
    ${CMAKE_CURRENT_SOURCE_DIR}/Sources
    ${DRIVERS}/hal
    ${DRIVERS}/ll
    ${DRIVERS}/timebases
    ${DFP}/Include
    ${CMSIS}/CMSIS/Core/Include
)

set(PROJECT_DEFINES STM32C5A3xx)

project(${PROJECT_NAME} C ASM)

add_executable(${PROJECT_NAME} ${PROJECT_SOURCES})
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_INCLUDES})
target_compile_definitions(${PROJECT_NAME} PRIVATE ${PROJECT_DEFINES})
target_compile_options(${PROJECT_NAME} PRIVATE
    -include "${CMAKE_CURRENT_SOURCE_DIR}/Sources/stm32_external_env.h")

set(CMAKE_EXECUTABLE_SUFFIX ".elf")
set(CMAKE_C_FLAGS   "${MCPU} ${MFPU} -mthumb -std=gnu11 --specs=nano.specs -Wall -Werror=implicit-function-declaration")
set(CMAKE_ASM_FLAGS "${MCPU} ${MFPU} -mthumb -x assembler-with-cpp")
set(CMAKE_EXE_LINKER_FLAGS
    "-T${LINKER_SCRIPT} --specs=nosys.specs -static -Wl,--gc-sections \
     -Wl,--defsym=__Vectors=g_pfnVectors \
     -Wl,--start-group -lc -lm -Wl,--end-group \
     -Wl,-Map=${PROJECT_NAME}.map")

add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
    COMMAND ${CMAKE_SIZE} $<TARGET_FILE:${PROJECT_NAME}>)

# Cross-platform UF2 generation using the converter bundled with this project.
# Windows commonly exposes a non-functional Microsoft Store `python3.exe`
# alias, so prefer `python`; Unix-like systems normally fall back to `python3`.
find_program(PYTHON_CMD NAMES python python3 py)
set(UF2_TOOL "${CMAKE_CURRENT_SOURCE_DIR}/tools/uf2conv.py" CACHE FILEPATH
    "Path to the TinyUF2 conversion script")
if(PYTHON_CMD AND EXISTS "${UF2_TOOL}")
    add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
        COMMAND ${CMAKE_OBJCOPY} -O binary
                $<TARGET_FILE:${PROJECT_NAME}>
                $<TARGET_FILE_DIR:${PROJECT_NAME}>/${PROJECT_NAME}.bin
        COMMAND ${PYTHON_CMD} ${UF2_TOOL}
                --input  $<TARGET_FILE_DIR:${PROJECT_NAME}>/${PROJECT_NAME}.bin
                --output $<TARGET_FILE_DIR:${PROJECT_NAME}>/${PROJECT_NAME}.uf2
                --base 0x08008000 --family-id 0x00C5C5C5
        COMMENT "Generating BIN + UF2 for TinyUF2")
elseif(NOT PYTHON_CMD)
    message(WARNING "Python 3 was not found; BIN and UF2 files will not be generated. Install Python 3 and rebuild.")
else()
    message(WARNING "UF2 conversion script was not found: ${UF2_TOOL}")
endif()
