diff --git a/generic-gcc-avr.cmake b/generic-gcc-avr.cmake new file mode 100644 index 0000000000000000000000000000000000000000..6842d4fb0cd9265b3088e308d87da1b8e4621629 --- /dev/null +++ b/generic-gcc-avr.cmake @@ -0,0 +1,287 @@ +########################################################################## +# "THE ANY BEVERAGE-WARE LICENSE" (Revision 42 - based on beer-ware +# license): +# <dev@layer128.net> wrote this file. As long as you retain this notice +# you can do whatever you want with this stuff. If we meet some day, and +# you think this stuff is worth it, you can buy me a be(ve)er(age) in +# return. (I don't like beer much.) +# +# Matthias Kleemann +########################################################################## + +########################################################################## +# The toolchain requires some variables set. +# +# AVR_MCU (default: atmega8) +# the type of AVR the application is built for +# AVR_L_FUSE (NO DEFAULT) +# the LOW fuse value for the MCU used +# AVR_H_FUSE (NO DEFAULT) +# the HIGH fuse value for the MCU used +# AVR_UPLOADTOOL (default: avrdude) +# the application used to upload to the MCU +# NOTE: The toolchain is currently quite specific about +# the commands used, so it needs tweaking. +# AVR_UPLOADTOOL_PORT (default: usb) +# the port used for the upload tool, e.g. usb +# AVR_PROGRAMMER (default: avrispmkII) +# the programmer hardware used, e.g. avrispmkII +########################################################################## + +########################################################################## +# options +########################################################################## +option(WITH_MCU "Add the mCU type to the target file name." ON) + +########################################################################## +# executables in use +########################################################################## +find_program(AVR_CC avr-gcc) +find_program(AVR_CXX avr-g++) +find_program(AVR_OBJCOPY avr-objcopy) +find_program(AVR_SIZE_TOOL avr-size) +find_program(AVR_OBJDUMP avr-objdump) + +########################################################################## +# toolchain starts with defining mandatory variables +########################################################################## +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR avr) +set(CMAKE_C_COMPILER ${AVR_CC}) +set(CMAKE_CXX_COMPILER ${AVR_CXX}) + +########################################################################## +# Identification +########################################################################## +set(AVR 1) + +########################################################################## +# check build types: +# - Debug +# - Release +# - RelWithDebInfo +# +# Release is chosen, because of some optimized functions in the +# AVR toolchain, e.g. _delay_ms(). +########################################################################## +if(NOT ((CMAKE_BUILD_TYPE MATCHES Release) OR +(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) OR +(CMAKE_BUILD_TYPE MATCHES Debug) OR +(CMAKE_BUILD_TYPE MATCHES MinSizeRel))) + set( + CMAKE_BUILD_TYPE Release + CACHE STRING "Choose cmake build type: Debug Release RelWithDebInfo MinSizeRel" + FORCE + ) +endif(NOT ((CMAKE_BUILD_TYPE MATCHES Release) OR +(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) OR +(CMAKE_BUILD_TYPE MATCHES Debug) OR +(CMAKE_BUILD_TYPE MATCHES MinSizeRel))) + +########################################################################## + +########################################################################## +# target file name add-on +########################################################################## +if(WITH_MCU) + set(MCU_TYPE_FOR_FILENAME "-${AVR_MCU}") +else(WITH_MCU) + set(MCU_TYPE_FOR_FILENAME "") +endif(WITH_MCU) + +########################################################################## +# add_avr_executable +# - IN_VAR: EXECUTABLE_NAME +# +# Creates targets and dependencies for AVR toolchain, building an +# executable. Calls add_executable with ELF file as target name, so +# any link dependencies need to be using that target, e.g. for +# target_link_libraries(<EXECUTABLE_NAME>-${AVR_MCU}.elf ...). +########################################################################## +function(add_avr_executable EXECUTABLE_NAME) + if(NOT ARGN) + message(FATAL_ERROR "No source files given for ${EXECUTABLE_NAME}.") + endif(NOT ARGN) + + # set file names + set(elf_file ${EXECUTABLE_NAME}${MCU_TYPE_FOR_FILENAME}.elf) + set(hex_file ${EXECUTABLE_NAME}${MCU_TYPE_FOR_FILENAME}.hex) + set(map_file ${EXECUTABLE_NAME}${MCU_TYPE_FOR_FILENAME}.map) + set(eeprom_image ${EXECUTABLE_NAME}${MCU_TYPE_FOR_FILENAME}-eeprom.hex) + + # elf file + add_executable(${elf_file} EXCLUDE_FROM_ALL ${ARGN}) + + set_target_properties( + ${elf_file} + PROPERTIES + COMPILE_FLAGS "-mmcu=${AVR_MCU}" + LINK_FLAGS "-mmcu=${AVR_MCU} -Wl,--gc-sections -mrelax -Wl,-Map,${map_file}-Wl,-u,vfprintf -lprintf_flt -lm" + ) + + add_custom_command( + OUTPUT ${hex_file} + COMMAND + ${AVR_OBJCOPY} -j .text -j .data -O ihex ${elf_file} ${hex_file} + COMMAND + ${AVR_SIZE_TOOL} ${AVR_SIZE_ARGS} ${elf_file} + DEPENDS ${elf_file} + ) + + # eeprom + add_custom_command( + OUTPUT ${eeprom_image} + COMMAND + ${AVR_OBJCOPY} -j .eeprom --set-section-flags=.eeprom=alloc,load + --change-section-lma .eeprom=0 --no-change-warnings + -O ihex ${elf_file} ${eeprom_image} + DEPENDS ${elf_file} + ) + + add_custom_target( + ${EXECUTABLE_NAME} + ALL + DEPENDS ${hex_file} ${eeprom_image} + ) + + set_target_properties( + ${EXECUTABLE_NAME} + PROPERTIES + OUTPUT_NAME "${elf_file}" + ) + + # clean + get_directory_property(clean_files ADDITIONAL_MAKE_CLEAN_FILES) + set_directory_properties( + PROPERTIES + ADDITIONAL_MAKE_CLEAN_FILES "${map_file}" + ) + + # upload - with dfu-programmer + add_custom_target( + upload_${EXECUTABLE_NAME} + + ${AVR_UPLOADTOOL} ${AVR_MCU} erase --force + COMMAND ${AVR_UPLOADTOOL} ${AVR_MCU} flash ${hex_file} + DEPENDS ${hex_file} + COMMENT "Uploading ${hex_file} to ${AVR_MCU} using ${AVR_UPLOADTOOL}" + ) + + # upload eeprom only - with dfu-programmer + add_custom_target( + upload_eeprom + ${AVR_UPLOADTOOL} ${AVR_MCU} flash-eeprom ${eeprom_image} + DEPENDS ${eeprom_image} + COMMENT "Uploading ${eeprom_image} to ${AVR_MCU} using ${AVR_UPLOADTOOL}" + ) + + # disassemble + add_custom_target( + disassemble_${EXECUTABLE_NAME} + ${AVR_OBJDUMP} -h -S ${elf_file} > ${EXECUTABLE_NAME}.lst + DEPENDS ${elf_file} + ) + +endfunction(add_avr_executable) + +########################################################################## +# add_avr_library +# - IN_VAR: LIBRARY_NAME +# +# Calls add_library with an optionally concatenated name +# <LIBRARY_NAME>${MCU_TYPE_FOR_FILENAME}. +# This needs to be used for linking against the library, e.g. calling +# target_link_libraries(...). +########################################################################## +function(add_avr_library LIBRARY_NAME) + if(NOT ARGN) + message(FATAL_ERROR "No source files given for ${LIBRARY_NAME}.") + endif(NOT ARGN) + + set(lib_file ${LIBRARY_NAME}${MCU_TYPE_FOR_FILENAME}) + + add_library(${lib_file} STATIC ${ARGN}) + + set_target_properties( + ${lib_file} + PROPERTIES + COMPILE_FLAGS "-mmcu=${AVR_MCU}" + OUTPUT_NAME "${lib_file}" + ) + + if(NOT TARGET ${LIBRARY_NAME}) + add_custom_target( + ${LIBRARY_NAME} + ALL + DEPENDS ${lib_file} + ) + + set_target_properties( + ${LIBRARY_NAME} + PROPERTIES + OUTPUT_NAME "${lib_file}" + ) + endif(NOT TARGET ${LIBRARY_NAME}) + +endfunction(add_avr_library) + +########################################################################## +# avr_target_link_libraries +# - IN_VAR: EXECUTABLE_TARGET +# - ARGN : targets and files to link to +# +# Calls target_link_libraries with AVR target names (concatenation, +# extensions and so on. +########################################################################## +function(avr_target_link_libraries EXECUTABLE_TARGET) + if(NOT ARGN) + message(FATAL_ERROR "Nothing to link to ${EXECUTABLE_TARGET}.") + endif(NOT ARGN) + + get_target_property(TARGET_LIST ${EXECUTABLE_TARGET} OUTPUT_NAME) + + foreach(TGT ${ARGN}) + if(TARGET ${TGT}) + get_target_property(ARG_NAME ${TGT} OUTPUT_NAME) + list(APPEND TARGET_LIST ${ARG_NAME}) + else(TARGET ${TGT}) + list(APPEND NON_TARGET_LIST ${TGT}) + endif(TARGET ${TGT}) + endforeach(TGT ${ARGN}) + + target_link_libraries(${TARGET_LIST} ${NON_TARGET_LIST}) +endfunction(avr_target_link_libraries EXECUTABLE_TARGET) + +########################################################################## +# avr_target_include_directories +# +# Calls target_include_directories with AVR target names +########################################################################## + +function(avr_target_include_directories EXECUTABLE_TARGET) + if(NOT ARGN) + message(FATAL_ERROR "No include directories to add to ${EXECUTABLE_TARGET}.") + endif() + + get_target_property(TARGET_LIST ${EXECUTABLE_TARGET} OUTPUT_NAME) + set(extra_args ${ARGN}) + + target_include_directories(${TARGET_LIST} ${extra_args}) +endfunction() + +########################################################################## +# avr_target_compile_definitions +# +# Calls target_compile_definitions with AVR target names +########################################################################## + +function(avr_target_compile_definitions EXECUTABLE_TARGET) + if(NOT ARGN) + message(FATAL_ERROR "No compile definitions to add to ${EXECUTABLE_TARGET}.") + endif() + + get_target_property(TARGET_LIST ${EXECUTABLE_TARGET} OUTPUT_NAME) + set(extra_args ${ARGN}) + + target_compile_definitions(${TARGET_LIST} ${extra_args}) +endfunction() \ No newline at end of file