diff options
| -rw-r--r-- | CMakeLists.txt | 18 | ||||
| -rw-r--r-- | cmake/arm-gcc-toolchain.cmake | 35 | ||||
| -rw-r--r-- | cmake/clang-arm-gcc-toolchain.cmake | 91 | ||||
| -rw-r--r-- | cmake/device.cmake | 2 | ||||
| -rw-r--r-- | cmake/device_utils.cmake | 15 | ||||
| -rw-r--r-- | cmake/utils.cmake | 123 | ||||
| -rw-r--r-- | device/MSP432P401R/MSP432P401R.cmake | 32 | ||||
| -rw-r--r-- | device/MSP432P401R/device.cpp | 8 | ||||
| -rw-r--r-- | device/MSP432P401R/gpio.cpp | 15 | ||||
| l--------- | device/MSP432P401R/msp432p4_sdk | 1 | ||||
| -rw-r--r-- | device/device.hpp | 3 | ||||
| -rw-r--r-- | device/gpio.hpp | 6 | ||||
| -rw-r--r-- | main.cpp | 13 |
13 files changed, 362 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..93476d6 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.20) + +set(DEVICE "MSP432P401R") +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") +set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_LIST_DIR}/cmake/arm-gcc-toolchain.cmake") + +include(device) + +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) +set(CMAKE_CXX_STANDARD 26) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +project(blinky LANGUAGES C CXX) +add_executable(blinky) +target_link_libraries(blinky PUBLIC toolchain) +target_link_libraries(blinky PUBLIC device) +target_include_directories(blinky PRIVATE .) +target_sources(blinky PRIVATE main.cpp) diff --git a/cmake/arm-gcc-toolchain.cmake b/cmake/arm-gcc-toolchain.cmake new file mode 100644 index 0000000..d7dc340 --- /dev/null +++ b/cmake/arm-gcc-toolchain.cmake @@ -0,0 +1,35 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR ARM) + +set(TOOLCHAIN_PREFIX "arm-none-eabi-") + +set(SPECS "-specs=nosys.specs -specs=nano.specs") + +# Without that flag CMake is not able to pass test compilation check +if (${CMAKE_VERSION} VERSION_EQUAL "3.6.0" OR ${CMAKE_VERSION} VERSION_GREATER "3.6") + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +endif () + +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc CACHE STRING "") +set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER} CACHE STRING "") +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++ CACHE STRING "") + +# Default C compiler flags +set(CMAKE_C_FLAGS_DEBUG_INIT "-g3 -Og -Wall -DDEBUG ${SPECS}") +set(CMAKE_C_FLAGS_RELEASE_INIT "-O3 -Wall ${SPECS}") +set(CMAKE_C_FLAGS_MINSIZEREL_INIT "-Os -Wall ${SPECS}") +set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "-O2 -g -Wall ${SPECS}") +# Default C++ compiler flags +set(CMAKE_CXX_FLAGS_DEBUG_INIT "-g3 -Og -Wall -DDEBUG ${SPECS}") +set(CMAKE_CXX_FLAGS_RELEASE_INIT "-O3 -Wall ${SPECS}") +set(CMAKE_CXX_FLAGS_MINSIZEREL_INIT "-Os -Wall ${SPECS}") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-O2 -g -Wall ${SPECS}") + +find_program(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy DOC "objcopy tool") +find_program(CMAKE_SIZE_UTIL ${TOOLCHAIN_PREFIX}size DOC "size tool") + +if (NOT TARGET toolchain) + add_library(toolchain INTERFACE) + target_compile_options(toolchain INTERFACE "-fno-exceptions") + target_link_options(toolchain INTERFACE "-Wl,--gc-sections" "-Wl,--print-memory-usage") +endif () diff --git a/cmake/clang-arm-gcc-toolchain.cmake b/cmake/clang-arm-gcc-toolchain.cmake new file mode 100644 index 0000000..091dad3 --- /dev/null +++ b/cmake/clang-arm-gcc-toolchain.cmake @@ -0,0 +1,91 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR ARM) + +set(TOOLCHAIN_PREFIX arm-none-eabi-) +set(TOOLCHAIN_TRIPLE arm-none-eabi) +find_program(BINUTILS_PATH ${TOOLCHAIN_PREFIX}gcc NO_CACHE) + +if (NOT BINUTILS_PATH) + message(FATAL_ERROR "ARM GCC toolchain not found") +endif () + +cmake_path(GET BINUTILS_PATH PARENT_PATH ARM_TOOLCHAIN_DIR) +set(ARM_GCC_C_COMPILER ${TOOLCHAIN_PREFIX}gcc) +execute_process(COMMAND ${ARM_GCC_C_COMPILER} -print-sysroot + OUTPUT_VARIABLE ARM_GCC_SYSROOT OUTPUT_STRIP_TRAILING_WHITESPACE) +# get GNU ARM GCC version +execute_process(COMMAND ${ARM_GCC_C_COMPILER} --version + OUTPUT_VARIABLE ARM_GCC_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) +string(REGEX MATCH " [0-9]+\.[0-9]+\.[0-9]+" ARM_GCC_VERSION ${ARM_GCC_VERSION}) +string(STRIP ${ARM_GCC_VERSION} ARM_GCC_VERSION) + +# set compiler triple +set(triple ${TOOLCHAIN_TRIPLE}) +set(CMAKE_ASM_COMPILER clang) +set(CMAKE_ASM_COMPILER_TARGET ${triple}) +set(CMAKE_C_COMPILER clang) +set(CMAKE_C_COMPILER_TARGET ${triple}) +set(CMAKE_CXX_COMPILER clang++) +set(CMAKE_CXX_COMPILER_TARGET ${triple}) + +set(CMAKE_C_FLAGS_INIT " -B${ARM_TOOLCHAIN_DIR}") +set(CMAKE_CXX_FLAGS_INIT " -B${ARM_TOOLCHAIN_DIR} ") +# Without that flag CMake is not able to pass test compilation check +if (${CMAKE_VERSION} VERSION_EQUAL "3.6.0" OR ${CMAKE_VERSION} VERSION_GREATER "3.6") + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +else () + set(CMAKE_EXE_LINKER_FLAGS_INIT "-nostdlib") +endif () + +set(CMAKE_OBJCOPY llvm-objcopy CACHE INTERNAL "objcopy tool") +set(CMAKE_SIZE_UTIL llvm-size CACHE INTERNAL "size tool") +# Default C compiler flags +set(CMAKE_C_FLAGS_DEBUG_INIT "-g3 -Og -Wall -pedantic -DDEBUG") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG_INIT}" CACHE STRING "" FORCE) +set(CMAKE_C_FLAGS_RELEASE_INIT "-O3 -Wall") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE_INIT}" CACHE STRING "" FORCE) +set(CMAKE_C_FLAGS_MINSIZEREL_INIT "-Oz -Wall") +set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL_INIT}" CACHE STRING "" FORCE) +set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "-O2 -g -Wall") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO_INIT}" CACHE STRING "" FORCE) +# Default C++ compiler flags +set(TOOLCHAIN_CXX_INCLUDE_DIRS_FLAG "") +string(APPEND TOOLCHAIN_CXX_INCLUDE_DIRS_FLAG " -cxx-isystem ${ARM_GCC_SYSROOT}/include/c++/${ARM_GCC_VERSION}") +string(APPEND TOOLCHAIN_CXX_INCLUDE_DIRS_FLAG " -cxx-isystem ${ARM_GCC_SYSROOT}/include/c++/${ARM_GCC_VERSION}/arm-none-eabi") +string(APPEND TOOLCHAIN_CXX_INCLUDE_DIRS_FLAG " -cxx-isystem ${ARM_GCC_SYSROOT}/include/c++/${ARM_GCC_VERSION}/backward") +set(CMAKE_CXX_FLAGS_DEBUG_INIT "-g3 -Og -Wall -pedantic -DDEBUG ${TOOLCHAIN_CXX_INCLUDE_DIRS_FLAG}") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG_INIT}" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_RELEASE_INIT "-O3 -Wall ${TOOLCHAIN_CXX_INCLUDE_DIRS_FLAG}") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE_INIT}" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_MINSIZEREL_INIT "-Oz -Wall ${TOOLCHAIN_CXX_INCLUDE_DIRS_FLAG}") +set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL_INIT}" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-O2 -g -Wall ${TOOLCHAIN_CXX_INCLUDE_DIRS_FLAG}") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT}" CACHE STRING "" FORCE) + +set(CMAKE_SYSROOT ${ARM_GCC_SYSROOT}) +set(CMAKE_FIND_ROOT_PATH ${ARM_GCC_SYSROOT}) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) + + +if (ARCH_FLAGS) + execute_process(COMMAND ${ARM_GCC_C_COMPILER} ${ARCH_FLAGS} -print-libgcc-file-name + OUTPUT_VARIABLE __ARM_GCC_LIBGCC + OUTPUT_STRIP_TRAILING_WHITESPACE) + cmake_path(GET __ARM_GCC_LIBGCC PARENT_PATH LIBGCC_DIR) + + execute_process(COMMAND ${ARM_GCC_C_COMPILER} ${ARCH_FLAGS} -print-multi-directory + OUTPUT_VARIABLE ARM_GCC_MULTIDIR + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if (NOT TARGET toolchain) + add_library(toolchain INTERFACE) + target_compile_options(toolchain INTERFACE "-fno-exceptions") + target_link_directories(toolchain INTERFACE "${LIBGCC_DIR}") + target_link_libraries(toolchain INTERFACE -nostdlib -lc_nano -lnosys -lgcc -lstdc++_nano -lm) + target_link_options(toolchain INTERFACE "-Wl,--gc-sections" "-Wl,--print-memory-usage") + + target_sources(toolchain INTERFACE "${LIBGCC_DIR}/crti.o" "${ARM_GCC_SYSROOT}/lib/${ARM_GCC_MULTIDIR}/crt0.o" "${LIBGCC_DIR}/crtbegin.o" "${LIBGCC_DIR}/crtend.o" "${LIBGCC_DIR}/crtn.o") + endif () +endif () diff --git a/cmake/device.cmake b/cmake/device.cmake new file mode 100644 index 0000000..d5b28da --- /dev/null +++ b/cmake/device.cmake @@ -0,0 +1,2 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/device/${DEVICE}/${DEVICE}.cmake") +message(STATUS "Device: ${DEVICE}") diff --git a/cmake/device_utils.cmake b/cmake/device_utils.cmake new file mode 100644 index 0000000..5309f5c --- /dev/null +++ b/cmake/device_utils.cmake @@ -0,0 +1,15 @@ +include(utils) + +function (create_device_target arch_flags device_defines include_dirs linker_script system_code) + add_library(device OBJECT) + + target_sources(device PRIVATE "${system_code}") + + target_compile_options(device PUBLIC "${arch_flags}") + target_compile_definitions(device PUBLIC "${device_defines}") + target_include_directories(device PRIVATE "${include_dirs}") + target_include_directories(device PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/device") + + target_link_options(device INTERFACE "${arch_flags}") + target_linker_script(device INTERFACE "${linker_script}") +endfunction () diff --git a/cmake/utils.cmake b/cmake/utils.cmake new file mode 100644 index 0000000..17fb235 --- /dev/null +++ b/cmake/utils.cmake @@ -0,0 +1,123 @@ +# Get all subdirectories under ${current_dir} and store them in ${result} variable +macro(subdirlist result current_dir) + file(GLOB children "${current_dir}/*") + set(dirlist "") + + foreach(child ${children}) + if (IS_DIRECTORY "${child}") + list(APPEND dirlist "${child}") + endif() + endforeach() + + set(${result} ${dirlist}) +endmacro() + +# Prepend ${CMAKE_CURRENT_SOURCE_DIR} to a ${directory} name and save it in PARENT_SCOPE ${variable} +macro(prepend_cur_dir variable directory) + set(${variable} "${CMAKE_CURRENT_SOURCE_DIR}/${directory}") +endmacro() + +# Add custom command to print firmware size in Berkeley format +function(firmware_size target) + add_custom_command(TARGET ${target} POST_BUILD + COMMAND ${CMAKE_SIZE_UTIL} -B "$<TARGET_FILE:${target}>" + ) +endfunction() + +# Add a command to generate firmware in a provided format +function(generate_object target suffix type) + add_custom_command(TARGET ${target} POST_BUILD + COMMAND ${CMAKE_OBJCOPY} -O ${type} "$<TARGET_FILE:${target}>" "${CMAKE_CURRENT_BINARY_DIR}/${target}${suffix}" + ) +endfunction() + +# Set linker script for a target +function(target_linker_script target scope script) + target_link_options(${target} "${scope}" "-T${script}") + + get_target_property(_cur_link_deps ${target} LINK_DEPENDS) + if (_cur_link_deps STREQUAL "_cur_link_deps-NOTFOUND") + set(_cur_link_deps "") + endif() + + string(APPEND _cur_link_deps "${script}") + set_target_properties(${target} PROPERTIES LINK_DEPENDS ${_cur_link_deps}) +endfunction() + +# Write file only if content has changed +function(write_file_if_changed file content) + if (EXISTS "${file}") + file(READ "${file}" existing_content) + else() + set(existing_content "") + endif() + + if (NOT "${existing_content}" STREQUAL "${content}") + file(WRITE "${file}" "${content}") + endif() +endfunction() + +# Embed a file into a target +function(embed_file target file symbol) + cmake_path(IS_ABSOLUTE file is_absolute) + if (NOT is_absolute) + set(file "${CMAKE_CURRENT_SOURCE_DIR}/${file}") + endif() + + cmake_path(GET file FILENAME filename) + + set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated") + if (NOT EXISTS "${generated_dir}") + file(MAKE_DIRECTORY "${generated_dir}") + endif() + + set(generated_objects "${generated_dir}_objects") + if (NOT EXISTS "${generated_objects}") + file(MAKE_DIRECTORY "${generated_objects}") + endif() + + set(asm_path "${generated_objects}/${filename}.S") + write_file_if_changed("${asm_path}" +".global ${symbol}_data +.global ${symbol}_size +.section .rodata +.align 4 +${symbol}_data: + .incbin \"${file}\" +1: +${symbol}_size: + .int 1b - ${symbol}_data +") + + add_custom_command(OUTPUT "${asm_path}" + COMMAND ${CMAKE_COMMAND} -E touch "${asm_path}" + DEPENDS "${file}") + + target_sources("${target}" PRIVATE "${asm_path}") + + set(header_path "${generated_dir}/${filename}") + + write_file_if_changed("${header_path}.h" +"#pragma once + +#ifdef __cplusplus +extern \"C\" { +#endif + +extern const char ${symbol}_data[]; +extern const unsigned int ${symbol}_size; + +#ifdef __cplusplus +} +#endif +") + + write_file_if_changed("${header_path}.hpp" +"#pragma once + +#include \"${header_path}.h\" +#include <span> + +inline const std::span<const char> ${symbol}{${symbol}_data, ${symbol}_size}; +") +endfunction() diff --git a/device/MSP432P401R/MSP432P401R.cmake b/device/MSP432P401R/MSP432P401R.cmake new file mode 100644 index 0000000..aa5a179 --- /dev/null +++ b/device/MSP432P401R/MSP432P401R.cmake @@ -0,0 +1,32 @@ +string(TOLOWER "${DEVICE}" DEVICE_LOWER) + +set(ARCH_FLAGS + -mcpu=cortex-m4 + -march=armv7e-m + -mthumb + -mfloat-abi=hard + -mfpu=fpv4-sp-d16) + +set(DEVICE_DEFINES + __MSP432P401R__ + DeviceFamily_MSP432P401x) + +set(SDK_DIR "${CMAKE_CURRENT_LIST_DIR}/msp432p4_sdk") + +set(INCLUDE_DIRS + "${SDK_DIR}/source" + "${SDK_DIR}/source/third_party/CMSIS/Include" +) + +set(FAMILY_DIR "${SDK_DIR}/source/ti/devices/msp432p4xx") + +set(LINKER_SCRIPT "${FAMILY_DIR}/linker_files/gcc/${DEVICE_LOWER}.lds") + +set(SYSTEM_CODE + "${FAMILY_DIR}/startup_system_files/system_${DEVICE_LOWER}.c" + "${FAMILY_DIR}/startup_system_files/gcc/startup_${DEVICE_LOWER}_gcc.c" +) + +include(device_utils) +create_device_target("${ARCH_FLAGS}" "${DEVICE_DEFINES}" "${INCLUDE_DIRS}" "${LINKER_SCRIPT}" "${SYSTEM_CODE}") +target_sources(device PRIVATE "${CMAKE_CURRENT_LIST_DIR}/gpio.cpp") diff --git a/device/MSP432P401R/device.cpp b/device/MSP432P401R/device.cpp new file mode 100644 index 0000000..d1753d6 --- /dev/null +++ b/device/MSP432P401R/device.cpp @@ -0,0 +1,8 @@ +#include <device.hpp> + +#include <ti/devices/msp432p4xx/inc/msp432p401r.h> + +void hardwareInit() +{ + WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD; +} diff --git a/device/MSP432P401R/gpio.cpp b/device/MSP432P401R/gpio.cpp new file mode 100644 index 0000000..20911ed --- /dev/null +++ b/device/MSP432P401R/gpio.cpp @@ -0,0 +1,15 @@ +#include <gpio.hpp> + +#include <cstdint> + +#include <ti/devices/msp432p4xx/inc/msp432p401r.h> + +void setupOutputs() +{ + P2->DIR = 0b111; +} + +void writeOutputs(std::uint8_t val) +{ + P2->OUT = val % 8; +} diff --git a/device/MSP432P401R/msp432p4_sdk b/device/MSP432P401R/msp432p4_sdk new file mode 120000 index 0000000..5b92425 --- /dev/null +++ b/device/MSP432P401R/msp432p4_sdk @@ -0,0 +1 @@ +/home/maxmitti/msp432/simplelink_msp432p4_sdk_3_40_01_02
\ No newline at end of file diff --git a/device/device.hpp b/device/device.hpp new file mode 100644 index 0000000..9ce4580 --- /dev/null +++ b/device/device.hpp @@ -0,0 +1,3 @@ +#pragma once + +void hardwareInit(); diff --git a/device/gpio.hpp b/device/gpio.hpp new file mode 100644 index 0000000..1672aaf --- /dev/null +++ b/device/gpio.hpp @@ -0,0 +1,6 @@ +#pragma once + +#include <cstdint> + +void setupOutputs(); +void writeOutputs(std::uint8_t value); diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..b7db9bc --- /dev/null +++ b/main.cpp @@ -0,0 +1,13 @@ +#include <device/gpio.hpp> + +int main() +{ + setupOutputs(); + + for (std::uint8_t i = 0;; ++i) + { + writeOutputs(i % 8); + + for (volatile std::uint16_t delay = 0; delay < 10000; ++delay); + } +} |
