Files
AVRDxBlink/CMakeLists.txt
T
2026-06-16 20:13:26 +02:00

91 lines
3.4 KiB
CMake

cmake_minimum_required(VERSION 3.10)
# Set the toolchain file BEFORE the project() call
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/.cmake/avr-gcc.cmake)
project(AVRDxBlink C)
# Configurable variables
set(MCU "avr128db28" CACHE STRING "Target Microcontroller")
set(F_CPU "20000000" CACHE STRING "Clock frequency in Hz")
set(DEVICE_PACK_DIR "/opt/toolchains/microchip/device-packs/AVRDx" CACHE STRING "Path to Device Packs")
set(PROGRAMMER "pickit4_updi" CACHE STRING "Programmer for avrdude") # often pickit4_updi is the right name for UPDI
# Include Device Pack
# -B instructs gcc to look for device-specific binaries/specs in this folder
# -I adds the device-specific headers
set(AVR_PACK_FLAGS "-B${DEVICE_PACK_DIR}/gcc/dev/${MCU} -I${DEVICE_PACK_DIR}/include")
# Clangd (and therefore eglot/lsp) often does not know about the AVR Device Pack.
# We define the corresponding macro manually so <avr/io.h> works.
string(TOUPPER "${MCU}" MCU_UPPER)
set(AVR_MACRO "-D__AVR_${MCU_UPPER}__ -D__AVR_DEVICE_NAME__=${MCU}")
# If the MCU is a modern AVR (Dx/Ex) or XMEGA, avr-gcc defines __AVR_XMEGA__ internally.
# Clangd needs this so <avr/fuse.h> uses NVM_FUSES_t instead of the old __fuse_t.
if(MCU MATCHES "^avr[0-9]+" OR MCU MATCHES "^atxmega")
set(AVR_MACRO "${AVR_MACRO} -D__AVR_XMEGA__")
endif()
# Set Build Type (Default: Release)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type: Debug or Release" FORCE)
endif()
# General Compiler Flags (for all build types)
# -ffunction-sections and -fdata-sections allow the linker to remove unused code
set(COMMON_FLAGS "-mmcu=${MCU} ${AVR_MACRO} -DF_CPU=${F_CPU}UL -Wall -Wstrict-prototypes -std=gnu99 ${AVR_PACK_FLAGS} -ffunction-sections -fdata-sections")
set(CMAKE_C_FLAGS "${COMMON_FLAGS}")
# Specific flags for Debug and Release
set(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -DDEBUG")
set(CMAKE_C_FLAGS_RELEASE "-Os -DNDEBUG")
# Linker Flags: -Wl,--gc-sections removes everything that is not needed
set(CMAKE_EXE_LINKER_FLAGS "-mmcu=${MCU} ${AVR_PACK_FLAGS} -Wl,--gc-sections")
# Generate compile_commands.json for Emacs/clangd (code completion)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Source and Header files
file(GLOB_RECURSE SRC_FILES src/*.c)
list(FILTER SRC_FILES EXCLUDE REGEX "/[.]#") # Ignore Emacs lock files like .#main.c
include_directories(inc)
# Generate Executable (.elf)
add_executable(${PROJECT_NAME}.elf ${SRC_FILES})
# Display size after build (Hex file is obsolete thanks to ELF support)
add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
COMMAND avr-size --format=avr --mcu=${MCU} ${PROJECT_NAME}.elf
)
# --- Avrdude Programming Targets ---
# F6: Program Flash only
add_custom_target(flash
COMMAND avrdude -c ${PROGRAMMER} -p ${MCU} -U flash:w:${PROJECT_NAME}.elf:e
DEPENDS ${PROJECT_NAME}.elf
COMMENT "Flashing program code (Flash)..."
)
# C-F6: Program Flash and EEPROM
add_custom_target(flash_eeprom
COMMAND avrdude -c ${PROGRAMMER} -p ${MCU} -U flash:w:${PROJECT_NAME}.elf:e -U eeprom:w:${PROJECT_NAME}.elf:e
DEPENDS ${PROJECT_NAME}.elf
COMMENT "Flashing program code and EEPROM..."
)
# F7: Read Fuses
add_custom_target(read_fuses
COMMAND avrdude -c ${PROGRAMMER} -p ${MCU} -U fuses:r:-:h
COMMENT "Reading fuses..."
)
# C-F7: Program Fuses only
add_custom_target(flash_fuses
COMMAND avrdude -c ${PROGRAMMER} -p ${MCU} -U fuses:w:${PROJECT_NAME}.elf:e
DEPENDS ${PROJECT_NAME}.elf
COMMENT "Programming fuses from ELF file..."
)