Old thread, but I finally had to remove platformio. Posting this here for anyone else that comes by.
This has only been used on Linux. Not sure what happens on Windows or macOS.
### Arduino
The Arduino IDE is used for the compiler, Teensy cores and libraries. All updates are handled through the Arduino IDE and its board and library manager.
1. Download and install the Arduino IDE 2.x
-
https://www.arduino.cc/en/software
2. Install Teensy into Arduino
-
https://www.pjrc.com/teensy/td_download.html
- In `File > Preferences`
- `Show verbose output`: `compile` and `upload` (useful for toolchain development)
- `Additional boards manager URLs`: `
https://www.pjrc.com/teensy/package_teensy_index.json`
### CLion
#### Toolchain
Create a new toolchain in Clion Settings:
1. In Clion `Settings > Build, Execution, Deployment > Toolchains`
2. Remove exciting
3. Create new toolchain:
- Name: `arduino_teensy`
- CMake `Bundled` (default)
- Build Tool: `Ninja` (default)
- C Compiler: `/home/{{user}}/.arduino15/packages/teensy/tools/teensy-compile/11.3.1/arm/bin/arm-none-eabi-gcc` (replace user)
- C++ Compiler: `/home/{{craiuserg}}/.arduino15/packages/teensy/tools/teensy-compile/11.3.1/arm/bin/arm-none-eabi-g++` (replace user)
### CMake
Crate a cmake profile
1. In Clion `Settings > Build, Execution, Deployment > CMake`
2. Delete any existing profiles
3. Create a new profile:
-Name: `Release`
-Build Type: `Release`
-Toolchain: `arduino_teensy` (default)
-Generator: `Ninja` (default)
-CMake Options: (leave empty to use defaults in grey)
-Build Options: (leave empty to use defaults in grey)
### Configurations
The following configurations are created:
- `{{project}}_elf`: compiles project to elf
- `{{project}}_hex`: compiles and converts elf to hex
- `{{project}}_upload`: compiles and uploads
Code:
cmake_minimum_required(VERSION 3.27)
# arduino home
# must install arduino ide
# https://www.arduino.cc/en/software
set(ARDUINO_PATH "$ENV{HOME}/.arduino15")
# add teensy 4 (4.0 and 4.1) toolchain
# path changes for each project
include("${CMAKE_SOURCE_DIR}/../../cmake/teensy4.toolchain.cmake")
# project
project(examples C CXX)
# remove clion -MD so can use -MMD
# https://discourse.cmake.org/t/how-to-force-cmake-use-mmd-flag-instead-of-md/9120/8
string(REPLACE "-MD" "" CMAKE_DEPFILE_FLAGS_C "${CMAKE_DEPFILE_FLAGS_C}")
string(REPLACE "-MD" "" CMAKE_DEPFILE_FLAGS_CXX "${CMAKE_DEPFILE_FLAGS_CXX}")
## set vars
set(TEENSY_VERSION 40 "[40, 41]" FORCE)
# arduino libs
teensy_add_arduino_library(EEPROM)
teensy_add_arduino_library(SPI)
teensy_add_arduino_library(Wire)
# executable: blank
teensy_add_executable(blink blink.cpp)
# executable: libs
teensy_add_executable(libs libs.cpp)
teensy_target_link_libraries(libs EEPROM SPI Wire)
# executable: serial
teensy_add_executable(serial serial.cpp)
Code:
# GoToTags
# heavily based on code from these projects:
# https://github.com/newdigate/teensy-cmake-macros/blob/main/cmake/teensy.cmake
# https://github.com/ronj/teensy-cmake-template/blob/master/toolchains/teensy.cmake
# https://github.com/platformio/platform-teensy
# https://github.com/PaulStoffregen/cores/blob/master/teensy4/Makefile
cmake_minimum_required(VERSION 3.25)
# cmake
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
set(CMAKE_CXX_STANDARD 17)
set(TEENSY_CORE_PATH "${ARDUINO_PATH}/packages/teensy/hardware/avr/1.59.0/cores/teensy4/" CACHE INTERNAL "TEENSY_CORE_PATH")
message(STATUS "TEENSY_CORE_PATH: ${TEENSY_CORE_PATH}")
set(ARDUINO_LIBS_PATH "${ARDUINO_PATH}/packages/teensy/hardware/avr/1.59.0/libraries/" CACHE INTERNAL "ARDUINO_LIBS_PATH")
message(STATUS "ARDUINO_LIBS_PATH: ${ARDUINO_LIBS_PATH}")
set(TEENSY_LOADER_CLI "${CMAKE_CURRENT_LIST_DIR}/../teensy_loader_cli/linux/teensy_loader_cli" CACHE INTERNAL "TEENSY_LOADER_CLI")
message(STATUS "TEENSY_LOADER_CLI: ${TEENSY_LOADER_CLI}")
# remove clion defaults
string(REPLACE "-O3" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
# teensy init
function(teensy_init)
#message(STATUS "teensy_init()")
get_property(teensy_init_run GLOBAL PROPERTY TEENSY_INIT_RUN)
if (NOT teensy_init_run)
message(STATUS "teensy_init_run()")
set_property(GLOBAL PROPERTY TEENSY_INIT_RUN TRUE)
teensy_vars()
teensy_lib()
endif()
endfunction()
# teensy vars
function(teensy_vars)
#message(STATUS "teensy_vars()")
get_property(teensy_vars_run GLOBAL PROPERTY TEENSY_VARS_RUN)
if (NOT teensy_vars_run)
message(STATUS "teensy_vars_run()")
set_property(GLOBAL PROPERTY TEENSY_VARS_RUN TRUE)
# teensy version
if (NOT DEFINED TEENSY_VERSION)
message(FATAL_ERROR "TEENSY_VERSION not set!")
else()
message(STATUS "TEENSY_VERSION: ${TEENSY_VERSION}")
endif()
# vars different for teensy versions
if(TEENSY_VERSION EQUAL 40)
set(MCU "ARDUINO_TEENSY40")
set(build_flags_optimize "-Os")
set(LINKER_FILE ${TEENSY_CORE_PATH}imxrt1062.ld)
elseif (TEENSY_VERSION EQUAL 41)
set(MCU "ARDUINO_TEENSY41")
set(build_flags_optimize "-O2")
set(LINKER_FILE ${TEENSY_CORE_PATH}imxrt1062_t41.ld)
else()
message(FATAL_ERROR "Unknown TEENSY_VERSION: ${TEENSY_VERSION}")
endif()
# common vars
set(build_flags_cpu "-mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16")
set(build_flags_libs "-lm")
set(build_flags_ld "-Wl,--gc-sections,--relax,-v")
# compile flags
set(COMPILE_FLAGS "-v -D${MCU} -D__IMXRT1062__ -DARDUINO=10607 -DTEENSYDUINO=159 -DF_CPU=600000000 -DUSB_SERIAL -DLAYOUT_US_ENGLISH ${build_flags_cpu} -Wall -g ${build_flags_optimize} -ffunction-sections -fdata-sections -MMD")
# these are cached for use outside scope of this function
# compile c++
set(CPP_COMPILE_FLAGS "${COMPILE_FLAGS} -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing" CACHE INTERNAL "CPP_COMPILE_FLAGS")
#message(STATUS "CPP_COMPILE_FLAGS: ${CPP_COMPILE_FLAGS}")
# compile c
set(C_COMPILE_FLAGS "${COMPILE_FLAGS}" CACHE INTERNAL "C_COMPILE_FLAGS")
#message(STATUS "C_COMPILE_FLAGS: ${C_COMPILE_FLAGS}")
# link flags
set(LINK_FLAGS "${build_flags_optimize} ${build_flags_ld} ${build_flags_cpu} -T${LINKER_FILE} ${build_flags_libs}" CACHE INTERNAL "C_COMPILE_FLAGS")
#message(STATUS "LINK_FLAGS: ${LINK_FLAGS}")
endif()
endfunction()
function(teensy_lib)
message(STATUS "teensy_lib()")
set(TEENSY_LIB Teensy CACHE INTERNAL "TEENSY_LIB")
teensy_add_library(${TEENSY_LIB} ${TEENSY_CORE_PATH})
endfunction()
# teensy_add_executable
function(teensy_add_executable TARGET)
message(STATUS "teensy_add_executable(${TARGET} ${ARGN})")
teensy_init()
# find all .cpp files and add to TEENSY_EXE_CPP_SOURCES
foreach(arg IN LISTS ARGN)
#message(STATUS "teensy_add_executable: arg=${arg}")
file(GLOB TEST_SOURCE RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${arg})
list(FILTER TEST_SOURCE INCLUDE REGEX ".cpp$")
set(TEENSY_EXE_CPP_SOURCES ${TEENSY_EXE_CPP_SOURCES} ${TEST_SOURCE})
endforeach()
#message(STATUS "teensy_add_executable: TEENSY_EXE_CPP_SOURCES=${TEENSY_EXE_CPP_SOURCES}")
# set_source_files_properties on app .cpp files
foreach(SOURCE_CPP ${TEENSY_EXE_CPP_SOURCES})
#message(STATUS "teensy_add_executable: SOURCE_CPP=${SOURCE_CPP}")
set_source_files_properties(${SOURCE_CPP} PROPERTIES COMPILE_FLAGS "${CPP_COMPILE_FLAGS}")
endforeach()
# elf
set(ELF_TARGET "${TARGET}_elf")
set(ELF_FILE "${TARGET}.elf")
# executable
add_executable(${ELF_TARGET} ${TEENSY_EXE_CPP_SOURCES})
set_target_properties(${ELF_TARGET} PROPERTIES OUTPUT_NAME ${ELF_FILE})
# link flags
set_target_properties(${ELF_TARGET} PROPERTIES LINK_FLAGS "${LINK_FLAGS}")
# target_link_options(${ELF_TARGET} PUBLIC ${LINK_FLAGS})
# link to Teensy lib
target_link_libraries(${ELF_TARGET} PRIVATE ${TEENSY_LIB})
# elf
set(HEX_TARGET "${TARGET}_hex")
set(HEX_FILE "${TARGET}.hex")
# convert elf to hex
add_custom_command(OUTPUT ${HEX_FILE}
COMMAND ${COMPILERPATH}arm-none-eabi-size ${ELF_FILE}
COMMAND ${COMPILERPATH}arm-none-eabi-objcopy -O ihex -R .eeprom ${ELF_FILE} ${HEX_FILE}
DEPENDS ${ELF_TARGET}
COMMENT "Converting ${ELF_FILE} to ${HEX_FILE}")
add_custom_target(${HEX_TARGET} ALL DEPENDS ${HEX_FILE})
# build elf before hex
add_dependencies(${HEX_TARGET} ${ELF_TARGET})
# upload target
add_custom_target("${TARGET}_upload"
COMMAND ${TEENSY_LOADER_CLI} -w -s -v -mmcu=IMXRT1062 ${HEX_FILE}
DEPENDS ${HEX_FILE}
COMMENT "Uploading ${HEX_FILE} to Teensy 4"
)
endfunction()
function(teensy_add_arduino_library LIB_NAME)
message(STATUS "teensy_add_arduino_library(${LIB_NAME})")
teensy_init()
set(LIB_ROOT "${ARDUINO_LIBS_PATH}${LIB_NAME}/")
teensy_add_library(${LIB_NAME} ${LIB_ROOT})
endfunction()
function(teensy_add_library LIB_NAME LIB_ROOT)
message(STATUS "teensy_add_library(${LIB_NAME} ${LIB_ROOT})")
teensy_init()
# lib .c files
file(GLOB_RECURSE C_FILES ABSOLUTE ${LIB_ROOT}**.c)
#message(STATUS "C_FILES: ${C_FILES}")
foreach(SOURCE_C ${C_FILES})
set_source_files_properties(${SOURCE_C} PROPERTIES COMPILE_FLAGS "${C_COMPILE_FLAGS}")
endforeach()
# lib .cpp files
file(GLOB_RECURSE CPP_FILES ${LIB_ROOT}**.cpp)
#message(STATUS "CPP_FILES: ${CPP_FILES}")
foreach(SOURCE_CPP ${CPP_FILES})
set_source_files_properties(${SOURCE_CPP} PROPERTIES COMPILE_FLAGS "${CPP_COMPILE_FLAGS}")
endforeach()
set(LIB_SOURCES ${C_FILES} ${CPP_FILES})
#message(STATUS "LIB_SOURCES: ${LIB_SOURCES}")
set(LIB_TARGET ${LIB_NAME})
# add library
add_library(${LIB_TARGET} STATIC ${LIB_SOURCES})
# include headers
target_include_directories(${LIB_TARGET} PUBLIC ${TEENSY_CORE_PATH} ${LIB_ROOT})
# link options
target_link_options(${LIB_TARGET} PRIVATE ${LINK_FLAGS})
endfunction()
# teensy_target_link_libraries
macro(teensy_target_link_libraries TARGET)
message(STATUS "teensy_target_link_libraries(${TARGET} ${ARGN})")
set(ELF_TARGET "${TARGET}_elf")
set(libs "${ARGN}")
foreach(lib IN LISTS libs)
target_link_libraries(${ELF_TARGET} PRIVATE ${lib})
endforeach()
endmacro()