Skip to content

Instantly share code, notes, and snippets.

@JuanM04
Last active May 9, 2025 23:36
Show Gist options
  • Save JuanM04/dc843ba1e2ac0e29775aff6701dc7c1e to your computer and use it in GitHub Desktop.
Save JuanM04/dc843ba1e2ac0e29775aff6701dc7c1e to your computer and use it in GitHub Desktop.
Configuración de CMake para AVR
##################################################################################
# Configuración de CMake para proyectos de AVR
# Intenta emular el comportamiento de Microchip Studio
#
# Referencias:
# https://www.kuon.ch/post/2018-07-11-avr-cmake/
# https://github.com/mkleemann/cmake-avr/tree/642828d406e76a875ed2227309f3bf962fa7feaf
#
# Inicialzación de CMake:
# - Para crear una salida de debug:
# mkdir Debug && cd Debug
# cmake -DCMAKE_BUILD_TYPE=Debug -DAVR_PATH=ruta/a/avr -DAVRDUDE_PATH=ruta/a/avrdude ..
# - Para crear una salida de release:
# mkdir Release && cd Release
# cmake -DCMAKE_BUILD_TYPE=Release -DAVR_PATH=ruta/a/avr -DAVRDUDE_PATH=ruta/a/avrdude ..
#
# Luego, dentro de la carpeta Debug o Release:
# - Para compilar el proyecto:
# cmake --build . --target all
# - Para limpiar la salida:
# cmake --build . --target clean
# - Para subir el programa al microcontrolador:
# cmake -DAVRDUDE_PORT=COM4 .. # setear el puerto de conexión
# cmake --build . --target upload # o upload_eeprom
#
##################################################################################
cmake_minimum_required(VERSION 3.30)
### TOOLCHAIN SETUP ######################################################
# Configuración de la toolchain para AVR.
# Se puede descargar desde la página de Microchip o utilizar la que viene
# con Microchip Studio.
#
# https://www.microchip.com/en-us/tools-resources/develop/microchip-studio/gcc-compilers
#
# Importante: esto debe ser configurado antes de ejecutar `project()`
# https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#method-3-avoid-use-set
##########################################################################
if(NOT DEFINED AVR_PATH)
message(FATAL_ERROR "Definí la ubicación de la toolchain de AVR en AVR_PATH.")
endif()
set(CMAKE_FIND_ROOT_PATH ${AVR_PATH})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
# No se agregan automáticamente, ya que más adelante
# se configura CMAKE_SYSTEM_NAME como Generic
set(CMAKE_SYSTEM_INCLUDE_PATH "${CMAKE_FIND_ROOT_PATH}/include")
set(CMAKE_SYSTEM_LIBRARY_PATH "${CMAKE_FIND_ROOT_PATH}/lib")
find_program(AVR_CC "${AVR_PATH}/bin/avr-gcc" REQUIRED)
find_program(AVR_CXX "${AVR_PATH}/bin/avr-g++" REQUIRED)
find_program(AVR_OBJCOPY "${AVR_PATH}/bin/avr-objcopy" REQUIRED)
find_program(AVR_SIZE_TOOL "${AVR_PATH}/bin/avr-size" REQUIRED)
find_program(AVR_OBJDUMP "${AVR_PATH}/bin/avr-objdump" REQUIRED)
##########################################################################
# También se recomienda instalar avrdude
# Se puede descargar desde https://github.com/avrdudes/avrdude/releases
##########################################################################
find_program(AVRDUDE avrdude PATHS "${AVRDUDE_PATH}")
##########################################################################
# Indicarle a CMake que va a compilar para AVR
##########################################################################
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR avr)
set(CMAKE_C_COMPILER ${AVR_CC})
set(CMAKE_CXX_COMPILER ${AVR_CXX})
### CONFIGURACIÓN GENERAL ################################################
# Configuración del proyecto, variables externas y otras opciones
# genéricas para cambiar de proyecto a proyecto.
##########################################################################
project(nombre-del-proyecto)
set(MCU atmega328p) # Microcontrolador utilizado
# Por defecto, CMAKE_BUILD_TYPE es Debug
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()
### MENSAJES DE INFORMACIÓN ##############################################
# Mensajes sobre la configuración de CMake
##########################################################################
execute_process(COMMAND ${AVR_CC} -dumpversion
OUTPUT_VARIABLE AVR_CC_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "====================================================")
message(STATUS "${PROJECT_NAME} (${CMAKE_BUILD_TYPE})")
message(STATUS "Versión de CMake : ${CMAKE_VERSION}")
message(STATUS "Versión de avr-gcc : ${AVR_CC_VERSION}")
message(STATUS "====================================================")
### CONFIGURACIÓN DE SALIDA ##############################################
# Opciones de compilación y enlazado, emulando el comportamiento de
# Microchip Studio.
##########################################################################
## Opciones de compilación
add_compile_options(
-x c # tratar todos los archivos como código C
-std=gnu99 # usar el estándar GNU99
-Wall # mostrar todas las advertencias
)
## Usar tipos de datos cortos (8 bits)
add_compile_options(
-funsigned-char # tratar char como sin signo
-funsigned-bitfields # tratar los bitfields como sin signo
-fpack-struct # empaquetar estructuras
-fshort-enums # crear enums con la menor cantidad de bytes posible
)
## Separar los archivos objeto por función
add_compile_options(
-ffunction-sections # separar las funciones en secciones
-fdata-sections # separar los datos en secciones
)
if(CMAKE_BUILD_TYPE MATCHES Release)
add_definitions(-DNDEBUG)
add_compile_options(-Os) # optimizar para tamaño (no velocidad)
else()
add_definitions(-DEBUG)
add_compile_options(-Og) # optimizar para debugging
add_compile_options(-g2) # incluir información de depuración nivel 2
endif()
## Opciones de enlazado
add_link_options(
-Wl,--start-group # declarar librerías a enlazar
-Wl,-lm # enlazar math
-Wl,--end-group # fin de la declaración
-Wl,--gc-sections # eliminar secciones no utilizadas
)
### SALIDAS ##############################################################
# Declaración de archivos fuente y de salida
##########################################################################
file(GLOB SRC_FILES "*.c")
## .map
set(map_file "${PROJECT_NAME}.map")
set_directory_properties(PROPERTIES ADDITIONAL_CLEAN_FILES "${map_file}")
## .elf
set(elf_file "${PROJECT_NAME}.elf")
add_executable(${elf_file} ${SRC_FILES})
set_target_properties(
${elf_file} PROPERTIES
COMPILE_FLAGS "-mmcu=${MCU}"
LINK_FLAGS "-mmcu=${MCU} -Wl,-Map=${map_file}"
)
## .hex
set(hex_file "${PROJECT_NAME}.hex")
add_custom_command(
OUTPUT ${hex_file}
COMMAND ${AVR_OBJCOPY} -R.eeprom -R.fuse -R.lock -R.signature -R.user_signatures -Oihex ${elf_file} ${hex_file}
COMMAND ${AVR_SIZE_TOOL} -C --mcu=${MCU} ${elf_file}
DEPENDS ${elf_file}
)
## .eep
set(eeprom_image "${PROJECT_NAME}.eep")
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 -Oihex ${elf_file} ${eeprom_image}
DEPENDS ${elf_file}
)
## .lss
set(listing_file "${PROJECT_NAME}.lss")
add_custom_command(
OUTPUT ${listing_file}
COMMAND ${AVR_OBJDUMP} -h -S ${elf_file} > ${listing_file}
DEPENDS ${elf_file}
)
## Generar .hex, .eep y .lss al compilar por defecto
add_custom_target(
"${PROJECT_NAME}" ALL
DEPENDS ${hex_file} ${eeprom_image} ${listing_file}
)
set_target_properties(
"${PROJECT_NAME}" PROPERTIES
OUTPUT_NAME "${elf_file}"
)
### AVRDUDE #############################################################
# Targets para subir el programa al microcontrolador
##########################################################################
if(DEFINED AVRDUDE)
## Tipo de programador
if(NOT AVRDUDE_PROGRAMMER)
set(AVRDUDE_PROGRAMMER arduino CACHE STRING "Programador de avrdude: arduino")
endif()
## Puerto de conexión
if(NOT AVRDUDE_PORT)
set(AVRDUDE_PORT usb CACHE STRING "Puerto de conexión: usb")
endif()
## Baud rate
if(NOT AVRDUDE_BAUD)
set(AVRDUDE_BAUD 115200 CACHE STRING "Baud rate: 115200")
endif()
## Subir .hex
add_custom_target(
upload
${AVRDUDE} -p ${MCU} -c ${AVRDUDE_PROGRAMMER} -P ${AVRDUDE_PORT} -b ${AVRDUDE_BAUD} -U flash:w:"${hex_file}":i
DEPENDS ${hex_file}
COMMENT "Subierndo ${hex_file} a ${MCU} utilizando ${AVRDUDE_PROGRAMMER}"
)
## Subir .eep
add_custom_target(
upload_eeprom
${AVRDUDE} -p ${MCU} -c ${AVRDUDE_PROGRAMMER} -P ${AVRDUDE_PORT} -b ${AVRDUDE_BAUD} -U eeprom:w:"${eeprom_image}":i
DEPENDS ${eeprom_image}
COMMENT "Subierndo ${eeprom_image} a ${MCU} utilizando ${AVRDUDE_PROGRAMMER}"
)
endif()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment