element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
    About the element14 Community
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      •  Vietnam
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Embedded and Microcontrollers
  • Technologies
  • More
Embedded and Microcontrollers
Blog MSPM0 project with VS Code, CMake and GCC - part 2: build a real project
  • Blog
  • Forum
  • Documents
  • Quiz
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Embedded and Microcontrollers to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Jan Cumps
  • Date Created: 2 Sep 2026 8:23 PM Date Created
  • Views 38 views
  • Likes 3 likes
  • Comments 0 comments
  • MSPM0L1105
  • ccs
  • MSPM0
  • VS Code
  • MSPM0L1306
  • vscode
  • code_composer_studio
Related
Recommended

MSPM0 project with VS Code, CMake and GCC - part 2: build a real project

Jan Cumps
Jan Cumps
2 Sep 2026

In this blog series, I build a Texas Instruments MSPM0 example with VS Code as IDE, and CMake as build infrastructure.
Post 1 covered the software setup. In this post: build firmware,

image

Configure Environment Variables

SDK_ROOT:

image

SYSCONFIG_CLI, TI Embedded toolchain path, Open OCD location: I set those in my Workspase settings.json file:

{
	"folders": [
		{
			"path": "msmp0_cmake"
		}
	],
	"settings": {
		"cmake.cmakePath": "C:/Users/jancu/.pico-sdk/cmake/v4.2.1/bin/cmake.exe",
		"cmake.generator": "Ninja",
		"cmake.environment": {
			"CMAKE_PROGRAM_PATH": "C:/Users/jancu/.pico-sdk/ninja/v1.13.2/ninja.exe",
			"SYSCONFIG_CLI": "C:/ti/sysconfig_1.27.1/sysconfig_cli.bat"
		},
		"cmake.configureEnvironment": {
			"SDK_ROOT": "C:/ti/mspm0_sdk_2_11_00_07"
		},
		"cmake.enableTraceLogging": false,
		"cmake.loggingLevel": "info",
		"ti-embedded-debug.armToolchainPath": "c:/Users/jancu/Documents/toolchains/arm-gnu-toolchain-15.2.rel1-mingw-w64-i686-arm-none-eabi/bin",
		"cortex-debug.armToolchainPath": "c:/Users/jancu/Documents/toolchains/arm-gnu-toolchain-15.2.rel1-mingw-w64-i686-arm-none-eabi/bin"
	}
}

    Build Project

    We 'll need 3 files to build firmware for the MSPM0:

    • system configuration (SysConfig)
    • C source
    • CMake script

    The first two can be taken from any Resource Explorer project. Or one of your own designs. I reused one of the projects of TI's DMA training course:  DMA move a table in memory with MSPM0 

    The CMake file takes more work. I started from TI's example for CLang. Then made changes so that it works for the GCC ARM cross-compiler. I used AI to resolve errors and gaps.

    Before the traditional C build can run, the CMake file invokes SysConfig to turn your device configuration settings into C code. That part is 100% based on TI's CMake script. The remainder is more traditional: gather sources, includes, libs. Compile and Link.

    I added the command to also create a bootloader compatible binary (for Shabaz' Python programmer).

    Here is the result:

    cmake_minimum_required(VERSION 3.29)
    
    set(CMAKE_VERBOSE_MAKEFILE ON)
    
    set(CMAKE_C_STANDARD 11)
    set(CMAKE_CXX_STANDARD 26)
    set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fmodules-ts")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcommon -fno-rtti -fno-exceptions")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections -g -gstrict-dwarf -Wall")
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    
    
    # Cross compiling for a target system that is an embedded device
    set(CMAKE_SYSTEM_NAME Generic)
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --specs=nosys.specs --specs=nano.specs -static -Wl,--gc-sections")
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -nostartfiles -mthumb")
    
    # Create the project
    project(
        mspm0_cmake
        LANGUAGES C  CXX     # Uses the programming language C
    )
    
    # Directory to the SDK used
    # SDK_ROOT set externally
    set(SDK_ROOT $ENV{SDK_ROOT})
    
    #---------------------------------------------------------------------
    # Configuration related to SysConfig
    #---------------------------------------------------------------------
    # Find the SysConfig command line interface (CLI) command in the system path
    # SYSCONFIG_CLI set externally
    set(SYSCONFIG_CLI $ENV{SYSCONFIG_CLI})
    
    # Directory to the generated SysConfig files
    set(SYSCONFIG_GENDIR ${CMAKE_BINARY_DIR}/sysconfig_generated)
    
    # SysConfig Input Script
    set(SYSCONFIG_INPUT_FILE_NAME mspm0_cmake.syscfg)
    set(SYSCONFIG_INPUT ${CMAKE_SOURCE_DIR}/${SYSCONFIG_INPUT_FILE_NAME})
    
    # SysConfig stamp file.  Described in the block comment at the end.
    set(SYSCONFIG_STAMP_FILE ${SYSCONFIG_GENDIR}/${SYSCONFIG_INPUT_FILE_NAME}.stamp)
    
    # SysConfig invocation command line
    set(SYSCONFIG_CLI_CMD
        ${SYSCONFIG_CLI}
            --script ${SYSCONFIG_INPUT}
            -o ${SYSCONFIG_GENDIR}
            --compiler gcc
            -s ${SDK_ROOT}/.metadata/product.json
    )
    
    # Ask SysConfig what files it generates.  Then categorize them.  This occurs
    # when CMake configures the project.
    execute_process(
        COMMAND ${SYSCONFIG_CLI_CMD} --listGeneratedFiles
        OUTPUT_VARIABLE SYSCONFIG_GEN_FILES_STR
    )
    string(REPLACE "\n" ";" SYSCONFIG_GEN_FILES ${SYSCONFIG_GEN_FILES_STR})
    
    set(SYSCONFIG_GEN_CFILES        ${SYSCONFIG_GEN_FILES})
    set(SYSCONFIG_GEN_HFILES        ${SYSCONFIG_GEN_FILES})
    set(SYSCONFIG_GEN_LNKCMD        ${SYSCONFIG_GEN_FILES})
    set(SYSCONFIG_GEN_COMPILER_OPTS ${SYSCONFIG_GEN_FILES})
    set(SYSCONFIG_GEN_LNKFILE       "${SYSCONFIG_GENDIR}/device_linker.lds")
    
    list(FILTER SYSCONFIG_GEN_CFILES        INCLUDE REGEX ".*\\.c$")
    list(FILTER SYSCONFIG_GEN_HFILES        INCLUDE REGEX ".*\\.h$")
    list(FILTER SYSCONFIG_GEN_LNKCMD        INCLUDE REGEX ".*\\.lds\\.")
    list(FILTER SYSCONFIG_GEN_COMPILER_OPTS INCLUDE REGEX ".*\\.opt$")
    
    # Cause CMake to run when the SysConfig input is modified, because that may
    # change the list of generated files
    set_property(
        DIRECTORY
        APPEND
        PROPERTY CMAKE_CONFIGURE_DEPENDS ${SYSCONFIG_INPUT}
    )
    
    # Run SysConfig over the input script.  Described further in a block comment
    # at the end.
    add_custom_command(
        DEPENDS    ${SYSCONFIG_INPUT}
        OUTPUT     ${SYSCONFIG_STAMP_FILE}
        BYPRODUCTS ${SYSCONFIG_GEN_FILES}
        COMMAND    ${SYSCONFIG_CLI_CMD}
        COMMAND    ${CMAKE_COMMAND} -E touch ${SYSCONFIG_STAMP_FILE}
        COMMENT    "Running SysConfig on ${SYSCONFIG_INPUT}"
        VERBATIM
    )
    add_custom_target(SysConfig_build ALL DEPENDS ${SYSCONFIG_STAMP_FILE})
    
    #---------------------------------------------------------------------
    # Configuration related to compiling
    #---------------------------------------------------------------------
    set(PROCESSOR_OPTIONS
        -march=armv6s-m
        -mcpu=cortex-m0plus
        -mfloat-abi=soft
        -mlittle-endian
        -mthumb
    )
    
    # These compiler options typically change as the project evolves.  Because
    # CMake replaces an undefined variable with an empty string, one way to
    # disable an option is to comment out that line.
    set(OPTIMIZATION_OPTION -O0)
    set(LTO_OPTION          -flto)
    set(DEBUG_OPTION        -gdwarf-3)
    
    message(STATUS "SYSCONFIG_GEN_COMPILER_OPTS: ${SYSCONFIG_GEN_COMPILER_OPTS}")
    
    # Compiler options
    add_compile_options(
        ${PROCESSOR_OPTIONS}
        ${OPTIMIZATION_OPTION}
        ${LTO_OPTION}
        ${DEBUG_OPTION}
        @${SYSCONFIG_GEN_COMPILER_OPTS}
    )
    
    message(STATUS "SYSCONFIG_GEN_CFILES: ${SYSCONFIG_GEN_CFILES}")
    
    # C files
    set(SOURCES
        ${CMAKE_SOURCE_DIR}/stub.c
        ${SYSCONFIG_GEN_CFILES}
        ${SDK_ROOT}/source/ti/devices/msp/m0p/startup_system_files/gcc/startup_mspm0l130x_gcc.c
    )
    
    # Cause C files to depend on the SysConfig generated compiler options file
    set_source_files_properties(
        ${SOURCES}
        PROPERTIES OBJECT_DEPENDS
        ${SYSCONFIG_GEN_COMPILER_OPTS}
    )
    
    message(STATUS "SYSCONFIG_GENDIR: ${SYSCONFIG_GENDIR}")
    
    # Directories searched for header files
    include_directories(
        ${SDK_ROOT}/source
        ${SDK_ROOT}/source/third_party/CMSIS/Core/Include
        ${SYSCONFIG_GENDIR}
    )
    
    #---------------------------------------------------------------------
    # Configuration related to linking
    #---------------------------------------------------------------------
    # Linker Options
    add_link_options(
        ${LTO_OPTION}            # Required when compiling AND linking
    )
    
    
    # Directories searched for libraries
    link_directories(
        ${SDK_ROOT}/source
    
    )
    
    
    message(STATUS "SYSCONFIG_GEN_LNKFILE: ${SYSCONFIG_GEN_LNKFILE}")
    message(STATUS "SYSCONFIG_GEN_LNKCMD: ${SYSCONFIG_GEN_LNKCMD}")
    
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-T${SYSCONFIG_GEN_LNKFILE}")
    # set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-T${SYSCONFIG_GEN_LNKCMD}")
    
    message(STATUS "SOURCES: ${SOURCES}")
    # Build the executable from source files in the project
    add_executable( ${PROJECT_NAME}
        ${SOURCES}
    )
    
    # target_link_directories(${PROJECT_NAME} PRIVATE 
    #     "${SDK_ROOT}/source/ti/driverlib/lib/gcc/m0p/mspm0l11xx_l13xx"
    # )
    
    # Libraries and linker command files
    target_link_libraries( ${PROJECT_NAME} PRIVATE
    #     ${SYSCONFIG_GEN_LNKFILE}
    #    ${SYSCONFIG_GEN_LNKCMD}
        ${SDK_ROOT}/source/ti/driverlib/lib/gcc/m0p/mspm0l11xx_l13xx/driverlib.a
        gcc
        c
        m
        nosys
    )
    
    get_target_property(TARGET_LIBS ${PROJECT_NAME} LINK_LIBRARIES)
    message(STATUS "Libraries linked to ${PROJECT_NAME}: ${TARGET_LIBS}")
    
    message(STATUS "SDK uses value of assignment with 'volatile'-qualified left operand ")
    target_compile_options(mspm0_cmake PRIVATE -Wno-volatile)
    message(STATUS "SDK uses bitwise operation between different enumeration types ")
    target_compile_options(mspm0_cmake PRIVATE -Wno-deprecated-enum-enum-conversion)
    
    
    
    # objcopy for bootloader compatible firmware
    set(HEX_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex)
    
    # POST_BUILD 
    message(STATUS "ObjCopy utility: ${CMAKE_OBJCOPY}")
    message(STATUS "firmware: ${PROJECT_BINARY_DIR}/${PROJECT_NAME}")
    add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
        COMMAND ${CMAKE_OBJCOPY} -O ihex  --gap-fill 0xFF ${PROJECT_BINARY_DIR}/${PROJECT_NAME} ${HEX_FILE}
    #    COMMENT "creating .hex file ..."
        VERBATIM
    )

    The TI pages that I linked to above, go in detail over each section.

    Use the VS Code CMake plugin to select the GCC compiler, and then config and build the project:

    image

    If all is well, you should get this message after config:

    [cmake] -- Configuring done (4.2s)
    [cmake] -- Generating done (0.1s)
    [cmake] -- Build files have been written to: C:/Users/jancu/workspace_vscode_mspm0/msmp0_cmake/build

    And this after build:

    [build] [4/4 100% :: 1.279] Linking C executable mspm0_cmake
    [driver] Build completed: 00:00:01.337
    [build] Build finished with exit code 0

    You can now load this firmware to your MSPM0. Either with Uniflash, or with Shabaz' Python loader.
    Or wait for the next post, where I'll build a VS Code loader script. That 'll allow you to step through your code, just like with TI's Code Composer Studio.

    Thank you for reading.

    post 1:  MSPM0 project with VS Code, CMake and GCC - part 1: infrastructure 

    • Sign in to reply
    element14 Community

    element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

    • Members
    • Learn
    • Technologies
    • Challenges & Projects
    • Products
    • Store
    • About Us
    • Feedback & Support
    • FAQs
    • Terms of Use
    • Privacy Policy
    • Legal and Copyright Notices
    • Sitemap
    • Cookies

    An Avnet Company © 2026 Premier Farnell Limited. All Rights Reserved.

    Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

    Follow element14

    • X
    • Facebook
    • linkedin
    • YouTube