In this post, I propose a CMake script for NXP MCXN326 controller. Not dependent on MCUXpresso's IDE or VS Code extension. Also independent of dev board definitions and SDK example code files.
Prerequisites: What do you need:
- working CMake and ARM GCC toolchains
- a downloaded and unzipped SDK (check if this link works - NXP account needed)
- MCUXPresso Config tools (link, NXP account needed)
- a .mex configuration file for your project. If you use shabaz' EZ-MCXN dev board, get it from his GitHub repo.
- a main file (example below)
- a CMake config file, the main focus of this post.
CMake file
I'll go start to end over the file. Check the inline comments
Initialisation
This step sets standards, and some definitions that are needed early on.
cmake_minimum_required(VERSION 3.29)
set(CMAKE_VERBOSE_MAKEFILE OF)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 26)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# SDK_ROOT set externally
set(SDK_ROOT $ENV{SDK_ROOT}) # set as a CMake Environment variable. Points to root of unzipped SDK
message(STATUS "SDK_ROOT: ${SDK_ROOT}")
set(CMAKE_SYSTEM_NAME Generic) # no OS
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --specs=nosys.specs") # prevents CMake throws toolchain error when using embedded GCC
add_compile_definitions(
MCXN236 # controller
CPU_MCXN236VKL # package
)
Fetch debug configuration, in case you want to use a hardware debugger later.
Only runs if needed. Either at first run, or if the cache is cleaned. First run needs an internet connection.
If you don't plan to use a hardware debugger, you can safely comment this section.
include(FetchContent)
set(FETCHCONTENT_QUIET FALSE CACHE BOOL "" FORCE) # show download, because it takes a while
set(FETCHCONTENT_UPDATES_DISCONNECTED ON CACHE BOOL "" FORCE) # skip if we have it in cache. Also allows for offline builds
FetchContent_Declare(svd # get MCXN236 svd definition, so registers are available during debug
GIT_REPOSITORY "https://github.com/nxp-mcuxpresso/mcux-soc-svd.git"
GIT_TAG origin/main
GIT_PROGRESS TRUE # show download, because it takes a while
# prevent makefile execution (if any)
SOURCE_SUBDIR =
)
FetchContent_MakeAvailable(svd)
file(COPY "${svd_SOURCE_DIR}/MCXN236/MCXN236.xml" # copy svd from download to build dir, where launch.json can find it
DESTINATION "${CMAKE_BINARY_DIR}"
)
Generate CMUXpresso Config source files
This is called, during Build, only when needed.
Either if the source files don't exist yet (first build, files removed), or if they are older than the .mex file.
It checks that for Pins, Clocks and Peripherals. The required jobs will run in parallel.
Because my project doesn't use the peripherals (the source files aren't added to the build target), CMake knows that it can skip the Peripherals .h and .c file generation.
# MCUXpresso Config section
set(CONFIG_TOOL_PATH $ENV{CONFIG_TOOL_PATH}) # check if MCUXpresso Config path is set
if(CONFIG_TOOL_PATH) # path set: generate sources
message(STATUS "CONFIG_TOOL_PATH: ${CONFIG_TOOL_PATH}")
set(MEX_FILE "${CMAKE_CURRENT_SOURCE_DIR}/EZ_MCXN.mex")
set(OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
message(STATUS "MCUXpresso Config Tools: source-export (Pins, Clocks, Peripherals)...")
# Check if needs to run: Pins
set(PINS_DEST_HEADER "${OUTPUT_DIR}/board/pin_mux.h")
set(PINS_DEST_SOURCE "${OUTPUT_DIR}/board/pin_mux.c")
add_custom_command(
OUTPUT "${PINS_DEST_HEADER}" "${PINS_DEST_SOURCE}"
COMMAND "${CONFIG_TOOL_PATH}"
"-noSplash"
"-consoleLog"
"-HeadlessTool" "Pins"
"-Load" "${MEX_FILE}"
"-ExportSrc" "${OUTPUT_DIR}"
RESULT_VARIABLE CONFIG_TOOL_RESULT
ERROR_VARIABLE CONFIG_TOOL_ERROR
DEPENDS "${MEX_FILE}"
COMMENT "Generating Pins files because ${MEX_FILE} changed or board files are missing"
VERBATIM
)
# Check if needs to run: Clocks
set(CLOCKS_DEST_HEADER "${OUTPUT_DIR}/board/clock_config.h")
set(CLOCKS_DEST_SOURCE "${OUTPUT_DIR}/board/clock_config.c")
add_custom_command(
OUTPUT "${CLOCKS_DEST_HEADER}" "${CLOCKS_DEST_SOURCE}"
COMMAND "${CONFIG_TOOL_PATH}"
"-noSplash"
"-consoleLog"
"-HeadlessTool" "Clocks"
"-Load" "${MEX_FILE}"
"-ExportSrc" "${OUTPUT_DIR}"
RESULT_VARIABLE CONFIG_TOOL_RESULT
ERROR_VARIABLE CONFIG_TOOL_ERROR
COMMAND ${CMAKE_COMMAND} -E rename "${OUTPUT_DIR}/cm33_core0/board/clock_config.h" "${CLOCKS_DEST_HEADER}"
COMMAND ${CMAKE_COMMAND} -E rename "${OUTPUT_DIR}/cm33_core0/board/clock_config.c" "${CLOCKS_DEST_SOURCE}"
COMMAND ${CMAKE_COMMAND} -E remove_directory "${OUTPUT_DIR}/cm33_core0/board"
COMMAND ${CMAKE_COMMAND} -E remove_directory "${OUTPUT_DIR}/cm33_core0"
DEPENDS "${MEX_FILE}"
COMMENT "Generating Clocks files because ${MEX_FILE} changed or board files are missing"
VERBATIM
)
# Check if needs to run: Peripherals
set(PERIPHERALS_DEST_FILE_1 "${OUTPUT_DIR}/board/peripherals.h")
set(PERIPHERALS_DEST_FILE_2 "${OUTPUT_DIR}/board/peripherals.c")
add_custom_command(
OUTPUT "${PERIPHERALS_DEST_FILE_1}" "${PERIPHERALS_DEST_FILE_2}"
COMMAND "${CONFIG_TOOL_PATH}"
"-noSplash"
"-consoleLog"
"-HeadlessTool" "Peripherals"
"-Load" "${MEX_FILE}"
"-ExportSrc" "${OUTPUT_DIR}"
RESULT_VARIABLE CONFIG_TOOL_RESULT
ERROR_VARIABLE CONFIG_TOOL_ERROR
DEPENDS "${MEX_FILE}"
COMMENT "Generating Peripherals files because ${MEX_FILE} changed or board files are missing"
VERBATIM
)
else() # path not set: developer should generate sources with GUI
message(STATUS "CONFIG_TOOL_PATH not set. Skipping source generation.")
endif()
Project declaration and includes
project(ez_mcxn_minimal LANGUAGES C CXX ASM)
include_directories(
${SDK_ROOT}/mcxn236/mcuxsdk/arch/arm/CMSIS/Core/Include
${SDK_ROOT}/mcxn236/mcuxsdk/arch/arm/CMSIS/Core/Include/m-profile
${SDK_ROOT}/mcxn236/mcuxsdk/devices/MCX/MCXN/MCXN236
${SDK_ROOT}/mcxn236/mcuxsdk/devices/MCX/MCXN/MCXN236/drivers
${SDK_ROOT}/mcxn236/mcuxsdk/devices/MCX/MCXN/periph1 # MCXN326 files are in periph1 (see config file in parent dir)
${SDK_ROOT}/mcxn236/mcuxsdk/drivers/common
${SDK_ROOT}/mcxn236/mcuxsdk/drivers/mcx_spc # system power controller
${SDK_ROOT}/mcxn236/mcuxsdk/drivers/port
${SDK_ROOT}/mcxn236/mcuxsdk/drivers/gpio
# project includes
${CMAKE_SOURCE_DIR}/board
)
Firmware
add_executable( ${CMAKE_PROJECT_NAME})
set(MCXN_FLAGS # flags common to compiler and linker
-mcpu=cortex-m33
-mthumb
-mfloat-abi=hard
-mfpu=fpv5-sp-d16
--specs=nano.specs
)
target_sources(${CMAKE_PROJECT_NAME} # default source files
PRIVATE
${SDK_ROOT}/mcxn236/mcuxsdk/devices/MCX/MCXN/MCXN236/gcc/startup_MCXN236.S
${SDK_ROOT}/mcxn236/mcuxsdk/devices/MCX/MCXN/MCXN236/system_MCXN236.c
${SDK_ROOT}/mcxn236/mcuxsdk/devices/MCX/MCXN/MCXN236/drivers/fsl_clock.c
${SDK_ROOT}/mcxn236/mcuxsdk/devices/MCX/MCXN/MCXN236/drivers/fsl_reset.c
${SDK_ROOT}/mcxn236/mcuxsdk/components/misc_utilities/fsl_syscall_stub.c # implements stubs for functions not implemented in nano
${SDK_ROOT}/mcxn236/mcuxsdk/components/misc_utilities/fsl_sbrk.c # alternative for gcc implementation
${SDK_ROOT}/mcxn236/mcuxsdk/components/misc_utilities/fsl_memcpy.S # alternative for gcc implementation
${SDK_ROOT}/mcxn236/mcuxsdk/components/misc_utilities/fsl_memset.S # alternative for gcc implementation
${SDK_ROOT}/mcxn236/mcuxsdk/drivers/common/fsl_common.c
${SDK_ROOT}/mcxn236/mcuxsdk/drivers/mcx_spc/fsl_spc.c # system power controller
)
target_sources(${CMAKE_PROJECT_NAME} # project source files (c, asm, cpp), except cpp modules
PRIVATE
${SDK_ROOT}/mcxn236/mcuxsdk/drivers/gpio/fsl_gpio.c
# project sources
# MCUXpresso Cfg generated:
${CLOCKS_DEST_SOURCE}
${PINS_DEST_SOURCE}
# application sources
${CMAKE_SOURCE_DIR}/main.c
)
target_sources(${CMAKE_PROJECT_NAME} # cpp modules
PRIVATE
FILE_SET cxx_modules TYPE CXX_MODULES FILES
)
target_compile_options(${CMAKE_PROJECT_NAME} PRIVATE
$<$<COMPILE_LANGUAGE:CXX>:-fno-use-cxa-atexit> # cpp flag
$<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions> # cpp flag
$<$<COMPILE_LANGUAGE:CXX>:-fno-rtti> # cpp flag
$<$<COMPILE_LANGUAGE:CXX>:-fcommon> # cpp flag
$<$<COMPILE_LANGUAGE:CXX>:-fmodules-ts> # cpp flag: support modules
${MCXN_FLAGS} # flags shared with linker
-Wall
-ffunction-sections
-fdata-sections
)
target_link_options(${CMAKE_PROJECT_NAME} PRIVATE
${MCXN_FLAGS} # flags shared with compiler
--specs=nano.specs # small c library
-Wl,--gc-sections
-Wl,--no-warn-rwx-segments
-T ${SDK_ROOT}/mcxn236/mcuxsdk/devices/MCX/MCXN/MCXN236/gcc/MCXN236_flash.ld # linker command file
)
Optional mcux-fix-elf
# MCUXpresso FIXELF section
# Not really needed for a single core MCXN236, but included for completeness
set(MCUX_FIXELF_EXE $ENV{MCUX_FIXELF_EXE}) # check if MCUXpresso FIXELF path is set
message(STATUS "mcux-fixelf set as: ${MCUX_FIXELF_EXE}")
if(NOT MCUX_FIXELF_EXE)
find_program(MCUX_FIXELF_EXE mcux-fixelf)
if(NOT MCUX_FIXELF_EXE)
message(STATUS "Can't locate mcux-fixelf.exe in environment or on path. Skipping post-build fixelf step.")
endif()
else()
message(STATUS "using mcux-fixelf: ${MCUX_FIXELF_EXE}")
endif()
if(MCUX_FIXELF_EXE)
message(STATUS "start mcux-fixelf")
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
COMMAND ${MCUX_FIXELF_EXE}
$<TARGET_FILE:${CMAKE_PROJECT_NAME}> # .elf file to fix
COMMENT "Executing mcux-fixelf post-build steps voor NXP MCU..."
VERBATIM
)
endif()
Flashable binary
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD # create extra output: flashable binary
COMMAND ${CMAKE_OBJCOPY}
-O binary
$<TARGET_FILE:${CMAKE_PROJECT_NAME}> ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.bin
COMMENT "create bin executable: ${CMAKE_PROJECT_NAME}.bin"
)
Full CMakeLists.txt source:
cmake_minimum_required(VERSION 3.29)
set(CMAKE_VERBOSE_MAKEFILE OF)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 26)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# SDK_ROOT set externally
set(SDK_ROOT $ENV{SDK_ROOT}) # set as a CMake Environment variable. Points to root of unzipped SDK
message(STATUS "SDK_ROOT: ${SDK_ROOT}")
set(CMAKE_SYSTEM_NAME Generic) # no OS
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --specs=nosys.specs") # prevents CMake throws toolchain error when using embedded GCC
add_compile_definitions(
MCXN236 # controller
CPU_MCXN236VKL # package
)
include(FetchContent)
set(FETCHCONTENT_QUIET FALSE CACHE BOOL "" FORCE) # show download, because it takes a while
set(FETCHCONTENT_UPDATES_DISCONNECTED ON CACHE BOOL "" FORCE) # skip if we have it in cache. Also allows for offline builds
FetchContent_Declare(svd # get MCXN236 svd definition, so registers are available during debug
GIT_REPOSITORY "https://github.com/nxp-mcuxpresso/mcux-soc-svd.git"
GIT_TAG origin/main
GIT_PROGRESS TRUE # show download, because it takes a while
# prevent makefile execution (if any)
SOURCE_SUBDIR =
)
FetchContent_MakeAvailable(svd)
file(COPY "${svd_SOURCE_DIR}/MCXN236/MCXN236.xml" # copy svd from download to build dir, where launch.json can find it
DESTINATION "${CMAKE_BINARY_DIR}"
)
# MCUXpresso Config section
set(CONFIG_TOOL_PATH $ENV{CONFIG_TOOL_PATH}) # check if MCUXpresso Config path is set
if(CONFIG_TOOL_PATH) # path set: generate sources
message(STATUS "CONFIG_TOOL_PATH: ${CONFIG_TOOL_PATH}")
set(MEX_FILE "${CMAKE_CURRENT_SOURCE_DIR}/EZ_MCXN.mex")
set(OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
# Check if needs to run: Pins
set(PINS_DEST_HEADER "${OUTPUT_DIR}/board/pin_mux.h")
set(PINS_DEST_SOURCE "${OUTPUT_DIR}/board/pin_mux.c")
add_custom_command(
OUTPUT "${PINS_DEST_HEADER}" "${PINS_DEST_SOURCE}"
COMMAND "${CONFIG_TOOL_PATH}"
"-noSplash"
"-consoleLog"
"-HeadlessTool" "Pins"
"-Load" "${MEX_FILE}"
"-ExportSrc" "${OUTPUT_DIR}"
RESULT_VARIABLE CONFIG_TOOL_RESULT
ERROR_VARIABLE CONFIG_TOOL_ERROR
DEPENDS "${MEX_FILE}"
COMMENT "Generating Pins files because ${MEX_FILE} changed or board files are missing"
VERBATIM
)
# Check if needs to run: Clocks
set(CLOCKS_DEST_HEADER "${OUTPUT_DIR}/board/clock_config.h")
set(CLOCKS_DEST_SOURCE "${OUTPUT_DIR}/board/clock_config.c")
add_custom_command(
OUTPUT "${CLOCKS_DEST_HEADER}" "${CLOCKS_DEST_SOURCE}"
COMMAND "${CONFIG_TOOL_PATH}"
"-noSplash"
"-consoleLog"
"-HeadlessTool" "Clocks"
"-Load" "${MEX_FILE}"
"-ExportSrc" "${OUTPUT_DIR}"
RESULT_VARIABLE CONFIG_TOOL_RESULT
ERROR_VARIABLE CONFIG_TOOL_ERROR
COMMAND ${CMAKE_COMMAND} -E rename "${OUTPUT_DIR}/cm33_core0/board/clock_config.h" "${CLOCKS_DEST_HEADER}"
COMMAND ${CMAKE_COMMAND} -E rename "${OUTPUT_DIR}/cm33_core0/board/clock_config.c" "${CLOCKS_DEST_SOURCE}"
COMMAND ${CMAKE_COMMAND} -E remove_directory "${OUTPUT_DIR}/cm33_core0/board"
COMMAND ${CMAKE_COMMAND} -E remove_directory "${OUTPUT_DIR}/cm33_core0"
DEPENDS "${MEX_FILE}"
COMMENT "Generating Clocks files because ${MEX_FILE} changed or board files are missing"
VERBATIM
)
# Check if needs to run: Peripherals
set(PERIPHERALS_DEST_FILE_1 "${OUTPUT_DIR}/board/peripherals.h")
set(PERIPHERALS_DEST_FILE_2 "${OUTPUT_DIR}/board/peripherals.c")
add_custom_command(
OUTPUT "${PERIPHERALS_DEST_FILE_1}" "${PERIPHERALS_DEST_FILE_2}"
COMMAND "${CONFIG_TOOL_PATH}"
"-noSplash"
"-consoleLog"
"-HeadlessTool" "Peripherals"
"-Load" "${MEX_FILE}"
"-ExportSrc" "${OUTPUT_DIR}"
RESULT_VARIABLE CONFIG_TOOL_RESULT
ERROR_VARIABLE CONFIG_TOOL_ERROR
DEPENDS "${MEX_FILE}"
COMMENT "Generating Peripherals files because ${MEX_FILE} changed or board files are missing"
VERBATIM
)
else() # path not set: developer should generate sources with GUI
message(STATUS "CONFIG_TOOL_PATH not set. Skipping source generation.")
endif()
project(ez_mcxn_minimal LANGUAGES C CXX ASM)
include_directories(
${SDK_ROOT}/mcxn236/mcuxsdk/arch/arm/CMSIS/Core/Include
${SDK_ROOT}/mcxn236/mcuxsdk/arch/arm/CMSIS/Core/Include/m-profile
${SDK_ROOT}/mcxn236/mcuxsdk/devices/MCX/MCXN/MCXN236
${SDK_ROOT}/mcxn236/mcuxsdk/devices/MCX/MCXN/MCXN236/drivers
${SDK_ROOT}/mcxn236/mcuxsdk/devices/MCX/MCXN/periph1 # MCXN326 files are in periph1 (see config file in parent dir)
${SDK_ROOT}/mcxn236/mcuxsdk/drivers/common
${SDK_ROOT}/mcxn236/mcuxsdk/drivers/mcx_spc # system power controller
${SDK_ROOT}/mcxn236/mcuxsdk/drivers/port
${SDK_ROOT}/mcxn236/mcuxsdk/drivers/gpio
# project includes
${CMAKE_SOURCE_DIR}/board
)
add_executable( ${CMAKE_PROJECT_NAME})
set(MCXN_FLAGS # flags common to compiler and linker
-mcpu=cortex-m33
-mthumb
-mfloat-abi=hard
-mfpu=fpv5-sp-d16
--specs=nano.specs
)
target_sources(${CMAKE_PROJECT_NAME} # default source files
PRIVATE
${SDK_ROOT}/mcxn236/mcuxsdk/devices/MCX/MCXN/MCXN236/gcc/startup_MCXN236.S
${SDK_ROOT}/mcxn236/mcuxsdk/devices/MCX/MCXN/MCXN236/system_MCXN236.c
${SDK_ROOT}/mcxn236/mcuxsdk/devices/MCX/MCXN/MCXN236/drivers/fsl_clock.c
${SDK_ROOT}/mcxn236/mcuxsdk/devices/MCX/MCXN/MCXN236/drivers/fsl_reset.c
${SDK_ROOT}/mcxn236/mcuxsdk/components/misc_utilities/fsl_syscall_stub.c # implements stubs for functions not implemented in nano
${SDK_ROOT}/mcxn236/mcuxsdk/components/misc_utilities/fsl_sbrk.c # alternative for gcc implementation
${SDK_ROOT}/mcxn236/mcuxsdk/components/misc_utilities/fsl_memcpy.S # alternative for gcc implementation
${SDK_ROOT}/mcxn236/mcuxsdk/components/misc_utilities/fsl_memset.S # alternative for gcc implementation
${SDK_ROOT}/mcxn236/mcuxsdk/drivers/common/fsl_common.c
${SDK_ROOT}/mcxn236/mcuxsdk/drivers/mcx_spc/fsl_spc.c # system power controller
)
target_sources(${CMAKE_PROJECT_NAME} # project source files (c, asm, cpp), except cpp modules
PRIVATE
${SDK_ROOT}/mcxn236/mcuxsdk/drivers/gpio/fsl_gpio.c
# project sources
# MCUXpresso Cfg generated:
${CLOCKS_DEST_SOURCE}
${PINS_DEST_SOURCE}
# ${PERIPHERALS_DEST_SOURCE} # this minimal project doesn't use the Peripherals
# application sources
${CMAKE_SOURCE_DIR}/main.c
)
target_sources(${CMAKE_PROJECT_NAME} # cpp modules
PRIVATE
FILE_SET cxx_modules TYPE CXX_MODULES FILES
)
target_compile_options(${CMAKE_PROJECT_NAME} PRIVATE
$<$<COMPILE_LANGUAGE:CXX>:-fno-use-cxa-atexit> # cpp flag
$<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions> # cpp flag
$<$<COMPILE_LANGUAGE:CXX>:-fno-rtti> # cpp flag
$<$<COMPILE_LANGUAGE:CXX>:-fcommon> # cpp flag
$<$<COMPILE_LANGUAGE:CXX>:-fmodules-ts> # cpp flag: support modules
${MCXN_FLAGS} # flags shared with linker
-Wall
-ffunction-sections
-fdata-sections
)
target_link_options(${CMAKE_PROJECT_NAME} PRIVATE
${MCXN_FLAGS} # flags shared with compiler
--specs=nano.specs # small c library
-Wl,--gc-sections
-Wl,--no-warn-rwx-segments
-T ${SDK_ROOT}/mcxn236/mcuxsdk/devices/MCX/MCXN/MCXN236/gcc/MCXN236_flash.ld # linker command file
)
# MCUXpresso FIXELF section
# Not really needed for a single core MCXN236, but included for completeness
set(MCUX_FIXELF_EXE $ENV{MCUX_FIXELF_EXE}) # check if MCUXpresso FIXELF path is set
message(STATUS "mcux-fixelf set as: ${MCUX_FIXELF_EXE}")
if(NOT MCUX_FIXELF_EXE)
find_program(MCUX_FIXELF_EXE mcux-fixelf)
if(NOT MCUX_FIXELF_EXE)
message(STATUS "Can't locate mcux-fixelf.exe in environment or on path. Skipping post-build fixelf step.")
endif()
else()
message(STATUS "using mcux-fixelf: ${MCUX_FIXELF_EXE}")
endif()
if(MCUX_FIXELF_EXE)
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
COMMAND ${MCUX_FIXELF_EXE}
$<TARGET_FILE:${CMAKE_PROJECT_NAME}> # .elf file to fix
COMMENT "Executing mcux-fixelf post-build steps voor NXP MCU..."
VERBATIM
)
endif()
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD # create extra output: flashable binary
COMMAND ${CMAKE_OBJCOPY}
-O binary
$<TARGET_FILE:${CMAKE_PROJECT_NAME}> $<TARGET_FILE:${CMAKE_PROJECT_NAME}>.bin
COMMENT "create bin executable: $<TARGET_FILE:${CMAKE_PROJECT_NAME}>.bin"
)
Example main source
main.c:
#include "fsl_common.h"
// #include "fsl_device_registers.h"
#include "pin_mux.h"
#include "clock_config.h"
int main(void)
{
BOARD_InitPins();
BOARD_BootClockRUN();
while (1) {
for (uint32_t i = 0; i < 1000000U; i++) {
__NOP();
}
}
}
Project setup
- create a folder
- put the CMakeLists.txt, main.c and EZ_MCXN.mex in that folder
- If you define an environment variable CONFIG_TOOL_PATH that points to the CMUXpresso Config executable, do nothing,
else: open the .mex file with CMUXpresso Config, and click Update Code.
Calling CMake
Do this as you 'd do for other projects.
Pass the SDK_ROOT and ARM toolchain. Optionally CONFIG_TOOL_PATH.
Here is a DOS command prompt example:
set SDK_ROOT=C:/Users/jancu/Documents/elektronica/nxp/sdk/mcxn236_noboard
set CONFIG_TOOL_PATH=C:/NXP/MCUX_CFG_26.09/bin/tools.exe
mkdir build cd build cmake .. -G "Ninja" -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_C_COMPILER:FILEPATH=c:\\Users\\jancu\\Documents\\toolchains\\arm-gnu-toolchain-15.2.rel1-mingw-w64-i686-arm-none-eabi\\bin\\arm-none-eabi-gcc.exe -DCMAKE_CXX_COMPILER:FILEPATH=c:\\Users\\jancu\\Documents\\toolchains\\arm-gnu-toolchain-15.2.rel1-mingw-w64-i686-arm-none-eabi\\bin\\arm-none-eabi-g++.exe -DCMAKE_BUILD_TYPE=Debug cmake --build . cd ..
First time CMake configuration takes a while, because the script fetches debug scripts from NXP's GitHub repositories.
First time CMake build also takes a bit, if the sources have to be generated from the .mex file.
After that, these two steps are only executed if the generated files are outdated, and will finish in seconds.
See the Timing section near the bottom of the post.
C:\Users\jancu\workspace_vscode_nxp\ez-mcxn_hello_world\ez_mcxn_minimal\build>cmake .. -G "Ninja" -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_C_COMPILER:FILEPATH=c:\\Users\\jancu\\Documents\\toolchains\\arm-gnu-toolchain-15.2.rel1-mingw-w64-i686-arm-none-eabi\\bin\\arm-none-eabi-gcc.exe -DCMAKE_CXX_COMPILER:FILEPATH=c:\\Users\\jancu\\Documents\\toolchains\\arm-gnu-toolchain-15.2.rel1-mingw-w64-i686-arm-none-eabi\\bin\\arm-none-eabi-g++.exe -DCMAKE_BUILD_TYPE=Debug-- SDK_ROOT: C:/Users/jancu/Documents/elektronica/nxp/sdk/mcxn236_noboard-- The C compiler identification is GNU 15.2.1-- The CXX compiler identification is GNU 15.2.1-- The ASM compiler identification is GNU-- Found assembler: C:/Users/jancu/Documents/toolchains/arm-gnu-toolchain-15.2.rel1-mingw-w64-i686-arm-none-eabi/bin/arm-none-eabi-gcc.exe-- Detecting C compiler ABI info-- Detecting C compiler ABI info - done-- Check for working C compiler: c:/Users/jancu/Documents/toolchains/arm-gnu-toolchain-15.2.rel1-mingw-w64-i686-arm-none-eabi/bin/arm-none-eabi-gcc.exe - skipped-- Detecting C compile features-- Detecting C compile features - done-- Detecting CXX compiler ABI info-- Detecting CXX compiler ABI info - done-- Check for working CXX compiler: c:/Users/jancu/Documents/toolchains/arm-gnu-toolchain-15.2.rel1-mingw-w64-i686-arm-none-eabi/bin/arm-none-eabi-g++.exe - skipped-- Detecting CXX compile features-- Detecting CXX compile features - done-- Configuring done (66.2s)-- Generating done (0.1s)-- Build files have been written to: C:/Users/jancu/workspace_vscode_nxp/ez-mcxn_hello_world/ez_mcxn_minimal/build
C:\Users\jancu\workspace_vscode_nxp\ez-mcxn_hello_world\ez_mcxn_minimal\build>cmake --build .[15/15] Linking C executable ez_mcxn_minimal
When you use VS Code's CMake extension:
- you can select the toolchain there, and it 'll be passed automatically.
- The SDK_ROOT and CONFIG_TOOL_PATH, you can configure in Extensions - CMake - CMake:Environment
- press Configure
- press build
Timings
- config: < 2.5s
- build: seconds**
- first config (or when cache cleared): 66s*.
- first build (or when build cleared, or .mex file altered): 20s**
* If you don't plan to use a hardware debugger, you can comment the svd section, and also a new config is below 10s
** first build includes generating the source files with CMUXpresso Config. If you do this step by hand, during your design, it takes virtually all time off. A rebuild after you changed / added some sources takes a few seconds.
All times recorded on
- Windows 11 Laptop, 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz (2.30 GHz), 16.0 GB RAM.
- Fast internet, but WiFi connected.
- BD711 solid state drive
In the next post, I'll try to get Debug working in VS Code. Also without the MCXpresso extension.
Thank you for reading
Project attached: ez_mcxn_minimal.zip
-
Jan Cumps
-
Cancel
-
Vote Up
0
Vote Down
-
-
Sign in to reply
-
More
-
Cancel
-
Jan Cumps
in reply to Jan Cumps
-
Cancel
-
Vote Up
0
Vote Down
-
-
Sign in to reply
-
More
-
Cancel
Comment-
Jan Cumps
in reply to Jan Cumps
-
Cancel
-
Vote Up
0
Vote Down
-
-
Sign in to reply
-
More
-
Cancel
Children