cmake_minimum_required(VERSION 3.15.0)

# ==========================
# Toolchain Setup
# ==========================
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/cmake/arm-none-eabi-gcc.cmake)

# ==========================
# Project Setup
# ==========================
project(elite_bootlaoder VERSION 0.1.0 LANGUAGES C ASM)

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)

set(EXECUTABLE ${PROJECT_NAME}.elf)
set(NRF_SDK_DIR ${CMAKE_SOURCE_DIR}/../bmd380_sdk)
set(NRF_SDK_LINKER_DIR ${NRF_SDK_DIR}/modules/nrfx/mdk)
set(SD_LINKER_DIR ${CMAKE_SOURCE_DIR}/SoftdeviceLibraries/hard)
set(LINKER_FILE ${CMAKE_SOURCE_DIR}/linkscripts/secure_bootloader_gcc_nrf52.ld)

# ==========================
# Compiler Flags and Defines
# ==========================
set(COMMON_COMPILE_OPT
    -mcpu=cortex-m4
    -mfpu=fpv4-sp-d16
    -mfloat-abi=hard
    -mthumb
    -fdata-sections
    -ffunction-sections
    -Wall
    -Os
    -g3
    -Wno-unused-variable
    -Wno-pointer-sign
    -Wno-array-bounds
)

set(COMMON_COMPILE_DEF
    -DDEBUG=1
    -DBLE_STACK_SUPPORT_REQD
    -DBOARD_CUSTOM
    -DDEBUG_NRF
    -DFLOAT_ABI_HARD
    -DNRF52840_XXAA
    -DNRF_DFU_SETTINGS_VERSION=2
    -DNRF_DFU_SVCI_ENABLED
    -DNRF_SD_BLE_API_VERSION=7
    -DS140
    -DSOFTDEVICE_PRESENT
    -DSVC_INTERFACE_CALL_AS_NORMAL_FUNCTION
    -DUSE_APP_CONFIG
    -DAPP_TIMER_V2    
    -DAPP_TIMER_V2_RTC1_ENABLED
    -DBL_SETTINGS_ACCESS_ONLY
    -DCONFIG_GPIO_AS_PINRESET
    -DNRF_DFU_TRANSPORT_BLE=1
    -D__HEAP_SIZE=8192
    -D__STACK_SIZE=8192
)

set(COMMON_COMPILE_INC
    ## Timing & Events
    ${NRF_SDK_DIR}/components/libraries/delay
    ${NRF_SDK_DIR}/components/libraries/led_softblink
    ${NRF_SDK_DIR}/components/libraries/low_power_pwm
    ${NRF_SDK_DIR}/components/libraries/scheduler
    ${NRF_SDK_DIR}/components/libraries/timer

    ## Others
    ${NRF_SDK_DIR}/components/libraries/experimental_section_vars
    ${NRF_SDK_DIR}/components/libraries/ringbuf
    ${NRF_SDK_DIR}/components/libraries/slip
    ${NRF_SDK_DIR}/components/libraries/svc

    ## Boards
    ${NRF_SDK_DIR}/bmd380_sdk/components/boards
    ${NRF_SDK_DIR}/components/boards

    ## BLE
    ${NRF_SDK_DIR}/components/ble/common

    ## External
    ${NRF_SDK_DIR}/external/fprintf
    ${NRF_SDK_DIR}/external/nano-pb
    ${NRF_SDK_DIR}/external/nrf_cc310_bl/include
    ${NRF_SDK_DIR}/external/segger_rtt
    ${NRF_SDK_DIR}/external/utf_converter

    ## USB
    ${NRF_SDK_DIR}/components/libraries/usbd
    ${NRF_SDK_DIR}/components/libraries/usbd/class/cdc
    ${NRF_SDK_DIR}/components/libraries/usbd/class/cdc/acm

    ## Crypto
    ${NRF_SDK_DIR}/components/libraries/crypto
    ${NRF_SDK_DIR}/components/libraries/crypto/backend/cc310
    ${NRF_SDK_DIR}/components/libraries/crypto/backend/cc310_bl
    ${NRF_SDK_DIR}/components/libraries/crypto/backend/cifra
    ${NRF_SDK_DIR}/components/libraries/crypto/backend/mbedtls
    ${NRF_SDK_DIR}/components/libraries/crypto/backend/micro_ecc
    ${NRF_SDK_DIR}/components/libraries/crypto/backend/nrf_hw
    ${NRF_SDK_DIR}/components/libraries/crypto/backend/nrf_sw
    ${NRF_SDK_DIR}/components/libraries/crypto/backend/oberon
    ${NRF_SDK_DIR}/components/libraries/crypto/backend/optiga

    ## Bootloader
    ${CMAKE_SOURCE_DIR}/bootloader/inc
    ${NRF_SDK_DIR}/components/libraries/bootloader
    ${NRF_SDK_DIR}/components/libraries/bootloader/ble_dfu
    ${NRF_SDK_DIR}/components/libraries/bootloader/dfu

    ## Utility
    ${NRF_SDK_DIR}/components/libraries/crc32
    ${NRF_SDK_DIR}/components/libraries/fstorage
    ${NRF_SDK_DIR}/components/libraries/sortlist
    ${NRF_SDK_DIR}/components/libraries/strerror

    ## Log
    ${NRF_SDK_DIR}/components/libraries/log
    ${NRF_SDK_DIR}/components/libraries/log/src

    ## Toolchain
    ${ARM_TOOLCHAIN_DIR}/../arm-none-eabi/include
    ${NRF_SDK_DIR}/components/toolchain/cmsis/include

    ## Core Libs
    ${NRF_SDK_DIR}/components/libraries/atomic
    ${NRF_SDK_DIR}/components/libraries/atomic_fifo
    ${NRF_SDK_DIR}/components/libraries/balloc
    ${NRF_SDK_DIR}/components/libraries/memobj
    ${NRF_SDK_DIR}/components/libraries/mutex
    ${NRF_SDK_DIR}/components/libraries/util

    ## NRFX
    ${NRF_SDK_DIR}/integration/nrfx
    ${NRF_SDK_DIR}/integration/nrfx/legacy
    ${NRF_SDK_DIR}/modules/nrfx
    ${NRF_SDK_DIR}/modules/nrfx/drivers/include
    ${NRF_SDK_DIR}/modules/nrfx/hal
    ${NRF_SDK_DIR}/modules/nrfx/mdk

    ## SoftDevice
    ${NRF_SDK_DIR}/components/softdevice/common
    ${NRF_SDK_DIR}/components/softdevice/mbr/headers
    ${NRF_SDK_DIR}/components/softdevice/s140/headers
    ${NRF_SDK_DIR}/components/softdevice/s140/headers/nrf52
)

# ==========================
# Configuration Interface
# ==========================
add_library(prj_config INTERFACE)
target_include_directories(prj_config INTERFACE ${COMMON_COMPILE_INC})
target_compile_definitions(prj_config INTERFACE ${COMMON_COMPILE_DEF})
target_compile_options(prj_config INTERFACE ${COMMON_COMPILE_OPT})

# ==========================
# Subdirectories
# ==========================

# ==========================
# Source Files
# ==========================
set(STARTUP_SRC
    ${NRF_SDK_DIR}/modules/nrfx/mdk/gcc_startup_nrf52840.S
    ${NRF_SDK_DIR}/modules/nrfx/mdk/system_nrf52.c
)

file(GLOB_RECURSE BOOTLOADER_SOURCES "bootloader/*.c")

# ==========================
# Executable and Linker
# ==========================
add_executable(${EXECUTABLE}
    ${STARTUP_SRC}
    ${BOOTLOADER_SOURCES}

    ### Bootloader (DFU)
    ${NRF_SDK_DIR}/components/libraries/bootloader/dfu/dfu-cc.pb.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/dfu/nrf_dfu.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/dfu/nrf_dfu_flash.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/dfu/nrf_dfu_handling_error.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/dfu/nrf_dfu_mbr.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/dfu/nrf_dfu_req_handler.c    
    ${NRF_SDK_DIR}/components/libraries/bootloader/dfu/nrf_dfu_settings.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/dfu/nrf_dfu_settings_svci.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/dfu/nrf_dfu_svci.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/dfu/nrf_dfu_svci_handler.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/dfu/nrf_dfu_transport.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/dfu/nrf_dfu_utils.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/dfu/nrf_dfu_validation.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/dfu/nrf_dfu_ver_validation.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/serial_dfu/nrf_dfu_serial_usb.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/serial_dfu/nrf_dfu_serial.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/ble_dfu/nrf_dfu_ble.c

    ### Bootloader Core
    ${NRF_SDK_DIR}/components/libraries/bootloader/nrf_bootloader.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/nrf_bootloader_app_start.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/nrf_bootloader_app_start_final.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/nrf_bootloader_dfu_timers.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/nrf_bootloader_fw_activation.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/nrf_bootloader_info.c
    ${NRF_SDK_DIR}/components/libraries/bootloader/nrf_bootloader_wdt.c

    ### USBD
    ${NRF_SDK_DIR}/components/libraries/usbd/class/cdc/acm/app_usbd_cdc_acm.c
    ${NRF_SDK_DIR}/components/libraries/usbd/app_usbd.c
    ${NRF_SDK_DIR}/components/libraries/usbd/app_usbd_string_desc.c
    ${NRF_SDK_DIR}/components/libraries/usbd/app_usbd_serial_num.c
    ${NRF_SDK_DIR}/components/libraries/usbd/app_usbd_core.c

    ### Crypto
    ${NRF_SDK_DIR}/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_ecc.c
    ${NRF_SDK_DIR}/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_ecdsa.c
    ${NRF_SDK_DIR}/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_hash.c
    ${NRF_SDK_DIR}/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_init.c
    ${NRF_SDK_DIR}/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_shared.c
    ${NRF_SDK_DIR}/components/libraries/crypto/nrf_crypto_ecc.c
    ${NRF_SDK_DIR}/components/libraries/crypto/nrf_crypto_ecdsa.c
    ${NRF_SDK_DIR}/components/libraries/crypto/nrf_crypto_hash.c
    ${NRF_SDK_DIR}/components/libraries/crypto/nrf_crypto_init.c
    ${NRF_SDK_DIR}/components/libraries/crypto/nrf_crypto_shared.c

    ### Core Libraries
    ${NRF_SDK_DIR}/components/libraries/atomic/nrf_atomic.c
    ${NRF_SDK_DIR}/components/libraries/atomic_fifo/nrf_atfifo.c
    ${NRF_SDK_DIR}/components/libraries/balloc/nrf_balloc.c
    ${NRF_SDK_DIR}/components/libraries/crc32/crc32.c
    ${NRF_SDK_DIR}/components/libraries/experimental_section_vars/nrf_section_iter.c
    ${NRF_SDK_DIR}/components/libraries/fstorage/nrf_fstorage.c
    ${NRF_SDK_DIR}/components/libraries/fstorage/nrf_fstorage_nvmc.c
    ${NRF_SDK_DIR}/components/libraries/fstorage/nrf_fstorage_sd.c
    ${NRF_SDK_DIR}/components/libraries/led_softblink/led_softblink.c
    ${NRF_SDK_DIR}/components/libraries/low_power_pwm/low_power_pwm.c
    ${NRF_SDK_DIR}/components/libraries/memobj/nrf_memobj.c
    ${NRF_SDK_DIR}/components/libraries/ringbuf/nrf_ringbuf.c
    ${NRF_SDK_DIR}/components/libraries/scheduler/app_scheduler.c
    ${NRF_SDK_DIR}/components/libraries/sortlist/nrf_sortlist.c
    ${NRF_SDK_DIR}/components/libraries/strerror/nrf_strerror.c
    ${NRF_SDK_DIR}/components/libraries/svc/nrf_svc_handler.c
    ${NRF_SDK_DIR}/components/libraries/timer/app_timer2.c
    ${NRF_SDK_DIR}/components/libraries/timer/drv_rtc.c
    ${NRF_SDK_DIR}/components/libraries/util/app_util_platform.c
    ${NRF_SDK_DIR}/components/libraries/util/nrf_assert.c

    ### Logging
    ${NRF_SDK_DIR}/components/libraries/log/src/nrf_log_backend_rtt.c
    ${NRF_SDK_DIR}/components/libraries/log/src/nrf_log_backend_serial.c
    ${NRF_SDK_DIR}/components/libraries/log/src/nrf_log_default_backends.c
    ${NRF_SDK_DIR}/components/libraries/log/src/nrf_log_frontend.c
    ${NRF_SDK_DIR}/components/libraries/log/src/nrf_log_str_formatter.c

    ### External Libraries
    ${NRF_SDK_DIR}/external/fprintf/nrf_fprintf.c
    ${NRF_SDK_DIR}/external/fprintf/nrf_fprintf_format.c
    ${NRF_SDK_DIR}/external/nano-pb/pb_common.c
    ${NRF_SDK_DIR}/external/nano-pb/pb_decode.c
    ${NRF_SDK_DIR}/external/segger_rtt/SEGGER_RTT.c
    ${NRF_SDK_DIR}/components/libraries/slip/slip.c

    ### HAL/Drivers
    ${NRF_SDK_DIR}/integration/nrfx/legacy/nrf_drv_clock.c
    ${NRF_SDK_DIR}/integration/nrfx/legacy/nrf_drv_power.c
    ${NRF_SDK_DIR}/modules/nrfx/drivers/src/nrfx_clock.c
    ${NRF_SDK_DIR}/modules/nrfx/drivers/src/nrfx_usbd.c
    ${NRF_SDK_DIR}/modules/nrfx/drivers/src/nrfx_power.c
    ${NRF_SDK_DIR}/modules/nrfx/hal/nrf_nvmc.c
    ${NRF_SDK_DIR}/modules/nrfx/soc/nrfx_atomic.c

    ### SoftDevice & Board
    ${NRF_SDK_DIR}/components/boards/boards.c
    ${NRF_SDK_DIR}/components/softdevice/common/nrf_sdh.c
    ${NRF_SDK_DIR}/components/softdevice/common/nrf_sdh_ble.c
    ${NRF_SDK_DIR}/components/softdevice/common/nrf_sdh_soc.c
    ${NRF_SDK_DIR}/components/ble/common/ble_srv_common.c
)
    
target_link_options(${EXECUTABLE} PRIVATE
    -T${LINKER_FILE}
    -L${LINKER_DIR}
    -L${SD_LINKER_DIR}
    -L${NRF_SDK_LINKER_DIR}
    -L${NRF_SDK_DIR}/external/nrf_cc310_bl/lib/cortex-m4/hard-float
    -mcpu=cortex-m4
    -mfpu=fpv4-sp-d16
    -mfloat-abi=hard
    -mthumb
    --specs=nano.specs 
    --specs=nosys.specs
    -Wl,-Map=${PROJECT_NAME}.map,--cref
    -Wl,--gc-sections
    -Xlinker -print-memory-usage -Xlinker
)

target_link_libraries(${EXECUTABLE} PRIVATE
    prj_config
    nrf_cc310_bl_0.9.13
)

# Optional: Print executable size as part of the post build process
add_custom_command(TARGET ${EXECUTABLE}
        POST_BUILD
        COMMAND ${CMAKE_SIZE} ${EXECUTABLE})

# Optional: Create hex, bin and S-Record files after the build
add_custom_command(TARGET ${EXECUTABLE}
        POST_BUILD
        COMMAND ${CMAKE_OBJCOPY} -O srec --srec-len=64 ${EXECUTABLE} ${PROJECT_NAME}.s19
        COMMAND ${CMAKE_OBJCOPY} -O ihex ${EXECUTABLE} ${PROJECT_NAME}.hex
        COMMAND ${CMAKE_OBJCOPY} -O binary ${EXECUTABLE} ${PROJECT_NAME}.bin
)