cmake_minimum_required(VERSION 3.22)

# Compiler settings
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER_FORCED TRUE)
set(CMAKE_CXX_COMPILER_FORCED TRUE)
set(CMAKE_C_COMPILER_ID GNU)
set(CMAKE_CXX_COMPILER_ID GNU)
set(CMAKE_EXECUTABLE_SUFFIX_C ".elf")
set(TOOLCHAIN_PREFIX arm-none-eabi-)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

# Define the default build type
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "Debug")
endif()
message("Build type: " ${CMAKE_BUILD_TYPE})

# Variables
if(NOT PROGRAMMER_CLI)
    set(PROGRAMMER_CLI /opt/ST/STM32CubeCLT_1.15.1/STM32CubeProgrammer/bin)
endif()
message("Programmer CLI: " ${PROGRAMMER_CLI})

if(NOT GDB_SERVER)
    set(GDB_SERVER /opt/ST/STM32CubeCLT_1.15.1/STLink-gdb-server/bin)
endif()
message("GDB Server: " ${GDB_SERVER})

# MCU specific compiler flags
set(TARGET_FLAGS "-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard ")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TARGET_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -fdata-sections -ffunction-sections")
if(CMAKE_BUILD_TYPE MATCHES Debug)
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g3")
endif()
if(CMAKE_BUILD_TYPE MATCHES Release)
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Os -g0")
endif()
set(CMAKE_C_LINK_FLAGS "${TARGET_FLAGS}")
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -T \"${CMAKE_SOURCE_DIR}/src/STM32F446RETx_FLASH.ld\"")
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} --specs=nano.specs")
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Wl,--gc-sections")
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--start-group -lc -lm -Wl,--end-group")
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--print-memory-usage")

# Set the project name
set(CMAKE_PROJECT_NAME stm32-boot-explained)

# Core project settings
project(${CMAKE_PROJECT_NAME})

enable_language(C ASM)

# Create an executable object type
add_executable(${CMAKE_PROJECT_NAME}
    ./src/main.c
    ./src/bootloader.c
    ./src/syscalls.c
    ./src/sysmem.c
    ./src/system_stm32f4xx.c
)

add_subdirectory(drivers)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
    stm32-drivers
)

# Upload ELF to the device
add_custom_target(flash
    COMMAND ${PROGRAMMER_CLI}/STM32_Programmer_CLI
     -c port=swd -w $<TARGET_FILE:${CMAKE_PROJECT_NAME}> -v -rst)

# Start ST-Link gdb server
add_custom_target(gdb-server
    COMMAND ${GDB_SERVER}/ST-LINK_gdbserver
     -d -cp ${PROGRAMMER_CLI})