From 7f20054fc436ba65715d2d72864254bc9d41915a Mon Sep 17 00:00:00 2001 From: Ali Eissa Date: Wed, 9 Sep 2026 15:12:59 +0400 Subject: [PATCH 01/13] Project Skeleton & Toolchain Setup --- NXP/MIMXRT1064-EVK/.gitignore | 10 ++ NXP/MIMXRT1064-EVK/CMakeLists.txt | 84 +++++++++ NXP/MIMXRT1064-EVK/NOTICE.md | 61 +++++++ NXP/MIMXRT1064-EVK/README.md | 88 +++++++++ .../cmake/arm-gcc-cortex-m7.cmake | 20 +++ .../cmake/arm-gcc-cortex-toolchain.cmake | 77 ++++++++ NXP/MIMXRT1064-EVK/cmake/utilities.cmake | 50 ++++++ NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h | 26 +++ NXP/MIMXRT1064-EVK/scripts/build.ps1 | 84 +++++++++ NXP/MIMXRT1064-EVK/scripts/build.sh | 77 ++++++++ NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 | 169 ++++++++++++++++++ NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh | 128 +++++++++++++ 12 files changed, 874 insertions(+) create mode 100644 NXP/MIMXRT1064-EVK/.gitignore create mode 100644 NXP/MIMXRT1064-EVK/CMakeLists.txt create mode 100644 NXP/MIMXRT1064-EVK/NOTICE.md create mode 100644 NXP/MIMXRT1064-EVK/README.md create mode 100644 NXP/MIMXRT1064-EVK/cmake/arm-gcc-cortex-m7.cmake create mode 100644 NXP/MIMXRT1064-EVK/cmake/arm-gcc-cortex-toolchain.cmake create mode 100644 NXP/MIMXRT1064-EVK/cmake/utilities.cmake create mode 100644 NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h create mode 100644 NXP/MIMXRT1064-EVK/scripts/build.ps1 create mode 100644 NXP/MIMXRT1064-EVK/scripts/build.sh create mode 100644 NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 create mode 100644 NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh diff --git a/NXP/MIMXRT1064-EVK/.gitignore b/NXP/MIMXRT1064-EVK/.gitignore new file mode 100644 index 00000000..c44f7285 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/.gitignore @@ -0,0 +1,10 @@ +# Build artifacts +build/ +*.elf +*.bin +*.hex +*.map + +# Downloaded SDK dependencies +lib/mcux-sdk/ +temp_fetch/ diff --git a/NXP/MIMXRT1064-EVK/CMakeLists.txt b/NXP/MIMXRT1064-EVK/CMakeLists.txt new file mode 100644 index 00000000..66d6593d --- /dev/null +++ b/NXP/MIMXRT1064-EVK/CMakeLists.txt @@ -0,0 +1,84 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. + +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) +set(CMAKE_C_STANDARD 99) + +# Set the toolchain if not defined +if(NOT CMAKE_TOOLCHAIN_FILE) + set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_LIST_DIR}/cmake/arm-gcc-cortex-m7.cmake") +endif() + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) + +include(utilities) + +# Define the Project +project(mimxrt1064_threadx C CXX ASM) + +# Define ThreadX User Configurations +set(TX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/lib/threadx/tx_user.h" CACHE STRING "Enable TX user configuration") +set(TX_USER_FILE_DIR "${CMAKE_CURRENT_LIST_DIR}/lib/threadx") + +# Set up paths for MCUXpresso SDK +set(SDK_DIR "${CMAKE_CURRENT_LIST_DIR}/lib/mcux-sdk") +if(NOT EXISTS "${SDK_DIR}/devices/MIMXRT1064/MIMXRT1064.h") + message(FATAL_ERROR "NXP SDK dependencies missing! Please run 'scripts/fetch_sdk.ps1' or 'scripts/fetch_sdk.sh' first.") +endif() + +# Compile the NXP MCUXpresso Driver & Board Library as an Object Library +set(SDK_TARGET mcux_sdk) + +add_library(${SDK_TARGET} OBJECT + ${SDK_DIR}/devices/MIMXRT1064/system_MIMXRT1064.c + ${SDK_DIR}/devices/MIMXRT1064/fsl_flexspi_nor_boot.c + ${SDK_DIR}/drivers/fsl_clock.c + ${SDK_DIR}/drivers/fsl_common.c + ${SDK_DIR}/drivers/fsl_common_arm.c + ${SDK_DIR}/drivers/fsl_gpio.c + ${SDK_DIR}/drivers/fsl_lpuart.c + ${SDK_DIR}/board/board.c + ${SDK_DIR}/board/clock_config.c + ${SDK_DIR}/board/pin_mux.c + ${SDK_DIR}/board/dcd.c + ${SDK_DIR}/board/evkmimxrt1064_flexspi_nor_config.c + ${SDK_DIR}/utilities/fsl_debug_console.c + ${SDK_DIR}/utilities/fsl_str.c + ${SDK_DIR}/utilities/fsl_assert.c + ${SDK_DIR}/components/uart/fsl_adapter_lpuart.c +) + +target_compile_definitions(${SDK_TARGET} + PUBLIC + CPU_MIMXRT1064DVL6A + XIP_EXTERNAL_FLASH=1 + XIP_BOOT_HEADER_ENABLE=1 + XIP_BOOT_HEADER_DCD_ENABLE=1 + FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE=1 + SDK_DEBUGCONSOLE=1 + SKIP_SYSCLK_INIT=1 +) + +target_include_directories(${SDK_TARGET} + PUBLIC + ${SDK_DIR}/CMSIS/Include + ${SDK_DIR}/devices/MIMXRT1064 + ${SDK_DIR}/drivers + ${SDK_DIR}/board + ${SDK_DIR}/utilities + ${SDK_DIR}/components/uart + ${CMAKE_CURRENT_LIST_DIR}/app + ${TX_USER_FILE_DIR} +) + +# Compile ThreadX Kernel from root shared libs submodule +set(THREADX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../libs/threadx") +add_subdirectory(${THREADX_DIR} threadx) diff --git a/NXP/MIMXRT1064-EVK/NOTICE.md b/NXP/MIMXRT1064-EVK/NOTICE.md new file mode 100644 index 00000000..854858e9 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/NOTICE.md @@ -0,0 +1,61 @@ +# Third-Party Software Notices + +This directory contains build automation scripts and configurations that download and compile third-party software components. This notice lists the licenses and copyrights applicable to those components. + +--- + +## 1. NXP MCUXpresso SDK Drivers & Device Support +* **Source**: https://github.com/nxp-mcuxpresso/mcuxsdk-core / https://mcuxpresso.nxp.com/ +* **License**: BSD 3-Clause + +```text +Copyright 2016-2026 NXP +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +``` + +--- + +## 2. ARM CMSIS Core +* **Source**: https://github.com/ARM-software/CMSIS_5 / https://github.com/STMicroelectronics/cmsis-core +* **License**: Apache License 2.0 + +```text +Copyright (c) 2009-2025 Arm Limited. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/NXP/MIMXRT1064-EVK/README.md b/NXP/MIMXRT1064-EVK/README.md new file mode 100644 index 00000000..c972249e --- /dev/null +++ b/NXP/MIMXRT1064-EVK/README.md @@ -0,0 +1,88 @@ +# NXP i.MX RT1064-EVK Board Support Package & Demos + +This directory contains the Board Support Package (BSP) and build environment for running the **Eclipse ThreadX RTOS** and **NetX Duo** on the **NXP i.MX RT1064-EVK** evaluation board (ARM Cortex-M7 @ 600 MHz). + +The project is designed to run seamlessly both in the **Antmicro Renode** simulation framework and on physical silicon. + +--- + +## Hardware Configuration + +* **Development Board**: MIMXRT1064-EVK +* **Microcontroller**: NXP i.MX RT1064 (MIMXRT1064DVL6A, ARM Cortex-M7 @ 600 MHz) +* **Flash Memory**: 4 MB internal FlexSPI NOR Flash (XIP) +* **Internal SRAM**: 1 MB on-chip RAM (Configurable as ITCM, DTCM, and OCRAM) +* **Debug Serial Console**: LPUART1 (115,200 baud, 8N1) +* **User LED**: GPIO9 Pin 3 (`GPIO_AD_B0_09`) / User LED (Green) +* **Virtual Networking**: ENET1 (10/100M Fast Ethernet MAC via KSZ8081 PHY) + +--- + +## Project Structure + +```text +NXP/MIMXRT1064-EVK/ +├── CMakeLists.txt # Top-level CMake build configuration +├── NOTICE.md # Third-party licensing notices (NXP BSD-3 & CMSIS) +├── README.md # This documentation file +├── cmake/ +│ ├── arm-gcc-cortex-m7.cmake # CPU architecture and FPU definitions +│ ├── arm-gcc-cortex-toolchain.cmake # GNU toolchain discovery and compiler flags +│ └── utilities.cmake # Elf-to-bin/hex conversion and linker macros +├── lib/ +│ ├── threadx/ +│ │ └── tx_user.h # ThreadX configuration (hardware FPU enabled) +│ └── mcux-sdk/ # Official NXP SDK drivers (fetched via script) +└── scripts/ + ├── fetch_sdk.ps1 / .sh # Download official NXP drivers, device headers & CMSIS + └── build.ps1 / .sh # One-command build script with Ninja/CMake +``` + +--- + +## Prerequisites + +Before building, ensure the following cross-compilation tools are installed and present on your `PATH`: + +* **ARM GNU Toolchain** (`arm-none-eabi-gcc` 10.3 or newer) +* **CMake** (version 3.5 or newer) +* **Ninja** (or **Make**) +* **Git** (for downloading SDK dependencies) +* **Antmicro Renode** (v1.15 or newer, for simulation) + +--- + +## Quick Start Guide + +### 1. Download SDK Dependencies +Run the driver fetcher script to retrieve official NXP MCUXpresso SDK drivers, CMSIS device headers, and board files: + +* **On Windows (PowerShell)**: + ```powershell + powershell -ExecutionPolicy Bypass -File .\scripts\fetch_sdk.ps1 + ``` +* **On Linux / macOS (Bash)**: + ```bash + chmod +x ./scripts/fetch_sdk.sh + ./scripts/fetch_sdk.sh + ``` + +### 2. Build the Project +Compile the application, vendor drivers, and Eclipse ThreadX kernel: + +* **On Windows (PowerShell)**: + ```powershell + powershell -ExecutionPolicy Bypass -File .\scripts\build.ps1 -Rebuild + ``` +* **On Linux / macOS (Bash)**: + ```bash + chmod +x ./scripts/build.sh + ./scripts/build.sh --rebuild + ``` + +--- + +## Hardware Verification Status + +> [!NOTE] +> This Board Support Package is developed and validated using **Antmicro Renode simulation**. Physical hardware verification on the EVK-MIMXRT1064 evaluation board is welcome and encouraged! diff --git a/NXP/MIMXRT1064-EVK/cmake/arm-gcc-cortex-m7.cmake b/NXP/MIMXRT1064-EVK/cmake/arm-gcc-cortex-m7.cmake new file mode 100644 index 00000000..c22c25b3 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/cmake/arm-gcc-cortex-m7.cmake @@ -0,0 +1,20 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. + +# Define the CPU architecture for ThreadX +set(THREADX_ARCH "cortex_m7") +set(THREADX_TOOLCHAIN "gnu") + +# Cortex-M7 compiler options for NXP i.MX RT1064 +set(MCPU_FLAGS "-mthumb -mcpu=cortex-m7") +set(VFP_FLAGS "-mfloat-abi=hard -mfpu=fpv5-d16") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-gcc-cortex-toolchain.cmake) diff --git a/NXP/MIMXRT1064-EVK/cmake/arm-gcc-cortex-toolchain.cmake b/NXP/MIMXRT1064-EVK/cmake/arm-gcc-cortex-toolchain.cmake new file mode 100644 index 00000000..0fe01f90 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/cmake/arm-gcc-cortex-toolchain.cmake @@ -0,0 +1,77 @@ +# Copyright (c) Microsoft +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Microsoft - Initial version +# Frédéric Desbiens - 2024 version. +# Ali Eissa - 2026 version. + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR arm) +set(TARGET_TRIPLET "arm-none-eabi-") + +# Default to Debug build +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build, options are: Debug Release." FORCE) +endif() + +# Windows executable suffix handling +if(WIN32) + set(TOOLCHAIN_EXT ".exe") +else() + set(TOOLCHAIN_EXT "") +endif() + +find_program(COMPILER_ON_PATH "${TARGET_TRIPLET}gcc${TOOLCHAIN_EXT}") + +if(DEFINED ENV{ARM_GCC_PATH}) + file(TO_CMAKE_PATH $ENV{ARM_GCC_PATH} ARM_TOOLCHAIN_PATH) + message(STATUS "Using ENV variable ARM_GCC_PATH = ${ARM_TOOLCHAIN_PATH}") +elseif(COMPILER_ON_PATH) + get_filename_component(ARM_TOOLCHAIN_PATH ${COMPILER_ON_PATH} DIRECTORY) + message(STATUS "Using ARM GCC from PATH = ${ARM_TOOLCHAIN_PATH}") +else() + message(FATAL_ERROR "Unable to find ARM GCC (${TARGET_TRIPLET}gcc). Either add it to your PATH, or define ARM_GCC_PATH to the compiler directory.") +endif() + +# Perform compiler test with a static library +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +set(CMAKE_C_COMPILER ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}gcc${TOOLCHAIN_EXT}) +set(CMAKE_CXX_COMPILER ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}g++${TOOLCHAIN_EXT}) +set(CMAKE_ASM_COMPILER ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}gcc${TOOLCHAIN_EXT}) +set(CMAKE_LINKER ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}gcc${TOOLCHAIN_EXT}) +set(CMAKE_SIZE_UTIL ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}size${TOOLCHAIN_EXT}) +set(CMAKE_OBJCOPY ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}objcopy${TOOLCHAIN_EXT}) +set(CMAKE_OBJDUMP ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}objdump${TOOLCHAIN_EXT}) +set(CMAKE_NM_UTIL ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}gcc-nm${TOOLCHAIN_EXT}) +set(CMAKE_AR ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}gcc-ar${TOOLCHAIN_EXT}) +set(CMAKE_RANLIB ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}gcc-ranlib${TOOLCHAIN_EXT}) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +# Compiler and linker flags +set(CMAKE_COMMON_FLAGS "-g3 -ffunction-sections -fdata-sections -fno-strict-aliasing -fno-builtin -fno-common -Wall -Wdouble-promotion -Werror -Wno-unused-parameter") +set(CMAKE_C_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} ${CMAKE_COMMON_FLAGS}") +set(CMAKE_CXX_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} ${CMAKE_COMMON_FLAGS}") +set(CMAKE_ASM_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} ${CMAKE_COMMON_FLAGS}") +set(CMAKE_EXE_LINKER_FLAGS "${LD_FLAGS} --specs=nano.specs -Wl,--gc-sections,-print-memory-usage") + +set(CMAKE_C_FLAGS_DEBUG "-O0") +set(CMAKE_CXX_FLAGS_DEBUG "-O0") +set(CMAKE_ASM_FLAGS_DEBUG "") +set(CMAKE_EXE_LINKER_FLAGS_DEBUG "") + +set(CMAKE_C_FLAGS_RELEASE "-Os -flto") +set(CMAKE_CXX_FLAGS_RELEASE "-Os -flto") +set(CMAKE_ASM_FLAGS_RELEASE "") +set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-flto") diff --git a/NXP/MIMXRT1064-EVK/cmake/utilities.cmake b/NXP/MIMXRT1064-EVK/cmake/utilities.cmake new file mode 100644 index 00000000..b86454da --- /dev/null +++ b/NXP/MIMXRT1064-EVK/cmake/utilities.cmake @@ -0,0 +1,50 @@ +# Copyright (c) Microsoft +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Microsoft - Initial version +# Frédéric Desbiens - 2024 version. +# Ali Eissa - 2026 version. + +function(post_build TARGET) + if(CMAKE_C_COMPILER_ID STREQUAL "IAR") + add_custom_target(${TARGET}.bin ALL + DEPENDS ${TARGET} + COMMAND ${CMAKE_IAR_ELFTOOL} --bin ${TARGET}.elf ${TARGET}.bin) + elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU") + add_custom_target(${TARGET}.bin ALL + DEPENDS ${TARGET} + COMMAND ${CMAKE_OBJCOPY} -Obinary ${TARGET}.elf ${TARGET}.bin + COMMAND ${CMAKE_OBJCOPY} -Oihex ${TARGET}.elf ${TARGET}.hex) + else() + message(FATAL_ERROR "Unknown CMAKE_C_COMPILER_ID ${CMAKE_C_COMPILER_ID}") + endif() +endfunction() + +function(set_target_linker TARGET LINKER_SCRIPT) + if(CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PRIVATE --config ${LINKER_SCRIPT}) + target_link_options(${TARGET} PRIVATE --map=${TARGET}.map) + elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PRIVATE -T${LINKER_SCRIPT}) + target_link_options(${TARGET} PRIVATE -Wl,-Map=${TARGET}.map) + set_target_properties(${TARGET} PROPERTIES SUFFIX ".elf") + else() + message(FATAL_ERROR "Unknown CMAKE_C_COMPILER_ID ${CMAKE_C_COMPILER_ID}") + endif() +endfunction() + +macro(print_all_variables) + message(STATUS "print_all_variables------------------------------------------{") + get_cmake_property(_variableNames VARIABLES) + foreach (_variableName ${_variableNames}) + message(STATUS "${_variableName}=${${_variableName}}") + endforeach() + message(STATUS "print_all_variables------------------------------------------}") +endmacro() diff --git a/NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h b/NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h new file mode 100644 index 00000000..c9258245 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h @@ -0,0 +1,26 @@ +/**************************************************************************/ +/* Copyright (c) Microsoft */ +/* Copyright (c) 2026 Eclipse ThreadX contributors */ +/* */ +/* This program and the accompanying materials are made available */ +/* under the terms of the MIT license which is available at */ +/* https://opensource.org/license/mit. */ +/* */ +/* SPDX-License-Identifier: MIT */ +/* */ +/* Contributors: */ +/* Ali Eissa - 2026 version. */ +/**************************************************************************/ + +#ifndef TX_USER_H +#define TX_USER_H + +/* Enable hardware FPU register context switching support for Cortex-M7 */ +#define TX_ENABLE_FPU_SUPPORT + +/* System tick frequency in Hz (typically 100 or 1000) */ +#ifndef TX_TIMER_TICKS_PER_SECOND +#define TX_TIMER_TICKS_PER_SECOND 1000 +#endif + +#endif /* TX_USER_H */ diff --git a/NXP/MIMXRT1064-EVK/scripts/build.ps1 b/NXP/MIMXRT1064-EVK/scripts/build.ps1 new file mode 100644 index 00000000..e688610d --- /dev/null +++ b/NXP/MIMXRT1064-EVK/scripts/build.ps1 @@ -0,0 +1,84 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. + +param( + [switch]$Clean, + [switch]$Rebuild +) + +$BoardDir = Resolve-Path "$PSScriptRoot/.." +$BUILD_DIR = Join-Path $BoardDir "build" +$NUM_JOBS = 4 + +Write-Host "==========================================" +Write-Host "NXP MIMXRT1064-EVK - Build Script" +Write-Host "==========================================" +Write-Host "Board Dir: $BoardDir" +Write-Host "Build Dir: $BUILD_DIR" +Write-Host "" + +# Check for ARM GCC compiler +$armGcc = Get-Command "arm-none-eabi-gcc" -ErrorAction SilentlyContinue +if (!$armGcc -and !$env:ARM_GCC_PATH) { + Write-Host "[WARNING] arm-none-eabi-gcc not found on PATH and ARM_GCC_PATH not set." -ForegroundColor Yellow + Write-Host "" +} + +if ($Clean -or $Rebuild) { + Write-Host "[INFO] Cleaning build directory..." + if (Test-Path $BUILD_DIR) { + Remove-Item -Path $BUILD_DIR -Recurse -Force + } + New-Item -ItemType Directory -Path $BUILD_DIR -Force | Out-Null + Write-Host "[OK] Build directory cleaned" + Write-Host "" +} + +if (!(Test-Path $BUILD_DIR)) { + New-Item -ItemType Directory -Path $BUILD_DIR -Force | Out-Null +} + +Push-Location $BUILD_DIR + +# Reconfigure if CMakeCache.txt or build.ninja is missing, or if forced +if (!(Test-Path "CMakeCache.txt") -or !(Test-Path "build.ninja") -or $Rebuild) { + Write-Host "[INFO] Configuring CMake..." + cmake -G Ninja ` + "-DCMAKE_BUILD_TYPE=Release" ` + .. + if ($LASTEXITCODE -ne 0) { + Write-Host "[ERROR] CMake configuration failed!" -ForegroundColor Red + Pop-Location + exit 1 + } + Write-Host "[OK] CMake configured" + Write-Host "" +} + +Write-Host "[INFO] Building with $NUM_JOBS parallel jobs..." +if (Get-Command ninja -ErrorAction SilentlyContinue) { + ninja -j $NUM_JOBS +} else { + cmake --build . --parallel $NUM_JOBS --config Release +} + +$buildExitCode = $LASTEXITCODE +Pop-Location + +if ($buildExitCode -ne 0) { + Write-Host "[ERROR] Build failed!" -ForegroundColor Red + exit 1 +} + +Write-Host "" +Write-Host "==========================================" +Write-Host "[OK] Build completed successfully!" +Write-Host "==========================================" diff --git a/NXP/MIMXRT1064-EVK/scripts/build.sh b/NXP/MIMXRT1064-EVK/scripts/build.sh new file mode 100644 index 00000000..a202f82f --- /dev/null +++ b/NXP/MIMXRT1064-EVK/scripts/build.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +BOARD_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" +BUILD_DIR="${BOARD_DIR}/build" +NUM_JOBS=4 + +CLEAN=0 +REBUILD=0 + +# Parse arguments +while [[ "$#" -gt 0 ]]; do + case $1 in + --clean) CLEAN=1 ;; + --rebuild) REBUILD=1 ;; + *) echo "Unknown parameter passed: $1"; exit 1 ;; + esac + shift +done + +echo "==========================================" +echo "NXP MIMXRT1064-EVK - Build Script (POSIX)" +echo "==========================================" +echo "Board Dir: ${BOARD_DIR}" +echo "Build Dir: ${BUILD_DIR}" +echo "" + +# Check for ARM GCC compiler +if ! command -v arm-none-eabi-gcc &> /dev/null && [ -z "${ARM_GCC_PATH}" ]; then + echo "[WARNING] arm-none-eabi-gcc not found on PATH and ARM_GCC_PATH not set." + echo "" +fi + +if [ "${CLEAN}" -eq 1 ] || [ "${REBUILD}" -eq 1 ]; then + echo "[INFO] Cleaning build directory..." + rm -rf "${BUILD_DIR}" + mkdir -p "${BUILD_DIR}" + echo "[OK] Build directory cleaned" + echo "" +fi + +mkdir -p "${BUILD_DIR}" +cd "${BUILD_DIR}" + +# Reconfigure if CMakeCache.txt or build.ninja is missing, or if forced +if [ ! -f "CMakeCache.txt" ] || [ ! -f "build.ninja" ] || [ "${REBUILD}" -eq 1 ]; then + echo "[INFO] Configuring CMake..." + cmake -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + .. + echo "[OK] CMake configured" + echo "" +fi + +echo "[INFO] Building with ${NUM_JOBS} parallel jobs..." +if command -v ninja &> /dev/null; then + ninja -j "${NUM_JOBS}" +else + cmake --build . --parallel "${NUM_JOBS}" --config Release +fi + +echo "" +echo "==========================================" +echo "[OK] Build completed successfully!" +echo "==========================================" diff --git a/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 new file mode 100644 index 00000000..8965cb87 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 @@ -0,0 +1,169 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. + +$BoardDir = Resolve-Path "$PSScriptRoot/.." +$LibDir = Join-Path $BoardDir "lib/mcux-sdk" +$DeviceDir = Join-Path $LibDir "devices/MIMXRT1064" +$DriversDir = Join-Path $LibDir "drivers" +$UtilitiesDir = Join-Path $LibDir "utilities" +$ComponentsDir = Join-Path $LibDir "components" +$BoardFilesDir = Join-Path $LibDir "board" +$CmsisIncludeDest = Join-Path $LibDir "CMSIS/Include" +$TempDir = Join-Path $BoardDir "temp_fetch" + +Write-Host "==========================================" +Write-Host "NXP i.MX RT1064 Standalone Driver Fetcher" +Write-Host "==========================================" +Write-Host "Target Directory: $LibDir" +Write-Host "" + +# Clean and create target directories +if (Test-Path $LibDir) { Remove-Item -Path $LibDir -Recurse -Force } +New-Item -ItemType Directory -Path $DeviceDir -Force | Out-Null +New-Item -ItemType Directory -Path $DriversDir -Force | Out-Null +New-Item -ItemType Directory -Path $UtilitiesDir -Force | Out-Null +New-Item -ItemType Directory -Path (Join-Path $ComponentsDir "uart") -Force | Out-Null +New-Item -ItemType Directory -Path $BoardFilesDir -Force | Out-Null +New-Item -ItemType Directory -Path $CmsisIncludeDest -Force | Out-Null + +if (Test-Path $TempDir) { Remove-Item -Path $TempDir -Recurse -Force } +New-Item -ItemType Directory -Path $TempDir -Force | Out-Null + +function Clean-Temp { + if (Test-Path $TempDir) { + Remove-Item -Path $TempDir -Recurse -Force + } +} + +try { + # 1. Download official NXP MIMXRT1064 DFP pack from NXP repository + $packUrl = "https://mcuxpresso.nxp.com/cmsis_pack/repo/NXP.MIMXRT1064_DFP.15.1.0.pack" + $packZip = Join-Path $TempDir "dfp.zip" + $packExtract = Join-Path $TempDir "dfp_extracted" + + Write-Host "[INFO] Downloading official NXP MIMXRT1064 Device Pack..." + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + Invoke-WebRequest -Uri $packUrl -OutFile $packZip -UseBasicParsing + + Write-Host "[INFO] Extracting Device Pack..." + Expand-Archive -Path $packZip -DestinationPath $packExtract -Force + + # Copy device register headers & system files + $deviceFiles = @( + "MIMXRT1064.h", + "MIMXRT1064_features.h", + "fsl_device_registers.h", + "system_MIMXRT1064.c", + "system_MIMXRT1064.h" + ) + foreach ($file in $deviceFiles) { + $source = Join-Path $packExtract $file + if (Test-Path $source) { + Copy-Item -Path $source -Destination $DeviceDir -Force + } + } + + # Copy core peripheral drivers + $driverList = @( + "fsl_clock.c", "fsl_clock.h", + "fsl_common.c", "fsl_common.h", + "fsl_common_arm.c", "fsl_common_arm.h", + "fsl_gpio.c", "fsl_gpio.h", + "fsl_lpuart.c", "fsl_lpuart.h", + "fsl_enet.c", "fsl_enet.h", + "fsl_iomuxc.h" + ) + foreach ($file in $driverList) { + $source = Join-Path $packExtract "drivers/$file" + if (Test-Path $source) { + Copy-Item -Path $source -Destination $DriversDir -Force + } + } + + # Copy utilities (debug console & string formatting) + $utilFiles = @( + "utilities/debug_console_lite/fsl_debug_console.h", + "utilities/debug_console_lite/fsl_debug_console.c", + "utilities/debug_console_lite/fsl_assert.c", + "utilities/debug_console/fsl_debug_console_conf.h", + "utilities/str/fsl_str.c", + "utilities/str/fsl_str.h" + ) + foreach ($file in $utilFiles) { + $source = Join-Path $packExtract $file + if (Test-Path $source) { + Copy-Item -Path $source -Destination $UtilitiesDir -Force + } + } + + # Copy UART component adapter + $compUartDest = Join-Path $ComponentsDir "uart" + $compUartFiles = @( + "components/uart/fsl_adapter_uart.h", + "components/uart/fsl_adapter_lpuart.c" + ) + foreach ($file in $compUartFiles) { + $source = Join-Path $packExtract $file + if (Test-Path $source) { + Copy-Item -Path $source -Destination $compUartDest -Force + } + } + + # Copy XIP flexspi boot header from pack + $xipSource = Join-Path $packExtract "xip" + if (Test-Path $xipSource) { + Copy-Item -Path "$xipSource/*" -Destination $DeviceDir -Recurse -Force + } + Write-Host "[OK] NXP Device, Driver, Utility, and Component files copied" + Write-Host "" + + # 2. Download EVK-MIMXRT1064 Board Initialization Files from official NXP mcuxsdk-examples + $rawBase = "https://raw.githubusercontent.com/nxp-mcuxpresso/mcuxsdk-examples/main/_boards/evkmimxrt1064" + $boardFiles = @( + @{ Remote = "$rawBase/board.c"; Local = "board.c" }, + @{ Remote = "$rawBase/board.h"; Local = "board.h" }, + @{ Remote = "$rawBase/project_template/clock_config.c"; Local = "clock_config.c" }, + @{ Remote = "$rawBase/project_template/clock_config.h"; Local = "clock_config.h" }, + @{ Remote = "$rawBase/project_template/pin_mux.c"; Local = "pin_mux.c" }, + @{ Remote = "$rawBase/project_template/pin_mux.h"; Local = "pin_mux.h" }, + @{ Remote = "$rawBase/dcd.c"; Local = "dcd.c" }, + @{ Remote = "$rawBase/dcd.h"; Local = "dcd.h" }, + @{ Remote = "$rawBase/xip/evkmimxrt1064_flexspi_nor_config.c"; Local = "evkmimxrt1064_flexspi_nor_config.c" }, + @{ Remote = "$rawBase/xip/evkmimxrt1064_flexspi_nor_config.h"; Local = "evkmimxrt1064_flexspi_nor_config.h" }, + @{ Remote = "$rawBase/linker/mcux/MIMXRT1064xxxxx_flexspi_nor.ld"; Local = "MIMXRT1064xxxxx_flexspi_nor.ld" } + ) + + Write-Host "[INFO] Downloading EVK-MIMXRT1064 board support files..." + foreach ($item in $boardFiles) { + $dest = Join-Path $BoardFilesDir $item.Local + Invoke-WebRequest -Uri $item.Remote -OutFile $dest -UseBasicParsing + } + Write-Host "[OK] Board support files downloaded" + Write-Host "" + + # 3. Fetch CMSIS Core headers (standard ARM CMSIS-Core include files) + Write-Host "[INFO] Cloning CMSIS Core headers (depth=1)..." + $cmsisCloneDir = Join-Path $TempDir "cmsis_core_repo" + git clone --depth 1 https://github.com/STMicroelectronics/cmsis-core.git $cmsisCloneDir + if ($LASTEXITCODE -ne 0) { + throw "Failed to clone CMSIS Core repository" + } + Copy-Item -Path "$cmsisCloneDir/CMSIS/Core/Include/*" -Destination $CmsisIncludeDest -Recurse -Force + Write-Host "[OK] CMSIS Core headers copied" + Write-Host "" + + Write-Host "==========================================" + Write-Host "[SUCCESS] NXP i.MX RT1064 drivers successfully fetched!" + Write-Host "==========================================" +} +finally { + Clean-Temp +} diff --git a/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh new file mode 100644 index 00000000..50f2c45c --- /dev/null +++ b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh @@ -0,0 +1,128 @@ +#!/usr/bin/env bash +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +BOARD_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" + +LIB_DIR="${BOARD_DIR}/lib/mcux-sdk" +DEVICE_DIR="${LIB_DIR}/devices/MIMXRT1064" +DRIVERS_DIR="${LIB_DIR}/drivers" +UTILITIES_DIR="${LIB_DIR}/utilities" +COMPONENTS_DIR="${LIB_DIR}/components" +BOARD_FILES_DIR="${LIB_DIR}/board" +CMSIS_INCLUDE_DEST="${LIB_DIR}/CMSIS/Include" +TEMP_DIR="${BOARD_DIR}/temp_fetch" + +echo "==========================================" +echo "NXP i.MX RT1064 Standalone Driver Fetcher (POSIX)" +echo "==========================================" +echo "Target Directory: ${LIB_DIR}" +echo "" + +# Clean and recreate directories +rm -rf "${LIB_DIR}" +mkdir -p "${DEVICE_DIR}" +mkdir -p "${DRIVERS_DIR}" +mkdir -p "${UTILITIES_DIR}" +mkdir -p "${COMPONENTS_DIR}/uart" +mkdir -p "${BOARD_FILES_DIR}" +mkdir -p "${CMSIS_INCLUDE_DEST}" + +rm -rf "${TEMP_DIR}" +mkdir -p "${TEMP_DIR}" + +clean_temp() { + if [ -d "${TEMP_DIR}" ]; then + rm -rf "${TEMP_DIR}" + fi +} +trap clean_temp EXIT + +# 1. Download official NXP MIMXRT1064 DFP pack from NXP repository +PACK_URL="https://mcuxpresso.nxp.com/cmsis_pack/repo/NXP.MIMXRT1064_DFP.15.1.0.pack" +PACK_ZIP="${TEMP_DIR}/dfp.zip" +PACK_EXTRACT="${TEMP_DIR}/dfp_extracted" + +echo "[INFO] Downloading official NXP MIMXRT1064 Device Pack..." +curl -fsSL "${PACK_URL}" -o "${PACK_ZIP}" + +echo "[INFO] Extracting Device Pack..." +mkdir -p "${PACK_EXTRACT}" +unzip -q "${PACK_ZIP}" -d "${PACK_EXTRACT}" + +# Copy device register headers & system files +for file in MIMXRT1064.h MIMXRT1064_features.h fsl_device_registers.h system_MIMXRT1064.c system_MIMXRT1064.h; do + if [ -f "${PACK_EXTRACT}/${file}" ]; then + cp "${PACK_EXTRACT}/${file}" "${DEVICE_DIR}/" + fi +done + +# Copy core peripheral drivers +for file in fsl_clock.c fsl_clock.h fsl_common.c fsl_common.h fsl_common_arm.c fsl_common_arm.h fsl_gpio.c fsl_gpio.h fsl_lpuart.c fsl_lpuart.h fsl_enet.c fsl_enet.h fsl_iomuxc.h; do + if [ -f "${PACK_EXTRACT}/drivers/${file}" ]; then + cp "${PACK_EXTRACT}/drivers/${file}" "${DRIVERS_DIR}/" + fi +done + +# Copy utilities (debug console & string formatting) +for file in utilities/debug_console_lite/fsl_debug_console.h utilities/debug_console_lite/fsl_debug_console.c utilities/debug_console_lite/fsl_assert.c utilities/debug_console/fsl_debug_console_conf.h utilities/str/fsl_str.c utilities/str/fsl_str.h; do + if [ -f "${PACK_EXTRACT}/${file}" ]; then + cp "${PACK_EXTRACT}/${file}" "${UTILITIES_DIR}/" + fi +done + +# Copy UART component adapter +for file in components/uart/fsl_adapter_uart.h components/uart/fsl_adapter_lpuart.c; do + if [ -f "${PACK_EXTRACT}/${file}" ]; then + cp "${PACK_EXTRACT}/${file}" "${COMPONENTS_DIR}/uart/" + fi +done + +# Copy XIP flexspi boot headers +if [ -d "${PACK_EXTRACT}/xip" ]; then + cp -r "${PACK_EXTRACT}/xip/"* "${DEVICE_DIR}/" +fi +echo "[OK] NXP Device, Driver, Utility, and Component files copied" +echo "" + +# 2. Download EVK-MIMXRT1064 Board Support Files from official NXP mcuxsdk-examples +RAW_BASE="https://raw.githubusercontent.com/nxp-mcuxpresso/mcuxsdk-examples/main/_boards/evkmimxrt1064" +echo "[INFO] Downloading EVK-MIMXRT1064 board support files..." + +curl -fsSL "${RAW_BASE}/board.c" -o "${BOARD_FILES_DIR}/board.c" +curl -fsSL "${RAW_BASE}/board.h" -o "${BOARD_FILES_DIR}/board.h" +curl -fsSL "${RAW_BASE}/project_template/clock_config.c" -o "${BOARD_FILES_DIR}/clock_config.c" +curl -fsSL "${RAW_BASE}/project_template/clock_config.h" -o "${BOARD_FILES_DIR}/clock_config.h" +curl -fsSL "${RAW_BASE}/project_template/pin_mux.c" -o "${BOARD_FILES_DIR}/pin_mux.c" +curl -fsSL "${RAW_BASE}/project_template/pin_mux.h" -o "${BOARD_FILES_DIR}/pin_mux.h" +curl -fsSL "${RAW_BASE}/dcd.c" -o "${BOARD_FILES_DIR}/dcd.c" +curl -fsSL "${RAW_BASE}/dcd.h" -o "${BOARD_FILES_DIR}/dcd.h" +curl -fsSL "${RAW_BASE}/xip/evkmimxrt1064_flexspi_nor_config.c" -o "${BOARD_FILES_DIR}/evkmimxrt1064_flexspi_nor_config.c" +curl -fsSL "${RAW_BASE}/xip/evkmimxrt1064_flexspi_nor_config.h" -o "${BOARD_FILES_DIR}/evkmimxrt1064_flexspi_nor_config.h" +curl -fsSL "${RAW_BASE}/linker/mcux/MIMXRT1064xxxxx_flexspi_nor.ld" -o "${BOARD_FILES_DIR}/MIMXRT1064xxxxx_flexspi_nor.ld" + +echo "[OK] Board support files downloaded" +echo "" + +# 3. Fetch CMSIS Core headers +echo "[INFO] Cloning CMSIS Core headers (depth=1)..." +CMSIS_CLONE_DIR="${TEMP_DIR}/cmsis_core_repo" +git clone --depth 1 https://github.com/STMicroelectronics/cmsis-core.git "${CMSIS_CLONE_DIR}" +cp -r "${CMSIS_CLONE_DIR}/CMSIS/Core/Include/"* "${CMSIS_INCLUDE_DEST}/" +echo "[OK] CMSIS Core headers copied" +echo "" + +echo "==========================================" +echo "[SUCCESS] NXP i.MX RT1064 drivers successfully fetched!" +echo "==========================================" From 8bf20ef1f1a3bb6be12f026ea92f4d2dabc05370 Mon Sep 17 00:00:00 2001 From: Ali Eissa Date: Thu, 10 Sep 2026 06:55:45 +0400 Subject: [PATCH 02/13] Bring up core ThreadX kernel on MIMXRT1064-EVK --- NXP/MIMXRT1064-EVK/CMakeLists.txt | 52 + NXP/MIMXRT1064-EVK/app/board_init.c | 33 + NXP/MIMXRT1064-EVK/app/board_init.h | 32 + NXP/MIMXRT1064-EVK/app/console.c | 87 ++ NXP/MIMXRT1064-EVK/app/console.h | 34 + NXP/MIMXRT1064-EVK/app/main.c | 158 +++ .../startup/MIMXRT1064xxxxx_flexspi_nor.ld | 276 ++++ .../app/startup/startup_mimxrt1064.S | 1146 +++++++++++++++++ .../app/startup/tx_initialize_low_level.S | 207 +++ NXP/MIMXRT1064-EVK/app/syscalls.c | 131 ++ NXP/MIMXRT1064-EVK/app/sysmem.c | 50 + NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h | 2 +- NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc | 21 + NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 | 37 +- NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh | 12 +- NXP/MIMXRT1064-EVK/scripts/simulate.ps1 | 47 + NXP/MIMXRT1064-EVK/scripts/simulate.sh | 43 + 17 files changed, 2361 insertions(+), 7 deletions(-) create mode 100644 NXP/MIMXRT1064-EVK/app/board_init.c create mode 100644 NXP/MIMXRT1064-EVK/app/board_init.h create mode 100644 NXP/MIMXRT1064-EVK/app/console.c create mode 100644 NXP/MIMXRT1064-EVK/app/console.h create mode 100644 NXP/MIMXRT1064-EVK/app/main.c create mode 100644 NXP/MIMXRT1064-EVK/app/startup/MIMXRT1064xxxxx_flexspi_nor.ld create mode 100644 NXP/MIMXRT1064-EVK/app/startup/startup_mimxrt1064.S create mode 100644 NXP/MIMXRT1064-EVK/app/startup/tx_initialize_low_level.S create mode 100644 NXP/MIMXRT1064-EVK/app/syscalls.c create mode 100644 NXP/MIMXRT1064-EVK/app/sysmem.c create mode 100644 NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc create mode 100644 NXP/MIMXRT1064-EVK/scripts/simulate.ps1 create mode 100644 NXP/MIMXRT1064-EVK/scripts/simulate.sh diff --git a/NXP/MIMXRT1064-EVK/CMakeLists.txt b/NXP/MIMXRT1064-EVK/CMakeLists.txt index 66d6593d..69036528 100644 --- a/NXP/MIMXRT1064-EVK/CMakeLists.txt +++ b/NXP/MIMXRT1064-EVK/CMakeLists.txt @@ -82,3 +82,55 @@ target_include_directories(${SDK_TARGET} # Compile ThreadX Kernel from root shared libs submodule set(THREADX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../libs/threadx") add_subdirectory(${THREADX_DIR} threadx) + +# Create the Main Executable +set(EXE_TARGET mimxrt1064_threadx) + +add_executable(${EXE_TARGET} + app/startup/startup_mimxrt1064.S + app/startup/tx_initialize_low_level.S + app/board_init.c + app/console.c + app/main.c + app/sysmem.c + app/syscalls.c +) + +# Set compile definitions for our executable +target_compile_definitions(${EXE_TARGET} + PRIVATE + CPU_MIMXRT1064DVL6A + XIP_EXTERNAL_FLASH=1 + XIP_BOOT_HEADER_ENABLE=1 + XIP_BOOT_HEADER_DCD_ENABLE=1 + FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE=1 + SDK_DEBUGCONSOLE=1 + SKIP_SYSCLK_INIT=1 +) + +# Include paths +target_include_directories(${EXE_TARGET} + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/app + ${SDK_DIR}/CMSIS/Include + ${SDK_DIR}/devices/MIMXRT1064 + ${SDK_DIR}/drivers + ${SDK_DIR}/board + ${SDK_DIR}/utilities + ${SDK_DIR}/components/uart + ${TX_USER_FILE_DIR} +) + +# Link libraries (includes ThreadX kernel and MCUXpresso SDK object libraries) +target_link_libraries(${EXE_TARGET} + PRIVATE + threadx + mcux_sdk +) + +# Apply GCC linker script and print memory usage (utilities.cmake function) +set_target_linker(${EXE_TARGET} "${CMAKE_CURRENT_LIST_DIR}/app/startup/MIMXRT1064xxxxx_flexspi_nor.ld") + +# Post-build commands to generate raw .bin and .hex files +post_build(${EXE_TARGET}) + diff --git a/NXP/MIMXRT1064-EVK/app/board_init.c b/NXP/MIMXRT1064-EVK/app/board_init.c new file mode 100644 index 00000000..9586e39c --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/board_init.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available + * under the terms of the MIT license which is available at + * https://opensource.org/license/mit. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 NXP i.MX RT1064 port. + */ + +#include "board_init.h" +#include "console.h" + +void board_init(void) +{ + /* 1. Configure the Memory Protection Unit if supported by hardware (16 regions on real Cortex-M7 silicon) */ + if (((MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos) >= 12) + { + BOARD_ConfigMPU(); + } + + /* 2. Configure Pin Muxing (UART1 TX/RX pins) */ + BOARD_InitPins(); + + /* 3. Configure System Clocks (600 MHz AHB core clock) */ + BOARD_BootClockRUN(); + + /* 4. Initialize LPUART1 Serial Console at 115200 baud */ + console_init(); +} diff --git a/NXP/MIMXRT1064-EVK/app/board_init.h b/NXP/MIMXRT1064-EVK/app/board_init.h new file mode 100644 index 00000000..3080890b --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/board_init.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available + * under the terms of the MIT license which is available at + * https://opensource.org/license/mit. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 NXP i.MX RT1064 port. + */ + +#ifndef BOARD_INIT_H +#define BOARD_INIT_H + +#include "fsl_common.h" +#include "board.h" +#include "pin_mux.h" +#include "clock_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void board_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* BOARD_INIT_H */ diff --git a/NXP/MIMXRT1064-EVK/app/console.c b/NXP/MIMXRT1064-EVK/app/console.c new file mode 100644 index 00000000..9c95756f --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/console.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available + * under the terms of the MIT license which is available at + * https://opensource.org/license/mit. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 NXP i.MX RT1064 port. + */ + +#include "console.h" +#include "fsl_lpuart.h" +#include "board.h" + +void console_init(void) +{ + lpuart_config_t config; + + LPUART_GetDefaultConfig(&config); + config.baudRate_Bps = 115200U; + config.enableTx = true; + config.enableRx = true; + + uint32_t uartClkSrcFreq = BOARD_DebugConsoleSrcFreq(); + LPUART_Init(LPUART1, &config, uartClkSrcFreq); +} + +void console_putc(char c) +{ + if (c == '\n') + { + while (!(LPUART_GetStatusFlags(LPUART1) & (uint32_t)kLPUART_TxDataRegEmptyFlag)) + { + } + LPUART_WriteByte(LPUART1, (uint8_t)'\r'); + } + + while (!(LPUART_GetStatusFlags(LPUART1) & (uint32_t)kLPUART_TxDataRegEmptyFlag)) + { + } + LPUART_WriteByte(LPUART1, (uint8_t)c); +} + +void console_write(const char *str) +{ + while (*str != '\0') + { + console_putc(*str++); + } +} + +int __io_putchar(int ch) +{ + console_putc((char)ch); + return ch; +} + +int __io_getchar(void) +{ + while (!(LPUART_GetStatusFlags(LPUART1) & (uint32_t)kLPUART_RxDataRegFullFlag)) + { + } + return (int)LPUART_ReadByte(LPUART1); +} + +int _write(int file, char *ptr, int len) +{ + (void)file; + for (int i = 0; i < len; i++) + { + console_putc(ptr[i]); + } + return len; +} + +int _read(int file, char *ptr, int len) +{ + (void)file; + for (int i = 0; i < len; i++) + { + ptr[i] = (char)__io_getchar(); + } + return len; +} diff --git a/NXP/MIMXRT1064-EVK/app/console.h b/NXP/MIMXRT1064-EVK/app/console.h new file mode 100644 index 00000000..89140a90 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/console.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available + * under the terms of the MIT license which is available at + * https://opensource.org/license/mit. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 NXP i.MX RT1064 port. + */ + +#ifndef CONSOLE_H +#define CONSOLE_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void console_init(void); +void console_putc(char c); +void console_write(const char *str); +int __io_putchar(int ch); +int __io_getchar(void); + +#ifdef __cplusplus +} +#endif + +#endif /* CONSOLE_H */ diff --git a/NXP/MIMXRT1064-EVK/app/main.c b/NXP/MIMXRT1064-EVK/app/main.c new file mode 100644 index 00000000..c3807225 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/main.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available + * under the terms of the MIT license which is available at + * https://opensource.org/license/mit. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 NXP i.MX RT1064 port. + */ + +#include "board_init.h" +#include "console.h" +#include "tx_api.h" +#include + +#define HEARTBEAT_THREAD_STACK_SIZE 1024 +#define WORKER_THREAD_STACK_SIZE 1024 + +static TX_THREAD heartbeat_thread; +static uint8_t heartbeat_thread_stack[HEARTBEAT_THREAD_STACK_SIZE]; + +static TX_THREAD worker_thread; +static uint8_t worker_thread_stack[WORKER_THREAD_STACK_SIZE]; + +static TX_TIMER app_timer; +static volatile ULONG timer_fire_count = 0; + +/* Thread Function Prototypes */ +static void heartbeat_thread_entry(ULONG thread_input); +static void worker_thread_entry(ULONG thread_input); +static void app_timer_callback(ULONG timer_input); + +int main(void) +{ + /* Initialize hardware: MPU, clocks (600 MHz), pins, and LPUART1 */ + board_init(); + + printf("\r\n"); + printf("==================================================\r\n"); + printf(" Eclipse ThreadX RTOS on NXP i.MX RT1064-EVK\r\n"); + printf(" Simulated in Antmicro Renode\r\n"); + printf("==================================================\r\n"); + printf("[System] Core Clock: %lu MHz | Tick Rate: %u Hz\r\n", + SystemCoreClock / 1000000UL, + TX_TIMER_TICKS_PER_SECOND); + printf("[System] Initializing ThreadX kernel...\r\n"); + + /* Enter the ThreadX kernel */ + tx_kernel_enter(); + + return 0; +} + +void tx_application_define(void *first_unused_memory) +{ + (void)first_unused_memory; + + UINT status; + + /* Create Heartbeat Thread (Priority 15 - lower priority) */ + status = tx_thread_create(&heartbeat_thread, + "Heartbeat Thread", + heartbeat_thread_entry, + 0, + heartbeat_thread_stack, + HEARTBEAT_THREAD_STACK_SIZE, + 15, + 15, + TX_NO_TIME_SLICE, + TX_AUTO_START); + if (status != TX_SUCCESS) + { + printf("[ERROR] Failed to create Heartbeat Thread (status: 0x%02X)\r\n", status); + } + + /* Create Worker Thread (Priority 10 - medium priority) */ + status = tx_thread_create(&worker_thread, + "Worker Thread", + worker_thread_entry, + 0, + worker_thread_stack, + WORKER_THREAD_STACK_SIZE, + 10, + 10, + TX_NO_TIME_SLICE, + TX_AUTO_START); + if (status != TX_SUCCESS) + { + printf("[ERROR] Failed to create Worker Thread (status: 0x%02X)\r\n", status); + } + + /* Create Application Timer (Periodic 200 ms / 20 ticks) */ + status = tx_timer_create(&app_timer, + "App Timer", + app_timer_callback, + 0, + 20, /* Initial ticks (200 ms) */ + 20, /* Reschedule ticks (200 ms) */ + TX_AUTO_ACTIVATE); + if (status != TX_SUCCESS) + { + printf("[ERROR] Failed to create App Timer (status: 0x%02X)\r\n", status); + } + + printf("[System] ThreadX threads and timer registered successfully.\r\n"); +} + +static void heartbeat_thread_entry(ULONG thread_input) +{ + (void)thread_input; + ULONG count = 0; + + printf("[Heartbeat Thread] Started.\r\n"); + + while (1) + { + /* Sleep for 50 ticks (500 ms @ 100 Hz) */ + tx_thread_sleep(50); + count++; + + printf("[Heartbeat Thread] Heartbeat #%lu (System Tick: %lu)\r\n", + count, tx_time_get()); + } +} + +static void worker_thread_entry(ULONG thread_input) +{ + (void)thread_input; + ULONG iteration = 0; + + printf("[Worker Thread] Started.\r\n"); + + while (1) + { + /* Sleep for 100 ticks (1000 ms @ 100 Hz) */ + tx_thread_sleep(100); + iteration++; + + printf("[Worker Thread] Executing periodic task (iteration #%lu, System Tick: %lu)\r\n", + iteration, tx_time_get()); + } +} + +static void app_timer_callback(ULONG timer_input) +{ + (void)timer_input; + timer_fire_count++; + + /* Report every 5 fires (1 second) */ + if ((timer_fire_count % 5) == 0) + { + printf("[App Timer] Kernel timer callback active (total firings: %lu)\r\n", + timer_fire_count); + } +} diff --git a/NXP/MIMXRT1064-EVK/app/startup/MIMXRT1064xxxxx_flexspi_nor.ld b/NXP/MIMXRT1064-EVK/app/startup/MIMXRT1064xxxxx_flexspi_nor.ld new file mode 100644 index 00000000..e5dd1d68 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/startup/MIMXRT1064xxxxx_flexspi_nor.ld @@ -0,0 +1,276 @@ +/* +** ################################################################### +** Processors: MIMXRT1064CVJ5A +** MIMXRT1064CVJ5B +** MIMXRT1064CVL5A +** MIMXRT1064CVL5B +** MIMXRT1064DVJ6A +** MIMXRT1064DVJ6B +** MIMXRT1064DVL6A +** MIMXRT1064DVL6B +** +** Compiler: GNU C Compiler +** Reference manual: IMXRT1064RM Rev.2, 7/2021 | IMXRT106XSRM Rev.0 +** Version: rev. 0.1, 2018-06-22 +** Build: b230821 +** +** Abstract: +** Linker file for the GNU C Compiler +** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2023 NXP +** SPDX-License-Identifier: BSD-3-Clause +** +** http: www.nxp.com +** mail: support@nxp.com +** +** ################################################################### +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x0400; +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0400; +VECTOR_RAM_SIZE = DEFINED(__ram_vector_table__) ? 0x00000400 : 0; + +/* Specify the memory areas */ +MEMORY +{ + m_flash_config (RX) : ORIGIN = 0x70000000, LENGTH = 0x00001000 + m_ivt (RX) : ORIGIN = 0x70001000, LENGTH = 0x00001000 + m_interrupts (RX) : ORIGIN = 0x70002000, LENGTH = 0x00000400 + m_text (RX) : ORIGIN = 0x70002400, LENGTH = 0x003FDC00 + m_qacode (RX) : ORIGIN = 0x00000000, LENGTH = 0x00020000 + m_data (RW) : ORIGIN = 0x20000000, LENGTH = 0x00020000 + m_data2 (RW) : ORIGIN = 0x20200000, LENGTH = 0x000C0000 +} + +/* Define output sections */ +SECTIONS +{ + __NCACHE_REGION_START = ORIGIN(m_data2); + __NCACHE_REGION_SIZE = 0; + + .flash_config : + { + . = ALIGN(4); + __FLASH_BASE = .; + KEEP(* (.boot_hdr.conf)) /* flash config section */ + . = ALIGN(4); + } > m_flash_config + + ivt_begin = ORIGIN(m_flash_config) + LENGTH(m_flash_config); + + .ivt : AT(ivt_begin) + { + . = ALIGN(4); + KEEP(* (.boot_hdr.ivt)) /* ivt section */ + KEEP(* (.boot_hdr.boot_data)) /* boot section */ + KEEP(* (.boot_hdr.dcd_data)) /* dcd section */ + . = ALIGN(4); + } > m_ivt + + /* The startup code goes first into internal RAM */ + .interrupts : + { + __VECTOR_TABLE = .; + __Vectors = .; + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } > m_interrupts + + /* The program code and other data goes into internal RAM */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + KEEP (*(.init)) + KEEP (*(.fini)) + . = ALIGN(4); + } > m_text + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > m_text + + .ARM : + { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } > m_text + + .ctors : + { + __CTOR_LIST__ = .; + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + from the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __CTOR_END__ = .; + } > m_text + + .dtors : + { + __DTOR_LIST__ = .; + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __DTOR_END__ = .; + } > m_text + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } > m_text + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } > m_text + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } > m_text + + __etext = .; /* define a global symbol at end of code */ + __DATA_ROM = .; /* Symbol is used by startup for data initialization */ + + .interrupts_ram : + { + . = ALIGN(4); + __VECTOR_RAM__ = .; + __interrupts_ram_start__ = .; /* Create a global symbol at data start */ + *(.m_interrupts_ram) /* This is a user defined section */ + . += VECTOR_RAM_SIZE; + . = ALIGN(4); + __interrupts_ram_end__ = .; /* Define a global symbol at data end */ + } > m_data + + __VECTOR_RAM = DEFINED(__ram_vector_table__) ? __VECTOR_RAM__ : ORIGIN(m_interrupts); + __RAM_VECTOR_TABLE_SIZE_BYTES = DEFINED(__ram_vector_table__) ? (__interrupts_ram_end__ - __interrupts_ram_start__) : 0x0; + + .data : AT(__DATA_ROM) + { + . = ALIGN(4); + __DATA_RAM = .; + __data_start__ = .; /* create a global symbol at data start */ + *(m_usb_dma_init_data) + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + *(DataQuickAccess) /* quick access data section */ + KEEP(*(.jcr*)) + . = ALIGN(4); + __data_end__ = .; /* define a global symbol at data end */ + } > m_data + + __ram_function_flash_start = __DATA_ROM + (__data_end__ - __data_start__); /* Symbol is used by startup for TCM data initialization */ + + .ram_function : AT(__ram_function_flash_start) + { + . = ALIGN(32); + __ram_function_start__ = .; + *(CodeQuickAccess) + . = ALIGN(128); + __ram_function_end__ = .; + } > m_qacode + + __NDATA_ROM = __ram_function_flash_start + (__ram_function_end__ - __ram_function_start__); + .ncache.init : AT(__NDATA_ROM) + { + __noncachedata_start__ = .; /* create a global symbol at ncache data start */ + *(NonCacheable.init) + . = ALIGN(4); + __noncachedata_init_end__ = .; /* create a global symbol at initialized ncache data end */ + } > m_data + . = __noncachedata_init_end__; + .ncache : + { + *(NonCacheable) + . = ALIGN(4); + __noncachedata_end__ = .; /* define a global symbol at ncache data end */ + } > m_data + + __DATA_END = __NDATA_ROM + (__noncachedata_init_end__ - __noncachedata_start__); + text_end = ORIGIN(m_text) + LENGTH(m_text); + ASSERT(__DATA_END <= text_end, "region m_text overflowed with text and data") + + /* Uninitialized data section */ + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + . = ALIGN(4); + __START_BSS = .; + __bss_start__ = .; + *(m_usb_dma_noninit_data) + *(.bss) + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + __END_BSS = .; + } > m_data + + .heap : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + PROVIDE(_end = .); + __HeapBase = .; + . += HEAP_SIZE; + __HeapLimit = .; + __heap_limit = .; /* Add for _sbrk */ + __RAM_segment_used_end__ = .; /* Used by ThreadX for first unused memory */ + } > m_data + + .stack : + { + . = ALIGN(8); + . += STACK_SIZE; + } > m_data + + /* Initializes stack on the end of block */ + __StackTop = ORIGIN(m_data) + LENGTH(m_data); + __StackLimit = __StackTop - STACK_SIZE; + PROVIDE(__stack = __StackTop); + PROVIDE(_estack = __StackTop); + + .ARM.attributes 0 : { *(.ARM.attributes) } + + ASSERT(__StackLimit >= __HeapLimit, "region m_data overflowed with stack and heap") +} diff --git a/NXP/MIMXRT1064-EVK/app/startup/startup_mimxrt1064.S b/NXP/MIMXRT1064-EVK/app/startup/startup_mimxrt1064.S new file mode 100644 index 00000000..a2137e4f --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/startup/startup_mimxrt1064.S @@ -0,0 +1,1146 @@ +/* ------------------------------------------------------------------------- */ +/* @file: startup_MIMXRT1064.s */ +/* @purpose: CMSIS Cortex-M7 Core Device Startup File */ +/* MIMXRT1064 */ +/* @version: 1.3 */ +/* @date: 2021-8-10 */ +/* @build: b231019 */ +/* ------------------------------------------------------------------------- */ +/* */ +/* Copyright 1997-2016 Freescale Semiconductor, Inc. */ +/* Copyright 2016-2023 NXP */ +/* SPDX-License-Identifier: BSD-3-Clause */ +/*****************************************************************************/ +/* Version: GCC for ARM Embedded Processors */ +/*****************************************************************************/ + .syntax unified + .arch armv7-m + + .section .isr_vector, "a" + .align 2 + .globl __isr_vector + .globl __VECTOR_TABLE + .globl __Vectors + .globl _vectors + .globl g_pfnVectors +__isr_vector: +__VECTOR_TABLE: +__Vectors: +_vectors: +g_pfnVectors: + .long __StackTop /* Top of Stack */ + .long Reset_Handler /* Reset Handler */ + .long NMI_Handler /* NMI Handler*/ + .long HardFault_Handler /* Hard Fault Handler*/ + .long MemManage_Handler /* MPU Fault Handler*/ + .long BusFault_Handler /* Bus Fault Handler*/ + .long UsageFault_Handler /* Usage Fault Handler*/ + .long 0 /* Reserved*/ + .long 0 /* Reserved*/ + .long 0 /* Reserved*/ + .long 0 /* Reserved*/ + .long SVC_Handler /* SVCall Handler*/ + .long DebugMon_Handler /* Debug Monitor Handler*/ + .long 0 /* Reserved*/ + .long PendSV_Handler /* PendSV Handler*/ + .long SysTick_Handler /* SysTick Handler*/ + + /* External Interrupts*/ + .long DMA0_DMA16_IRQHandler /* DMA channel 0/16 transfer complete*/ + .long DMA1_DMA17_IRQHandler /* DMA channel 1/17 transfer complete*/ + .long DMA2_DMA18_IRQHandler /* DMA channel 2/18 transfer complete*/ + .long DMA3_DMA19_IRQHandler /* DMA channel 3/19 transfer complete*/ + .long DMA4_DMA20_IRQHandler /* DMA channel 4/20 transfer complete*/ + .long DMA5_DMA21_IRQHandler /* DMA channel 5/21 transfer complete*/ + .long DMA6_DMA22_IRQHandler /* DMA channel 6/22 transfer complete*/ + .long DMA7_DMA23_IRQHandler /* DMA channel 7/23 transfer complete*/ + .long DMA8_DMA24_IRQHandler /* DMA channel 8/24 transfer complete*/ + .long DMA9_DMA25_IRQHandler /* DMA channel 9/25 transfer complete*/ + .long DMA10_DMA26_IRQHandler /* DMA channel 10/26 transfer complete*/ + .long DMA11_DMA27_IRQHandler /* DMA channel 11/27 transfer complete*/ + .long DMA12_DMA28_IRQHandler /* DMA channel 12/28 transfer complete*/ + .long DMA13_DMA29_IRQHandler /* DMA channel 13/29 transfer complete*/ + .long DMA14_DMA30_IRQHandler /* DMA channel 14/30 transfer complete*/ + .long DMA15_DMA31_IRQHandler /* DMA channel 15/31 transfer complete*/ + .long DMA_ERROR_IRQHandler /* DMA error interrupt channels 0-15 / 16-31*/ + .long CTI0_ERROR_IRQHandler /* CTI0_Error*/ + .long CTI1_ERROR_IRQHandler /* CTI1_Error*/ + .long CORE_IRQHandler /* CorePlatform exception IRQ*/ + .long LPUART1_IRQHandler /* LPUART1 TX interrupt and RX interrupt*/ + .long LPUART2_IRQHandler /* LPUART2 TX interrupt and RX interrupt*/ + .long LPUART3_IRQHandler /* LPUART3 TX interrupt and RX interrupt*/ + .long LPUART4_IRQHandler /* LPUART4 TX interrupt and RX interrupt*/ + .long LPUART5_IRQHandler /* LPUART5 TX interrupt and RX interrupt*/ + .long LPUART6_IRQHandler /* LPUART6 TX interrupt and RX interrupt*/ + .long LPUART7_IRQHandler /* LPUART7 TX interrupt and RX interrupt*/ + .long LPUART8_IRQHandler /* LPUART8 TX interrupt and RX interrupt*/ + .long LPI2C1_IRQHandler /* LPI2C1 interrupt*/ + .long LPI2C2_IRQHandler /* LPI2C2 interrupt*/ + .long LPI2C3_IRQHandler /* LPI2C3 interrupt*/ + .long LPI2C4_IRQHandler /* LPI2C4 interrupt*/ + .long LPSPI1_IRQHandler /* LPSPI1 single interrupt vector for all sources*/ + .long LPSPI2_IRQHandler /* LPSPI2 single interrupt vector for all sources*/ + .long LPSPI3_IRQHandler /* LPSPI3 single interrupt vector for all sources*/ + .long LPSPI4_IRQHandler /* LPSPI4 single interrupt vector for all sources*/ + .long CAN1_IRQHandler /* CAN1 interrupt*/ + .long CAN2_IRQHandler /* CAN2 interrupt*/ + .long FLEXRAM_IRQHandler /* FlexRAM address out of range Or access hit IRQ*/ + .long KPP_IRQHandler /* Keypad nterrupt*/ + .long TSC_DIG_IRQHandler /* TSC interrupt*/ + .long GPR_IRQ_IRQHandler /* GPR interrupt*/ + .long LCDIF_IRQHandler /* LCDIF interrupt*/ + .long CSI_IRQHandler /* CSI interrupt*/ + .long PXP_IRQHandler /* PXP interrupt*/ + .long WDOG2_IRQHandler /* WDOG2 interrupt*/ + .long SNVS_HP_WRAPPER_IRQHandler /* SRTC Consolidated Interrupt. Non TZ*/ + .long SNVS_HP_WRAPPER_TZ_IRQHandler /* SRTC Security Interrupt. TZ*/ + .long SNVS_LP_WRAPPER_IRQHandler /* ON-OFF button press shorter than 5 secs (pulse event)*/ + .long CSU_IRQHandler /* CSU interrupt*/ + .long DCP_IRQHandler /* DCP_IRQ interrupt*/ + .long DCP_VMI_IRQHandler /* DCP_VMI_IRQ interrupt*/ + .long Reserved68_IRQHandler /* Reserved interrupt*/ + .long TRNG_IRQHandler /* TRNG interrupt*/ + .long SJC_IRQHandler /* SJC interrupt*/ + .long BEE_IRQHandler /* BEE interrupt*/ + .long SAI1_IRQHandler /* SAI1 interrupt*/ + .long SAI2_IRQHandler /* SAI1 interrupt*/ + .long SAI3_RX_IRQHandler /* SAI3 interrupt*/ + .long SAI3_TX_IRQHandler /* SAI3 interrupt*/ + .long SPDIF_IRQHandler /* SPDIF interrupt*/ + .long PMU_EVENT_IRQHandler /* Brown-out event interrupt*/ + .long Reserved78_IRQHandler /* Reserved interrupt*/ + .long TEMP_LOW_HIGH_IRQHandler /* TempSensor low/high interrupt*/ + .long TEMP_PANIC_IRQHandler /* TempSensor panic interrupt*/ + .long USB_PHY1_IRQHandler /* USBPHY (UTMI0), Interrupt*/ + .long USB_PHY2_IRQHandler /* USBPHY (UTMI1), Interrupt*/ + .long ADC1_IRQHandler /* ADC1 interrupt*/ + .long ADC2_IRQHandler /* ADC2 interrupt*/ + .long DCDC_IRQHandler /* DCDC interrupt*/ + .long Reserved86_IRQHandler /* Reserved interrupt*/ + .long GPIO10_IRQHandler /* GPIO10 interrupt*/ + .long GPIO1_INT0_IRQHandler /* Active HIGH Interrupt from INT0 from GPIO*/ + .long GPIO1_INT1_IRQHandler /* Active HIGH Interrupt from INT1 from GPIO*/ + .long GPIO1_INT2_IRQHandler /* Active HIGH Interrupt from INT2 from GPIO*/ + .long GPIO1_INT3_IRQHandler /* Active HIGH Interrupt from INT3 from GPIO*/ + .long GPIO1_INT4_IRQHandler /* Active HIGH Interrupt from INT4 from GPIO*/ + .long GPIO1_INT5_IRQHandler /* Active HIGH Interrupt from INT5 from GPIO*/ + .long GPIO1_INT6_IRQHandler /* Active HIGH Interrupt from INT6 from GPIO*/ + .long GPIO1_INT7_IRQHandler /* Active HIGH Interrupt from INT7 from GPIO*/ + .long GPIO1_Combined_0_15_IRQHandler /* Combined interrupt indication for GPIO1 signal 0 throughout 15*/ + .long GPIO1_Combined_16_31_IRQHandler /* Combined interrupt indication for GPIO1 signal 16 throughout 31*/ + .long GPIO2_Combined_0_15_IRQHandler /* Combined interrupt indication for GPIO2 signal 0 throughout 15*/ + .long GPIO2_Combined_16_31_IRQHandler /* Combined interrupt indication for GPIO2 signal 16 throughout 31*/ + .long GPIO3_Combined_0_15_IRQHandler /* Combined interrupt indication for GPIO3 signal 0 throughout 15*/ + .long GPIO3_Combined_16_31_IRQHandler /* Combined interrupt indication for GPIO3 signal 16 throughout 31*/ + .long GPIO4_Combined_0_15_IRQHandler /* Combined interrupt indication for GPIO4 signal 0 throughout 15*/ + .long GPIO4_Combined_16_31_IRQHandler /* Combined interrupt indication for GPIO4 signal 16 throughout 31*/ + .long GPIO5_Combined_0_15_IRQHandler /* Combined interrupt indication for GPIO5 signal 0 throughout 15*/ + .long GPIO5_Combined_16_31_IRQHandler /* Combined interrupt indication for GPIO5 signal 16 throughout 31*/ + .long FLEXIO1_IRQHandler /* FLEXIO1 interrupt*/ + .long FLEXIO2_IRQHandler /* FLEXIO2 interrupt*/ + .long WDOG1_IRQHandler /* WDOG1 interrupt*/ + .long RTWDOG_IRQHandler /* RTWDOG interrupt*/ + .long EWM_IRQHandler /* EWM interrupt*/ + .long CCM_1_IRQHandler /* CCM IRQ1 interrupt*/ + .long CCM_2_IRQHandler /* CCM IRQ2 interrupt*/ + .long GPC_IRQHandler /* GPC interrupt*/ + .long SRC_IRQHandler /* SRC interrupt*/ + .long Reserved115_IRQHandler /* Reserved interrupt*/ + .long GPT1_IRQHandler /* GPT1 interrupt*/ + .long GPT2_IRQHandler /* GPT2 interrupt*/ + .long PWM1_0_IRQHandler /* PWM1 capture 0, compare 0, or reload 0 interrupt*/ + .long PWM1_1_IRQHandler /* PWM1 capture 1, compare 1, or reload 0 interrupt*/ + .long PWM1_2_IRQHandler /* PWM1 capture 2, compare 2, or reload 0 interrupt*/ + .long PWM1_3_IRQHandler /* PWM1 capture 3, compare 3, or reload 0 interrupt*/ + .long PWM1_FAULT_IRQHandler /* PWM1 fault or reload error interrupt*/ + .long FLEXSPI2_IRQHandler /* FlexSPI2 interrupt*/ + .long FLEXSPI_IRQHandler /* FlexSPI0 interrupt*/ + .long SEMC_IRQHandler /* SEMC interrupt*/ + .long USDHC1_IRQHandler /* USDHC1 interrupt*/ + .long USDHC2_IRQHandler /* USDHC2 interrupt*/ + .long USB_OTG2_IRQHandler /* USBO2 USB OTG2*/ + .long USB_OTG1_IRQHandler /* USBO2 USB OTG1*/ + .long ENET_IRQHandler /* ENET interrupt*/ + .long ENET_1588_Timer_IRQHandler /* ENET_1588_Timer interrupt*/ + .long XBAR1_IRQ_0_1_IRQHandler /* XBARA1 output signal 0, 1 interrupt*/ + .long XBAR1_IRQ_2_3_IRQHandler /* XBARA1 output signal 2, 3 interrupt*/ + .long ADC_ETC_IRQ0_IRQHandler /* ADCETC IRQ0 interrupt*/ + .long ADC_ETC_IRQ1_IRQHandler /* ADCETC IRQ1 interrupt*/ + .long ADC_ETC_IRQ2_IRQHandler /* ADCETC IRQ2 interrupt*/ + .long ADC_ETC_ERROR_IRQ_IRQHandler /* ADCETC Error IRQ interrupt*/ + .long PIT_IRQHandler /* PIT interrupt*/ + .long ACMP1_IRQHandler /* ACMP interrupt*/ + .long ACMP2_IRQHandler /* ACMP interrupt*/ + .long ACMP3_IRQHandler /* ACMP interrupt*/ + .long ACMP4_IRQHandler /* ACMP interrupt*/ + .long Reserved143_IRQHandler /* Reserved interrupt*/ + .long Reserved144_IRQHandler /* Reserved interrupt*/ + .long ENC1_IRQHandler /* ENC1 interrupt*/ + .long ENC2_IRQHandler /* ENC2 interrupt*/ + .long ENC3_IRQHandler /* ENC3 interrupt*/ + .long ENC4_IRQHandler /* ENC4 interrupt*/ + .long TMR1_IRQHandler /* TMR1 interrupt*/ + .long TMR2_IRQHandler /* TMR2 interrupt*/ + .long TMR3_IRQHandler /* TMR3 interrupt*/ + .long TMR4_IRQHandler /* TMR4 interrupt*/ + .long PWM2_0_IRQHandler /* PWM2 capture 0, compare 0, or reload 0 interrupt*/ + .long PWM2_1_IRQHandler /* PWM2 capture 1, compare 1, or reload 0 interrupt*/ + .long PWM2_2_IRQHandler /* PWM2 capture 2, compare 2, or reload 0 interrupt*/ + .long PWM2_3_IRQHandler /* PWM2 capture 3, compare 3, or reload 0 interrupt*/ + .long PWM2_FAULT_IRQHandler /* PWM2 fault or reload error interrupt*/ + .long PWM3_0_IRQHandler /* PWM3 capture 0, compare 0, or reload 0 interrupt*/ + .long PWM3_1_IRQHandler /* PWM3 capture 1, compare 1, or reload 0 interrupt*/ + .long PWM3_2_IRQHandler /* PWM3 capture 2, compare 2, or reload 0 interrupt*/ + .long PWM3_3_IRQHandler /* PWM3 capture 3, compare 3, or reload 0 interrupt*/ + .long PWM3_FAULT_IRQHandler /* PWM3 fault or reload error interrupt*/ + .long PWM4_0_IRQHandler /* PWM4 capture 0, compare 0, or reload 0 interrupt*/ + .long PWM4_1_IRQHandler /* PWM4 capture 1, compare 1, or reload 0 interrupt*/ + .long PWM4_2_IRQHandler /* PWM4 capture 2, compare 2, or reload 0 interrupt*/ + .long PWM4_3_IRQHandler /* PWM4 capture 3, compare 3, or reload 0 interrupt*/ + .long PWM4_FAULT_IRQHandler /* PWM4 fault or reload error interrupt*/ + .long ENET2_IRQHandler /* ENET2 interrupt*/ + .long ENET2_1588_Timer_IRQHandler /* ENET2_1588_Timer interrupt*/ + .long CAN3_IRQHandler /* CAN3 interrupt*/ + .long Reserved171_IRQHandler /* Reserved interrupt*/ + .long FLEXIO3_IRQHandler /* FLEXIO3 interrupt*/ + .long GPIO6_7_8_9_IRQHandler /* GPIO6, GPIO7, GPIO8, GPIO9 interrupt*/ + .long DefaultISR /* 174*/ + .long DefaultISR /* 175*/ + .long DefaultISR /* 176*/ + .long DefaultISR /* 177*/ + .long DefaultISR /* 178*/ + .long DefaultISR /* 179*/ + .long DefaultISR /* 180*/ + .long DefaultISR /* 181*/ + .long DefaultISR /* 182*/ + .long DefaultISR /* 183*/ + .long DefaultISR /* 184*/ + .long DefaultISR /* 185*/ + .long DefaultISR /* 186*/ + .long DefaultISR /* 187*/ + .long DefaultISR /* 188*/ + .long DefaultISR /* 189*/ + .long DefaultISR /* 190*/ + .long DefaultISR /* 191*/ + .long DefaultISR /* 192*/ + .long DefaultISR /* 193*/ + .long DefaultISR /* 194*/ + .long DefaultISR /* 195*/ + .long DefaultISR /* 196*/ + .long DefaultISR /* 197*/ + .long DefaultISR /* 198*/ + .long DefaultISR /* 199*/ + .long DefaultISR /* 200*/ + .long DefaultISR /* 201*/ + .long DefaultISR /* 202*/ + .long DefaultISR /* 203*/ + .long DefaultISR /* 204*/ + .long DefaultISR /* 205*/ + .long DefaultISR /* 206*/ + .long DefaultISR /* 207*/ + .long DefaultISR /* 208*/ + .long DefaultISR /* 209*/ + .long DefaultISR /* 210*/ + .long DefaultISR /* 211*/ + .long DefaultISR /* 212*/ + .long DefaultISR /* 213*/ + .long DefaultISR /* 214*/ + .long DefaultISR /* 215*/ + .long DefaultISR /* 216*/ + .long DefaultISR /* 217*/ + .long DefaultISR /* 218*/ + .long DefaultISR /* 219*/ + .long DefaultISR /* 220*/ + .long DefaultISR /* 221*/ + .long DefaultISR /* 222*/ + .long DefaultISR /* 223*/ + .long DefaultISR /* 224*/ + .long DefaultISR /* 225*/ + .long DefaultISR /* 226*/ + .long DefaultISR /* 227*/ + .long DefaultISR /* 228*/ + .long DefaultISR /* 229*/ + .long DefaultISR /* 230*/ + .long DefaultISR /* 231*/ + .long DefaultISR /* 232*/ + .long DefaultISR /* 233*/ + .long DefaultISR /* 234*/ + .long DefaultISR /* 235*/ + .long DefaultISR /* 236*/ + .long DefaultISR /* 237*/ + .long DefaultISR /* 238*/ + .long DefaultISR /* 239*/ + .long DefaultISR /* 240*/ + .long DefaultISR /* 241*/ + .long DefaultISR /* 242*/ + .long DefaultISR /* 243*/ + .long DefaultISR /* 244*/ + .long DefaultISR /* 245*/ + .long DefaultISR /* 246*/ + .long DefaultISR /* 247*/ + .long DefaultISR /* 248*/ + .long DefaultISR /* 249*/ + .long DefaultISR /* 250*/ + .long DefaultISR /* 251*/ + .long DefaultISR /* 252*/ + .long DefaultISR /* 253*/ + .long DefaultISR /* 254*/ + .long 0xFFFFFFFF /* Reserved for user TRIM value*/ + + .size __isr_vector, . - __isr_vector + + .text + .thumb + +#if defined (__cplusplus) +#ifdef __REDLIB__ +#error Redlib does not support C++ +#endif +#endif +/* Reset Handler */ + + .thumb_func + .align 2 + .globl Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + cpsid i /* Mask interrupts */ + .equ VTOR, 0xE000ED08 + ldr r0, =VTOR + ldr r1, =__isr_vector + str r1, [r0] + ldr r2, [r1] + msr msp, r2 +#ifndef __NO_SYSTEM_INIT + ldr r0,=SystemInit + blx r0 +#endif +/* Loop to copy data from read only memory to RAM. The ranges + * of copy from/to are specified by following symbols evaluated in + * linker script. + * __etext: End of code section, i.e., begin of data sections to copy from. + * __data_start__/__data_end__: RAM address range that data should be + * __noncachedata_start__/__noncachedata_end__ : none cachable region + * __ram_function_start__/__ram_function_end__ : ramfunction region + * copied to. Both must be aligned to 4 bytes boundary. */ + + ldr r1, =__etext + ldr r2, =__data_start__ + ldr r3, =__data_end__ + +#ifdef __PERFORMANCE_IMPLEMENTATION +/* Here are two copies of loop implementations. First one favors performance + * and the second one favors code size. Default uses the second one. + * Define macro "__PERFORMANCE_IMPLEMENTATION" in project to use the first one */ + subs r3, r2 + ble .LC1 +.LC0: + subs r3, #4 + ldr r0, [r1, r3] + str r0, [r2, r3] + bgt .LC0 +.LC1: +#else /* code size implemenation */ +.LC0: + cmp r2, r3 + ittt lt + ldrlt r0, [r1], #4 + strlt r0, [r2], #4 + blt .LC0 +#endif +#ifdef __STARTUP_INITIALIZE_RAMFUNCTION + ldr r2, =__ram_function_start__ + ldr r3, =__ram_function_end__ +#ifdef __PERFORMANCE_IMPLEMENTATION +/* Here are two copies of loop implementations. First one favors performance + * and the second one favors code size. Default uses the second one. + * Define macro "__PERFORMANCE_IMPLEMENTATION" in project to use the first one */ + subs r3, r2 + ble .LC_ramfunc_copy_end +.LC_ramfunc_copy_start: + subs r3, #4 + ldr r0, [r1, r3] + str r0, [r2, r3] + bgt .LC_ramfunc_copy_start +.LC_ramfunc_copy_end: +#else /* code size implemenation */ +.LC_ramfunc_copy_start: + cmp r2, r3 + ittt lt + ldrlt r0, [r1], #4 + strlt r0, [r2], #4 + blt .LC_ramfunc_copy_start +#endif +#endif /* __STARTUP_INITIALIZE_RAMFUNCTION */ +#ifdef __STARTUP_INITIALIZE_NONCACHEDATA + ldr r2, =__noncachedata_start__ + ldr r3, =__noncachedata_init_end__ +#ifdef __PERFORMANCE_IMPLEMENTATION +/* Here are two copies of loop implementations. First one favors performance + * and the second one favors code size. Default uses the second one. + * Define macro "__PERFORMANCE_IMPLEMENTATION" in project to use the first one */ + subs r3, r2 + ble .LC3 +.LC2: + subs r3, #4 + ldr r0, [r1, r3] + str r0, [r2, r3] + bgt .LC2 +.LC3: +#else /* code size implemenation */ +.LC2: + cmp r2, r3 + ittt lt + ldrlt r0, [r1], #4 + strlt r0, [r2], #4 + blt .LC2 +#endif +/* zero inited ncache section initialization */ + ldr r3, =__noncachedata_end__ + movs r0,0 +.LC4: + cmp r2,r3 + itt lt + strlt r0,[r2],#4 + blt .LC4 +#endif /* __STARTUP_INITIALIZE_NONCACHEDATA */ + +#ifndef __STARTUP_CLEAR_BSS +#define __STARTUP_CLEAR_BSS +#endif + +#ifdef __STARTUP_CLEAR_BSS +/* This part of work usually is done in C library startup code. Otherwise, + * define this macro to enable it in this startup. + * + * Loop to zero out BSS section, which uses following symbols + * in linker script: + * __bss_start__: start of BSS section. Must align to 4 + * __bss_end__: end of BSS section. Must align to 4 + */ + ldr r1, =__bss_start__ + ldr r2, =__bss_end__ + + movs r0, 0 +.LC5: + cmp r1, r2 + itt lt + strlt r0, [r1], #4 + blt .LC5 +#endif /* __STARTUP_CLEAR_BSS */ + + cpsie i /* Unmask interrupts */ +#ifndef __START +#ifdef __REDLIB__ +#define __START __main +#else +#define __START _start +#endif +#endif +#ifndef __ATOLLIC__ + ldr r0,=__START + blx r0 +#else + ldr r0,=__libc_init_array + blx r0 + ldr r0,=main + bx r0 +#endif + .pool + .size Reset_Handler, . - Reset_Handler + + .align 1 + .thumb_func + .weak DefaultISR + .type DefaultISR, %function +DefaultISR: + b DefaultISR + .size DefaultISR, . - DefaultISR + + .align 1 + .thumb_func + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + ldr r0,=NMI_Handler + bx r0 + .size NMI_Handler, . - NMI_Handler + + .align 1 + .thumb_func + .weak HardFault_Handler + .type HardFault_Handler, %function +HardFault_Handler: + ldr r0,=HardFault_Handler + bx r0 + .size HardFault_Handler, . - HardFault_Handler + + .align 1 + .thumb_func + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + ldr r0,=SVC_Handler + bx r0 + .size SVC_Handler, . - SVC_Handler + + .align 1 + .thumb_func + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + ldr r0,=PendSV_Handler + bx r0 + .size PendSV_Handler, . - PendSV_Handler + + .align 1 + .thumb_func + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + ldr r0,=SysTick_Handler + bx r0 + .size SysTick_Handler, . - SysTick_Handler + + .align 1 + .thumb_func + .weak DMA0_DMA16_IRQHandler + .type DMA0_DMA16_IRQHandler, %function +DMA0_DMA16_IRQHandler: + ldr r0,=DMA0_DMA16_DriverIRQHandler + bx r0 + .size DMA0_DMA16_IRQHandler, . - DMA0_DMA16_IRQHandler + + .align 1 + .thumb_func + .weak DMA1_DMA17_IRQHandler + .type DMA1_DMA17_IRQHandler, %function +DMA1_DMA17_IRQHandler: + ldr r0,=DMA1_DMA17_DriverIRQHandler + bx r0 + .size DMA1_DMA17_IRQHandler, . - DMA1_DMA17_IRQHandler + + .align 1 + .thumb_func + .weak DMA2_DMA18_IRQHandler + .type DMA2_DMA18_IRQHandler, %function +DMA2_DMA18_IRQHandler: + ldr r0,=DMA2_DMA18_DriverIRQHandler + bx r0 + .size DMA2_DMA18_IRQHandler, . - DMA2_DMA18_IRQHandler + + .align 1 + .thumb_func + .weak DMA3_DMA19_IRQHandler + .type DMA3_DMA19_IRQHandler, %function +DMA3_DMA19_IRQHandler: + ldr r0,=DMA3_DMA19_DriverIRQHandler + bx r0 + .size DMA3_DMA19_IRQHandler, . - DMA3_DMA19_IRQHandler + + .align 1 + .thumb_func + .weak DMA4_DMA20_IRQHandler + .type DMA4_DMA20_IRQHandler, %function +DMA4_DMA20_IRQHandler: + ldr r0,=DMA4_DMA20_DriverIRQHandler + bx r0 + .size DMA4_DMA20_IRQHandler, . - DMA4_DMA20_IRQHandler + + .align 1 + .thumb_func + .weak DMA5_DMA21_IRQHandler + .type DMA5_DMA21_IRQHandler, %function +DMA5_DMA21_IRQHandler: + ldr r0,=DMA5_DMA21_DriverIRQHandler + bx r0 + .size DMA5_DMA21_IRQHandler, . - DMA5_DMA21_IRQHandler + + .align 1 + .thumb_func + .weak DMA6_DMA22_IRQHandler + .type DMA6_DMA22_IRQHandler, %function +DMA6_DMA22_IRQHandler: + ldr r0,=DMA6_DMA22_DriverIRQHandler + bx r0 + .size DMA6_DMA22_IRQHandler, . - DMA6_DMA22_IRQHandler + + .align 1 + .thumb_func + .weak DMA7_DMA23_IRQHandler + .type DMA7_DMA23_IRQHandler, %function +DMA7_DMA23_IRQHandler: + ldr r0,=DMA7_DMA23_DriverIRQHandler + bx r0 + .size DMA7_DMA23_IRQHandler, . - DMA7_DMA23_IRQHandler + + .align 1 + .thumb_func + .weak DMA8_DMA24_IRQHandler + .type DMA8_DMA24_IRQHandler, %function +DMA8_DMA24_IRQHandler: + ldr r0,=DMA8_DMA24_DriverIRQHandler + bx r0 + .size DMA8_DMA24_IRQHandler, . - DMA8_DMA24_IRQHandler + + .align 1 + .thumb_func + .weak DMA9_DMA25_IRQHandler + .type DMA9_DMA25_IRQHandler, %function +DMA9_DMA25_IRQHandler: + ldr r0,=DMA9_DMA25_DriverIRQHandler + bx r0 + .size DMA9_DMA25_IRQHandler, . - DMA9_DMA25_IRQHandler + + .align 1 + .thumb_func + .weak DMA10_DMA26_IRQHandler + .type DMA10_DMA26_IRQHandler, %function +DMA10_DMA26_IRQHandler: + ldr r0,=DMA10_DMA26_DriverIRQHandler + bx r0 + .size DMA10_DMA26_IRQHandler, . - DMA10_DMA26_IRQHandler + + .align 1 + .thumb_func + .weak DMA11_DMA27_IRQHandler + .type DMA11_DMA27_IRQHandler, %function +DMA11_DMA27_IRQHandler: + ldr r0,=DMA11_DMA27_DriverIRQHandler + bx r0 + .size DMA11_DMA27_IRQHandler, . - DMA11_DMA27_IRQHandler + + .align 1 + .thumb_func + .weak DMA12_DMA28_IRQHandler + .type DMA12_DMA28_IRQHandler, %function +DMA12_DMA28_IRQHandler: + ldr r0,=DMA12_DMA28_DriverIRQHandler + bx r0 + .size DMA12_DMA28_IRQHandler, . - DMA12_DMA28_IRQHandler + + .align 1 + .thumb_func + .weak DMA13_DMA29_IRQHandler + .type DMA13_DMA29_IRQHandler, %function +DMA13_DMA29_IRQHandler: + ldr r0,=DMA13_DMA29_DriverIRQHandler + bx r0 + .size DMA13_DMA29_IRQHandler, . - DMA13_DMA29_IRQHandler + + .align 1 + .thumb_func + .weak DMA14_DMA30_IRQHandler + .type DMA14_DMA30_IRQHandler, %function +DMA14_DMA30_IRQHandler: + ldr r0,=DMA14_DMA30_DriverIRQHandler + bx r0 + .size DMA14_DMA30_IRQHandler, . - DMA14_DMA30_IRQHandler + + .align 1 + .thumb_func + .weak DMA15_DMA31_IRQHandler + .type DMA15_DMA31_IRQHandler, %function +DMA15_DMA31_IRQHandler: + ldr r0,=DMA15_DMA31_DriverIRQHandler + bx r0 + .size DMA15_DMA31_IRQHandler, . - DMA15_DMA31_IRQHandler + + .align 1 + .thumb_func + .weak DMA_ERROR_IRQHandler + .type DMA_ERROR_IRQHandler, %function +DMA_ERROR_IRQHandler: + ldr r0,=DMA_ERROR_DriverIRQHandler + bx r0 + .size DMA_ERROR_IRQHandler, . - DMA_ERROR_IRQHandler + + .align 1 + .thumb_func + .weak LPUART1_IRQHandler + .type LPUART1_IRQHandler, %function +LPUART1_IRQHandler: + ldr r0,=LPUART1_DriverIRQHandler + bx r0 + .size LPUART1_IRQHandler, . - LPUART1_IRQHandler + + .align 1 + .thumb_func + .weak LPUART2_IRQHandler + .type LPUART2_IRQHandler, %function +LPUART2_IRQHandler: + ldr r0,=LPUART2_DriverIRQHandler + bx r0 + .size LPUART2_IRQHandler, . - LPUART2_IRQHandler + + .align 1 + .thumb_func + .weak LPUART3_IRQHandler + .type LPUART3_IRQHandler, %function +LPUART3_IRQHandler: + ldr r0,=LPUART3_DriverIRQHandler + bx r0 + .size LPUART3_IRQHandler, . - LPUART3_IRQHandler + + .align 1 + .thumb_func + .weak LPUART4_IRQHandler + .type LPUART4_IRQHandler, %function +LPUART4_IRQHandler: + ldr r0,=LPUART4_DriverIRQHandler + bx r0 + .size LPUART4_IRQHandler, . - LPUART4_IRQHandler + + .align 1 + .thumb_func + .weak LPUART5_IRQHandler + .type LPUART5_IRQHandler, %function +LPUART5_IRQHandler: + ldr r0,=LPUART5_DriverIRQHandler + bx r0 + .size LPUART5_IRQHandler, . - LPUART5_IRQHandler + + .align 1 + .thumb_func + .weak LPUART6_IRQHandler + .type LPUART6_IRQHandler, %function +LPUART6_IRQHandler: + ldr r0,=LPUART6_DriverIRQHandler + bx r0 + .size LPUART6_IRQHandler, . - LPUART6_IRQHandler + + .align 1 + .thumb_func + .weak LPUART7_IRQHandler + .type LPUART7_IRQHandler, %function +LPUART7_IRQHandler: + ldr r0,=LPUART7_DriverIRQHandler + bx r0 + .size LPUART7_IRQHandler, . - LPUART7_IRQHandler + + .align 1 + .thumb_func + .weak LPUART8_IRQHandler + .type LPUART8_IRQHandler, %function +LPUART8_IRQHandler: + ldr r0,=LPUART8_DriverIRQHandler + bx r0 + .size LPUART8_IRQHandler, . - LPUART8_IRQHandler + + .align 1 + .thumb_func + .weak LPI2C1_IRQHandler + .type LPI2C1_IRQHandler, %function +LPI2C1_IRQHandler: + ldr r0,=LPI2C1_DriverIRQHandler + bx r0 + .size LPI2C1_IRQHandler, . - LPI2C1_IRQHandler + + .align 1 + .thumb_func + .weak LPI2C2_IRQHandler + .type LPI2C2_IRQHandler, %function +LPI2C2_IRQHandler: + ldr r0,=LPI2C2_DriverIRQHandler + bx r0 + .size LPI2C2_IRQHandler, . - LPI2C2_IRQHandler + + .align 1 + .thumb_func + .weak LPI2C3_IRQHandler + .type LPI2C3_IRQHandler, %function +LPI2C3_IRQHandler: + ldr r0,=LPI2C3_DriverIRQHandler + bx r0 + .size LPI2C3_IRQHandler, . - LPI2C3_IRQHandler + + .align 1 + .thumb_func + .weak LPI2C4_IRQHandler + .type LPI2C4_IRQHandler, %function +LPI2C4_IRQHandler: + ldr r0,=LPI2C4_DriverIRQHandler + bx r0 + .size LPI2C4_IRQHandler, . - LPI2C4_IRQHandler + + .align 1 + .thumb_func + .weak LPSPI1_IRQHandler + .type LPSPI1_IRQHandler, %function +LPSPI1_IRQHandler: + ldr r0,=LPSPI1_DriverIRQHandler + bx r0 + .size LPSPI1_IRQHandler, . - LPSPI1_IRQHandler + + .align 1 + .thumb_func + .weak LPSPI2_IRQHandler + .type LPSPI2_IRQHandler, %function +LPSPI2_IRQHandler: + ldr r0,=LPSPI2_DriverIRQHandler + bx r0 + .size LPSPI2_IRQHandler, . - LPSPI2_IRQHandler + + .align 1 + .thumb_func + .weak LPSPI3_IRQHandler + .type LPSPI3_IRQHandler, %function +LPSPI3_IRQHandler: + ldr r0,=LPSPI3_DriverIRQHandler + bx r0 + .size LPSPI3_IRQHandler, . - LPSPI3_IRQHandler + + .align 1 + .thumb_func + .weak LPSPI4_IRQHandler + .type LPSPI4_IRQHandler, %function +LPSPI4_IRQHandler: + ldr r0,=LPSPI4_DriverIRQHandler + bx r0 + .size LPSPI4_IRQHandler, . - LPSPI4_IRQHandler + + .align 1 + .thumb_func + .weak CAN1_IRQHandler + .type CAN1_IRQHandler, %function +CAN1_IRQHandler: + ldr r0,=CAN1_DriverIRQHandler + bx r0 + .size CAN1_IRQHandler, . - CAN1_IRQHandler + + .align 1 + .thumb_func + .weak CAN2_IRQHandler + .type CAN2_IRQHandler, %function +CAN2_IRQHandler: + ldr r0,=CAN2_DriverIRQHandler + bx r0 + .size CAN2_IRQHandler, . - CAN2_IRQHandler + + .align 1 + .thumb_func + .weak SAI1_IRQHandler + .type SAI1_IRQHandler, %function +SAI1_IRQHandler: + ldr r0,=SAI1_DriverIRQHandler + bx r0 + .size SAI1_IRQHandler, . - SAI1_IRQHandler + + .align 1 + .thumb_func + .weak SAI2_IRQHandler + .type SAI2_IRQHandler, %function +SAI2_IRQHandler: + ldr r0,=SAI2_DriverIRQHandler + bx r0 + .size SAI2_IRQHandler, . - SAI2_IRQHandler + + .align 1 + .thumb_func + .weak SAI3_RX_IRQHandler + .type SAI3_RX_IRQHandler, %function +SAI3_RX_IRQHandler: + ldr r0,=SAI3_RX_DriverIRQHandler + bx r0 + .size SAI3_RX_IRQHandler, . - SAI3_RX_IRQHandler + + .align 1 + .thumb_func + .weak SAI3_TX_IRQHandler + .type SAI3_TX_IRQHandler, %function +SAI3_TX_IRQHandler: + ldr r0,=SAI3_TX_DriverIRQHandler + bx r0 + .size SAI3_TX_IRQHandler, . - SAI3_TX_IRQHandler + + .align 1 + .thumb_func + .weak SPDIF_IRQHandler + .type SPDIF_IRQHandler, %function +SPDIF_IRQHandler: + ldr r0,=SPDIF_DriverIRQHandler + bx r0 + .size SPDIF_IRQHandler, . - SPDIF_IRQHandler + + .align 1 + .thumb_func + .weak FLEXIO1_IRQHandler + .type FLEXIO1_IRQHandler, %function +FLEXIO1_IRQHandler: + ldr r0,=FLEXIO1_DriverIRQHandler + bx r0 + .size FLEXIO1_IRQHandler, . - FLEXIO1_IRQHandler + + .align 1 + .thumb_func + .weak FLEXIO2_IRQHandler + .type FLEXIO2_IRQHandler, %function +FLEXIO2_IRQHandler: + ldr r0,=FLEXIO2_DriverIRQHandler + bx r0 + .size FLEXIO2_IRQHandler, . - FLEXIO2_IRQHandler + + .align 1 + .thumb_func + .weak FLEXSPI2_IRQHandler + .type FLEXSPI2_IRQHandler, %function +FLEXSPI2_IRQHandler: + ldr r0,=FLEXSPI2_DriverIRQHandler + bx r0 + .size FLEXSPI2_IRQHandler, . - FLEXSPI2_IRQHandler + + .align 1 + .thumb_func + .weak FLEXSPI_IRQHandler + .type FLEXSPI_IRQHandler, %function +FLEXSPI_IRQHandler: + ldr r0,=FLEXSPI_DriverIRQHandler + bx r0 + .size FLEXSPI_IRQHandler, . - FLEXSPI_IRQHandler + + .align 1 + .thumb_func + .weak USDHC1_IRQHandler + .type USDHC1_IRQHandler, %function +USDHC1_IRQHandler: + ldr r0,=USDHC1_DriverIRQHandler + bx r0 + .size USDHC1_IRQHandler, . - USDHC1_IRQHandler + + .align 1 + .thumb_func + .weak USDHC2_IRQHandler + .type USDHC2_IRQHandler, %function +USDHC2_IRQHandler: + ldr r0,=USDHC2_DriverIRQHandler + bx r0 + .size USDHC2_IRQHandler, . - USDHC2_IRQHandler + + .align 1 + .thumb_func + .weak ENET_IRQHandler + .type ENET_IRQHandler, %function +ENET_IRQHandler: + ldr r0,=ENET_DriverIRQHandler + bx r0 + .size ENET_IRQHandler, . - ENET_IRQHandler + + .align 1 + .thumb_func + .weak ENET_1588_Timer_IRQHandler + .type ENET_1588_Timer_IRQHandler, %function +ENET_1588_Timer_IRQHandler: + ldr r0,=ENET_1588_Timer_DriverIRQHandler + bx r0 + .size ENET_1588_Timer_IRQHandler, . - ENET_1588_Timer_IRQHandler + + .align 1 + .thumb_func + .weak ENET2_IRQHandler + .type ENET2_IRQHandler, %function +ENET2_IRQHandler: + ldr r0,=ENET2_DriverIRQHandler + bx r0 + .size ENET2_IRQHandler, . - ENET2_IRQHandler + + .align 1 + .thumb_func + .weak ENET2_1588_Timer_IRQHandler + .type ENET2_1588_Timer_IRQHandler, %function +ENET2_1588_Timer_IRQHandler: + ldr r0,=ENET2_1588_Timer_DriverIRQHandler + bx r0 + .size ENET2_1588_Timer_IRQHandler, . - ENET2_1588_Timer_IRQHandler + + .align 1 + .thumb_func + .weak CAN3_IRQHandler + .type CAN3_IRQHandler, %function +CAN3_IRQHandler: + ldr r0,=CAN3_DriverIRQHandler + bx r0 + .size CAN3_IRQHandler, . - CAN3_IRQHandler + + .align 1 + .thumb_func + .weak FLEXIO3_IRQHandler + .type FLEXIO3_IRQHandler, %function +FLEXIO3_IRQHandler: + ldr r0,=FLEXIO3_DriverIRQHandler + bx r0 + .size FLEXIO3_IRQHandler, . - FLEXIO3_IRQHandler + + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, DefaultISR + .endm +/* Exception Handlers */ + def_irq_handler MemManage_Handler + def_irq_handler BusFault_Handler + def_irq_handler UsageFault_Handler + def_irq_handler DebugMon_Handler + def_irq_handler DMA0_DMA16_DriverIRQHandler + def_irq_handler DMA1_DMA17_DriverIRQHandler + def_irq_handler DMA2_DMA18_DriverIRQHandler + def_irq_handler DMA3_DMA19_DriverIRQHandler + def_irq_handler DMA4_DMA20_DriverIRQHandler + def_irq_handler DMA5_DMA21_DriverIRQHandler + def_irq_handler DMA6_DMA22_DriverIRQHandler + def_irq_handler DMA7_DMA23_DriverIRQHandler + def_irq_handler DMA8_DMA24_DriverIRQHandler + def_irq_handler DMA9_DMA25_DriverIRQHandler + def_irq_handler DMA10_DMA26_DriverIRQHandler + def_irq_handler DMA11_DMA27_DriverIRQHandler + def_irq_handler DMA12_DMA28_DriverIRQHandler + def_irq_handler DMA13_DMA29_DriverIRQHandler + def_irq_handler DMA14_DMA30_DriverIRQHandler + def_irq_handler DMA15_DMA31_DriverIRQHandler + def_irq_handler DMA_ERROR_DriverIRQHandler + def_irq_handler CTI0_ERROR_IRQHandler + def_irq_handler CTI1_ERROR_IRQHandler + def_irq_handler CORE_IRQHandler + def_irq_handler LPUART1_DriverIRQHandler + def_irq_handler LPUART2_DriverIRQHandler + def_irq_handler LPUART3_DriverIRQHandler + def_irq_handler LPUART4_DriverIRQHandler + def_irq_handler LPUART5_DriverIRQHandler + def_irq_handler LPUART6_DriverIRQHandler + def_irq_handler LPUART7_DriverIRQHandler + def_irq_handler LPUART8_DriverIRQHandler + def_irq_handler LPI2C1_DriverIRQHandler + def_irq_handler LPI2C2_DriverIRQHandler + def_irq_handler LPI2C3_DriverIRQHandler + def_irq_handler LPI2C4_DriverIRQHandler + def_irq_handler LPSPI1_DriverIRQHandler + def_irq_handler LPSPI2_DriverIRQHandler + def_irq_handler LPSPI3_DriverIRQHandler + def_irq_handler LPSPI4_DriverIRQHandler + def_irq_handler CAN1_DriverIRQHandler + def_irq_handler CAN2_DriverIRQHandler + def_irq_handler FLEXRAM_IRQHandler + def_irq_handler KPP_IRQHandler + def_irq_handler TSC_DIG_IRQHandler + def_irq_handler GPR_IRQ_IRQHandler + def_irq_handler LCDIF_IRQHandler + def_irq_handler CSI_IRQHandler + def_irq_handler PXP_IRQHandler + def_irq_handler WDOG2_IRQHandler + def_irq_handler SNVS_HP_WRAPPER_IRQHandler + def_irq_handler SNVS_HP_WRAPPER_TZ_IRQHandler + def_irq_handler SNVS_LP_WRAPPER_IRQHandler + def_irq_handler CSU_IRQHandler + def_irq_handler DCP_IRQHandler + def_irq_handler DCP_VMI_IRQHandler + def_irq_handler Reserved68_IRQHandler + def_irq_handler TRNG_IRQHandler + def_irq_handler SJC_IRQHandler + def_irq_handler BEE_IRQHandler + def_irq_handler SAI1_DriverIRQHandler + def_irq_handler SAI2_DriverIRQHandler + def_irq_handler SAI3_RX_DriverIRQHandler + def_irq_handler SAI3_TX_DriverIRQHandler + def_irq_handler SPDIF_DriverIRQHandler + def_irq_handler PMU_EVENT_IRQHandler + def_irq_handler Reserved78_IRQHandler + def_irq_handler TEMP_LOW_HIGH_IRQHandler + def_irq_handler TEMP_PANIC_IRQHandler + def_irq_handler USB_PHY1_IRQHandler + def_irq_handler USB_PHY2_IRQHandler + def_irq_handler ADC1_IRQHandler + def_irq_handler ADC2_IRQHandler + def_irq_handler DCDC_IRQHandler + def_irq_handler Reserved86_IRQHandler + def_irq_handler GPIO10_IRQHandler + def_irq_handler GPIO1_INT0_IRQHandler + def_irq_handler GPIO1_INT1_IRQHandler + def_irq_handler GPIO1_INT2_IRQHandler + def_irq_handler GPIO1_INT3_IRQHandler + def_irq_handler GPIO1_INT4_IRQHandler + def_irq_handler GPIO1_INT5_IRQHandler + def_irq_handler GPIO1_INT6_IRQHandler + def_irq_handler GPIO1_INT7_IRQHandler + def_irq_handler GPIO1_Combined_0_15_IRQHandler + def_irq_handler GPIO1_Combined_16_31_IRQHandler + def_irq_handler GPIO2_Combined_0_15_IRQHandler + def_irq_handler GPIO2_Combined_16_31_IRQHandler + def_irq_handler GPIO3_Combined_0_15_IRQHandler + def_irq_handler GPIO3_Combined_16_31_IRQHandler + def_irq_handler GPIO4_Combined_0_15_IRQHandler + def_irq_handler GPIO4_Combined_16_31_IRQHandler + def_irq_handler GPIO5_Combined_0_15_IRQHandler + def_irq_handler GPIO5_Combined_16_31_IRQHandler + def_irq_handler FLEXIO1_DriverIRQHandler + def_irq_handler FLEXIO2_DriverIRQHandler + def_irq_handler WDOG1_IRQHandler + def_irq_handler RTWDOG_IRQHandler + def_irq_handler EWM_IRQHandler + def_irq_handler CCM_1_IRQHandler + def_irq_handler CCM_2_IRQHandler + def_irq_handler GPC_IRQHandler + def_irq_handler SRC_IRQHandler + def_irq_handler Reserved115_IRQHandler + def_irq_handler GPT1_IRQHandler + def_irq_handler GPT2_IRQHandler + def_irq_handler PWM1_0_IRQHandler + def_irq_handler PWM1_1_IRQHandler + def_irq_handler PWM1_2_IRQHandler + def_irq_handler PWM1_3_IRQHandler + def_irq_handler PWM1_FAULT_IRQHandler + def_irq_handler FLEXSPI2_DriverIRQHandler + def_irq_handler FLEXSPI_DriverIRQHandler + def_irq_handler SEMC_IRQHandler + def_irq_handler USDHC1_DriverIRQHandler + def_irq_handler USDHC2_DriverIRQHandler + def_irq_handler USB_OTG2_IRQHandler + def_irq_handler USB_OTG1_IRQHandler + def_irq_handler ENET_DriverIRQHandler + def_irq_handler ENET_1588_Timer_DriverIRQHandler + def_irq_handler XBAR1_IRQ_0_1_IRQHandler + def_irq_handler XBAR1_IRQ_2_3_IRQHandler + def_irq_handler ADC_ETC_IRQ0_IRQHandler + def_irq_handler ADC_ETC_IRQ1_IRQHandler + def_irq_handler ADC_ETC_IRQ2_IRQHandler + def_irq_handler ADC_ETC_ERROR_IRQ_IRQHandler + def_irq_handler PIT_IRQHandler + def_irq_handler ACMP1_IRQHandler + def_irq_handler ACMP2_IRQHandler + def_irq_handler ACMP3_IRQHandler + def_irq_handler ACMP4_IRQHandler + def_irq_handler Reserved143_IRQHandler + def_irq_handler Reserved144_IRQHandler + def_irq_handler ENC1_IRQHandler + def_irq_handler ENC2_IRQHandler + def_irq_handler ENC3_IRQHandler + def_irq_handler ENC4_IRQHandler + def_irq_handler TMR1_IRQHandler + def_irq_handler TMR2_IRQHandler + def_irq_handler TMR3_IRQHandler + def_irq_handler TMR4_IRQHandler + def_irq_handler PWM2_0_IRQHandler + def_irq_handler PWM2_1_IRQHandler + def_irq_handler PWM2_2_IRQHandler + def_irq_handler PWM2_3_IRQHandler + def_irq_handler PWM2_FAULT_IRQHandler + def_irq_handler PWM3_0_IRQHandler + def_irq_handler PWM3_1_IRQHandler + def_irq_handler PWM3_2_IRQHandler + def_irq_handler PWM3_3_IRQHandler + def_irq_handler PWM3_FAULT_IRQHandler + def_irq_handler PWM4_0_IRQHandler + def_irq_handler PWM4_1_IRQHandler + def_irq_handler PWM4_2_IRQHandler + def_irq_handler PWM4_3_IRQHandler + def_irq_handler PWM4_FAULT_IRQHandler + def_irq_handler ENET2_DriverIRQHandler + def_irq_handler ENET2_1588_Timer_DriverIRQHandler + def_irq_handler CAN3_DriverIRQHandler + def_irq_handler Reserved171_IRQHandler + def_irq_handler FLEXIO3_DriverIRQHandler + def_irq_handler GPIO6_7_8_9_IRQHandler + + .end diff --git a/NXP/MIMXRT1064-EVK/app/startup/tx_initialize_low_level.S b/NXP/MIMXRT1064-EVK/app/startup/tx_initialize_low_level.S new file mode 100644 index 00000000..40e3879d --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/startup/tx_initialize_low_level.S @@ -0,0 +1,207 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 NXP i.MX RT1064 port. + **************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Initialize */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .global _tx_thread_system_stack_ptr + .global _tx_initialize_unused_memory + .global __RAM_segment_used_end__ + .global _tx_timer_interrupt + .global _vectors + .global __tx_NMIHandler // NMI + .global __tx_BadHandler // HardFault + .global __tx_SVCallHandler // SVCall + .global __tx_DBGHandler // Monitor + .global __tx_PendSVHandler // PendSV + .global __tx_SysTickHandler // SysTick + .global __tx_IntHandler // Int 0 + +SYSTICK_CYCLES_HW = ((600000000 / 100) - 1) // 5,999,999 cycles: 600 MHz on real silicon -> 100 Hz +SYSTICK_CYCLES_RENODE = ((72000000 / 100) - 1) // 719,999 cycles: 72 MHz in Renode NVIC -> 100 Hz + + .text + .align 4 + .syntax unified + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_initialize_low_level Cortex-M7/GNU */ +/* 6.4.0 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for any low-level processor */ +/* initialization, including setting up interrupt vectors, setting */ +/* up a periodic timer interrupt source, saving the system stack */ +/* pointer for use in ISR processing later, and finding the first */ +/* available RAM memory address for tx_application_define. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter ThreadX entry function */ +/* */ +/**************************************************************************/ + .global _tx_initialize_low_level + .thumb_func +_tx_initialize_low_level: + + /* Disable interrupts during ThreadX initialization. */ + CPSID i + + /* Set base of available memory to end of non-initialised RAM area. */ + LDR r0, =_tx_initialize_unused_memory // Build address of unused memory pointer + LDR r1, =__RAM_segment_used_end__ // Build first free address + ADD r1, r1, #4 // + STR r1, [r0] // Setup first unused memory pointer + + /* Setup Vector Table Offset Register. */ + MOV r0, #0xE000E000 // Build address of NVIC registers + LDR r1, =_vectors // Pickup address of vector table + STR r1, [r0, #0xD08] // Set vector table address + + /* Set system stack pointer from vector value. */ + LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer + LDR r1, =_vectors // Pickup address of vector table + LDR r1, [r1] // Pickup reset stack pointer + STR r1, [r0] // Save system stack pointer + + /* Enable the DWT cycle count register if DWT hardware is present (physical silicon). */ + LDR r1, =0xE000ED90 // MPU->TYPE register + LDR r1, [r1] + LSRS r1, r1, #8 + AND r1, r1, #0xFF // Extract DREGION field + CMP r1, #12 // Physical silicon has 16 regions, Renode has 8 + BLT .Lskip_dwt + LDR r0, =0xE0001000 // Build address of DWT register + LDR r1, [r0] // Pickup the current value + ORR r1, r1, #1 // Set the CYCCNTENA bit + STR r1, [r0] // Enable the cycle count register +.Lskip_dwt: + + /* Configure SysTick reload: detect Renode (72 MHz NVIC clock) vs physical silicon (600 MHz core clock). */ + LDR r1, =0xE000ED90 // MPU->TYPE register + LDR r1, [r1] + LSRS r1, r1, #8 + AND r1, r1, #0xFF // Extract DREGION field + CMP r1, #12 + BLT .Lrenode_systick + LDR r1, =SYSTICK_CYCLES_HW // 600 MHz clock -> reload for 100 Hz + B .Lset_systick +.Lrenode_systick: + LDR r1, =SYSTICK_CYCLES_RENODE // 72 MHz clock -> reload for 100 Hz +.Lset_systick: + MOV r0, #0xE000E000 // Build address of NVIC registers + STR r1, [r0, #0x14] // Setup SysTick Reload Value + MOV r1, #0x7 // Build SysTick Control Enable Value (CLKSOURCE|TICKINT|ENABLE) + STR r1, [r0, #0x10] // Setup SysTick Control + + /* Configure handler priorities (upper 4 bits implemented on Cortex-M7, mask 0xF0). */ + LDR r1, =0x00000000 // Rsrv, UsgF, BusF, MemM + STR r1, [r0, #0xD18] // Setup System Handlers 4-7 Priority Registers + LDR r1, =0xF0000000 // SVCl, Rsrv, Rsrv, Rsrv + STR r1, [r0, #0xD1C] // Setup System Handlers 8-11 Priority Registers + // Note: SVC must be lowest priority (0xF0 for 4-bit NVIC) + LDR r1, =0x40F00000 // SysT (0x40), PnSV (0xF0), Rsrv, DbgM + STR r1, [r0, #0xD20] // Setup System Handlers 12-15 Priority Registers + // Note: PnSV must be lowest priority (0xF0 for 4-bit NVIC) + + /* Return to caller. */ + BX lr + +/* Define shells for each of the unused vectors. */ + .global __tx_BadHandler + .thumb_func +__tx_BadHandler: + B __tx_BadHandler + +/* Catch HardFault */ + .global __tx_HardfaultHandler + .thumb_func +__tx_HardfaultHandler: + B __tx_HardfaultHandler + +/* Catch SVC */ + .global __tx_SVCallHandler + .thumb_func +__tx_SVCallHandler: + B __tx_SVCallHandler + +/* Generic interrupt handler template */ + .global __tx_IntHandler + .thumb_func +__tx_IntHandler: + PUSH {r0, lr} +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_enter // Call the ISR enter function +#endif + /* Do interrupt handler work here */ +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_exit // Call the ISR exit function +#endif + POP {r0, lr} + BX lr + +/* System Tick timer interrupt handler */ + .global __tx_SysTickHandler + .global SysTick_Handler + .thumb_func +__tx_SysTickHandler: + .thumb_func +SysTick_Handler: + PUSH {r0, lr} +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_enter // Call the ISR enter function +#endif + BL _tx_timer_interrupt +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_exit // Call the ISR exit function +#endif + POP {r0, lr} + BX lr + +/* NMI, DBG handlers */ + .global __tx_NMIHandler + .thumb_func +__tx_NMIHandler: + B __tx_NMIHandler + + .global __tx_DBGHandler + .thumb_func +__tx_DBGHandler: + B __tx_DBGHandler diff --git a/NXP/MIMXRT1064-EVK/app/syscalls.c b/NXP/MIMXRT1064-EVK/app/syscalls.c new file mode 100644 index 00000000..fa3d9e88 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/syscalls.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available + * under the terms of the MIT license which is available at + * https://opensource.org/license/mit. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 NXP i.MX RT1064 port. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +char *__env[1] = { 0 }; +char **environ = __env; + +void initialise_monitor_handles(void) +{ +} + +int _getpid(void) +{ + return 1; +} + +int _kill(int pid, int sig) +{ + (void)pid; + (void)sig; + errno = EINVAL; + return -1; +} + +void _exit(int status) +{ + _kill(status, -1); + while (1) {} +} + +int _close(int file) +{ + (void)file; + return -1; +} + +int _fstat(int file, struct stat *st) +{ + (void)file; + st->st_mode = S_IFCHR; + return 0; +} + +int _isatty(int file) +{ + (void)file; + return 1; +} + +int _lseek(int file, int ptr, int dir) +{ + (void)file; + (void)ptr; + (void)dir; + return 0; +} + +int _open(char *path, int flags, ...) +{ + (void)path; + (void)flags; + return -1; +} + +int _wait(int *status) +{ + (void)status; + errno = ECHILD; + return -1; +} + +int _unlink(char *name) +{ + (void)name; + errno = ENOENT; + return -1; +} + +int _times(struct tms *buf) +{ + (void)buf; + return -1; +} + +int _stat(char *file, struct stat *st) +{ + (void)file; + st->st_mode = S_IFCHR; + return 0; +} + +int _link(char *old, char *new) +{ + (void)old; + (void)new; + errno = EMLINK; + return -1; +} + +int _fork(void) +{ + errno = EAGAIN; + return -1; +} + +int _execve(char *name, char **argv, char **env) +{ + (void)name; + (void)argv; + (void)env; + errno = ENOMEM; + return -1; +} diff --git a/NXP/MIMXRT1064-EVK/app/sysmem.c b/NXP/MIMXRT1064-EVK/app/sysmem.c new file mode 100644 index 00000000..98235ab8 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/sysmem.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available + * under the terms of the MIT license which is available at + * https://opensource.org/license/mit. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 NXP i.MX RT1064 port. + */ + +#include +#include +#include + +/** + * Pointer to the current high watermark of the heap usage + */ +static uint8_t *__sbrk_heap_end = NULL; + +/** + * @brief _sbrk() allocates memory to the newlib heap and is used by malloc. + */ +void *_sbrk(ptrdiff_t incr) +{ + extern uint8_t _end; + extern uint8_t __StackLimit; + const uint8_t *max_heap = &__StackLimit; + uint8_t *prev_heap_end; + + /* Initialize heap end at first call */ + if (NULL == __sbrk_heap_end) + { + __sbrk_heap_end = &_end; + } + + /* Protect heap from growing into stack */ + if (__sbrk_heap_end + incr > max_heap) + { + errno = ENOMEM; + return (void *)-1; + } + + prev_heap_end = __sbrk_heap_end; + __sbrk_heap_end += incr; + + return (void *)prev_heap_end; +} diff --git a/NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h b/NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h index c9258245..b6f7d03c 100644 --- a/NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h +++ b/NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h @@ -20,7 +20,7 @@ /* System tick frequency in Hz (typically 100 or 1000) */ #ifndef TX_TIMER_TICKS_PER_SECOND -#define TX_TIMER_TICKS_PER_SECOND 1000 +#define TX_TIMER_TICKS_PER_SECOND 100 #endif #endif /* TX_USER_H */ diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc new file mode 100644 index 00000000..40c039a3 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc @@ -0,0 +1,21 @@ +:name: MIMXRT1064-EVK ThreadX Demo +:description: This script runs the Eclipse ThreadX demo on NXP i.MX RT1064-EVK. + +mach create "mimxrt1064-evk" +machine LoadPlatformDescription @platforms/boards/mimxrt1064_evk.repl + +$bin?=@$ORIGIN/../build/mimxrt1064_threadx.elf + +showAnalyzer sysbus.lpuart1 + +macro reset +""" + cpu VectorTableOffset 0x70002000 + sysbus LoadELF $bin + cpu PC `sysbus ReadDoubleWord 0x70002004` + cpu SP `sysbus ReadDoubleWord 0x70002000` +""" + +runMacro $reset + +start diff --git a/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 index 8965cb87..1a0484c0 100644 --- a/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 +++ b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 @@ -33,6 +33,8 @@ New-Item -ItemType Directory -Path $UtilitiesDir -Force | Out-Null New-Item -ItemType Directory -Path (Join-Path $ComponentsDir "uart") -Force | Out-Null New-Item -ItemType Directory -Path $BoardFilesDir -Force | Out-Null New-Item -ItemType Directory -Path $CmsisIncludeDest -Force | Out-Null +$AppStartupDir = Join-Path $BoardDir "app/startup" +New-Item -ItemType Directory -Path $AppStartupDir -Force | Out-Null if (Test-Path $TempDir) { Remove-Item -Path $TempDir -Recurse -Force } New-Item -ItemType Directory -Path $TempDir -Force | Out-Null @@ -125,6 +127,21 @@ try { Write-Host "[OK] NXP Device, Driver, Utility, and Component files copied" Write-Host "" + # Helper function to download with retries for GitHub CDN resilience + function Download-WithRetry { + param([string]$Uri, [string]$OutFile, [int]$MaxAttempts = 4) + for ($i = 1; $i -le $MaxAttempts; $i++) { + try { + Invoke-WebRequest -Uri $Uri -OutFile $OutFile -UseBasicParsing -TimeoutSec 30 + return + } + catch { + if ($i -eq $MaxAttempts) { throw $_ } + Start-Sleep -Seconds 2 + } + } + } + # 2. Download EVK-MIMXRT1064 Board Initialization Files from official NXP mcuxsdk-examples $rawBase = "https://raw.githubusercontent.com/nxp-mcuxpresso/mcuxsdk-examples/main/_boards/evkmimxrt1064" $boardFiles = @( @@ -137,16 +154,28 @@ try { @{ Remote = "$rawBase/dcd.c"; Local = "dcd.c" }, @{ Remote = "$rawBase/dcd.h"; Local = "dcd.h" }, @{ Remote = "$rawBase/xip/evkmimxrt1064_flexspi_nor_config.c"; Local = "evkmimxrt1064_flexspi_nor_config.c" }, - @{ Remote = "$rawBase/xip/evkmimxrt1064_flexspi_nor_config.h"; Local = "evkmimxrt1064_flexspi_nor_config.h" }, - @{ Remote = "$rawBase/linker/mcux/MIMXRT1064xxxxx_flexspi_nor.ld"; Local = "MIMXRT1064xxxxx_flexspi_nor.ld" } + @{ Remote = "$rawBase/xip/evkmimxrt1064_flexspi_nor_config.h"; Local = "evkmimxrt1064_flexspi_nor_config.h" } ) Write-Host "[INFO] Downloading EVK-MIMXRT1064 board support files..." foreach ($item in $boardFiles) { $dest = Join-Path $BoardFilesDir $item.Local - Invoke-WebRequest -Uri $item.Remote -OutFile $dest -UseBasicParsing + Download-WithRetry -Uri $item.Remote -OutFile $dest } - Write-Host "[OK] Board support files downloaded" + + # Download official GNU GCC Linker Script & Startup File from official NXP mcux-sdk repository + Write-Host "[INFO] Downloading official NXP GNU GCC Linker Script and Startup File..." + $nxpGccBase = "https://raw.githubusercontent.com/nxp-mcuxpresso/mcux-sdk/main/devices/MIMXRT1064/gcc" + $ldDestBoard = Join-Path $BoardFilesDir "MIMXRT1064xxxxx_flexspi_nor.ld" + $ldDestApp = Join-Path $AppStartupDir "MIMXRT1064xxxxx_flexspi_nor.ld" + $startupDest = Join-Path $AppStartupDir "startup_mimxrt1064.S" + + Download-WithRetry -Uri "$nxpGccBase/MIMXRT1064xxxxx_flexspi_nor.ld" -OutFile $ldDestBoard + Copy-Item -Path $ldDestBoard -Destination $ldDestApp -Force + + Download-WithRetry -Uri "$nxpGccBase/startup_MIMXRT1064.S" -OutFile $startupDest + + Write-Host "[OK] Board support and official GCC startup/linker files downloaded" Write-Host "" # 3. Fetch CMSIS Core headers (standard ARM CMSIS-Core include files) diff --git a/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh index 50f2c45c..f4c6b3aa 100644 --- a/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh +++ b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh @@ -22,6 +22,7 @@ UTILITIES_DIR="${LIB_DIR}/utilities" COMPONENTS_DIR="${LIB_DIR}/components" BOARD_FILES_DIR="${LIB_DIR}/board" CMSIS_INCLUDE_DEST="${LIB_DIR}/CMSIS/Include" +APP_STARTUP_DIR="${BOARD_DIR}/app/startup" TEMP_DIR="${BOARD_DIR}/temp_fetch" echo "==========================================" @@ -38,6 +39,7 @@ mkdir -p "${UTILITIES_DIR}" mkdir -p "${COMPONENTS_DIR}/uart" mkdir -p "${BOARD_FILES_DIR}" mkdir -p "${CMSIS_INCLUDE_DEST}" +mkdir -p "${APP_STARTUP_DIR}" rm -rf "${TEMP_DIR}" mkdir -p "${TEMP_DIR}" @@ -110,9 +112,15 @@ curl -fsSL "${RAW_BASE}/dcd.c" -o "${BOARD_FILES_DIR}/dcd.c" curl -fsSL "${RAW_BASE}/dcd.h" -o "${BOARD_FILES_DIR}/dcd.h" curl -fsSL "${RAW_BASE}/xip/evkmimxrt1064_flexspi_nor_config.c" -o "${BOARD_FILES_DIR}/evkmimxrt1064_flexspi_nor_config.c" curl -fsSL "${RAW_BASE}/xip/evkmimxrt1064_flexspi_nor_config.h" -o "${BOARD_FILES_DIR}/evkmimxrt1064_flexspi_nor_config.h" -curl -fsSL "${RAW_BASE}/linker/mcux/MIMXRT1064xxxxx_flexspi_nor.ld" -o "${BOARD_FILES_DIR}/MIMXRT1064xxxxx_flexspi_nor.ld" -echo "[OK] Board support files downloaded" +echo "[INFO] Downloading official NXP GNU GCC Linker Script and Startup File..." +NXP_GCC_BASE="https://raw.githubusercontent.com/nxp-mcuxpresso/mcux-sdk/main/devices/MIMXRT1064/gcc" +curl --retry 3 -fsSL "${NXP_GCC_BASE}/MIMXRT1064xxxxx_flexspi_nor.ld" -o "${BOARD_FILES_DIR}/MIMXRT1064xxxxx_flexspi_nor.ld" +cp "${BOARD_FILES_DIR}/MIMXRT1064xxxxx_flexspi_nor.ld" "${APP_STARTUP_DIR}/MIMXRT1064xxxxx_flexspi_nor.ld" + +curl --retry 3 -fsSL "${NXP_GCC_BASE}/startup_MIMXRT1064.S" -o "${APP_STARTUP_DIR}/startup_mimxrt1064.S" + +echo "[OK] Board support and official GCC startup/linker files downloaded" echo "" # 3. Fetch CMSIS Core headers diff --git a/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 b/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 new file mode 100644 index 00000000..3d2ba2ad --- /dev/null +++ b/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 @@ -0,0 +1,47 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. + +$BoardDir = Resolve-Path "$PSScriptRoot/.." +$ElfPath = Join-Path $BoardDir "build/mimxrt1064_threadx.elf" +$RescRelPath = "renode/mimxrt1064-evk.resc" +$RescFullPath = Join-Path $BoardDir $RescRelPath + +if (-not (Test-Path $ElfPath)) { + Write-Error "Binary $ElfPath not found. Please build the project first using .\scripts\build.ps1" + exit 1 +} + +# Find Renode executable +$RenodeExe = (Get-Command renode -ErrorAction SilentlyContinue).Source +if (-not $RenodeExe -and (Test-Path "C:\Program Files\Renode\renode.exe")) { + $RenodeExe = "C:\Program Files\Renode\renode.exe" +} + +if (-not $RenodeExe) { + Write-Error "Renode was not found in PATH or at 'C:\Program Files\Renode\renode.exe'." + exit 1 +} + +Write-Host "==========================================" +Write-Host "Starting Renode Simulation" +Write-Host "==========================================" +Write-Host "Renode: $RenodeExe" +Write-Host "Script: $RescFullPath" +Write-Host "Target ELF: $ElfPath" +Write-Host "" +Write-Host "Opening Renode Monitor and LPUART1 terminal analyzer..." +Write-Host "To exit Renode, type 'quit' in the Renode Monitor or close the window." +Write-Host "==========================================" + +Set-Location $BoardDir + +# Pass relative script path with quotes to avoid tokenization errors when workspace contains spaces +& $RenodeExe -e "include @`"$RescRelPath`"" diff --git a/NXP/MIMXRT1064-EVK/scripts/simulate.sh b/NXP/MIMXRT1064-EVK/scripts/simulate.sh new file mode 100644 index 00000000..f47a8a43 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/scripts/simulate.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +BOARD_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" +ELF_PATH="${BOARD_DIR}/build/mimxrt1064_threadx.elf" +RESC_REL_PATH="renode/mimxrt1064-evk.resc" + +if [ ! -f "${ELF_PATH}" ]; then + echo "[ERROR] Binary ${ELF_PATH} not found. Please build first using ./scripts/build.sh" + exit 1 +fi + +RENODE_CMD="renode" +if ! command -v renode &> /dev/null; then + if [ -f "/opt/renode/renode" ]; then + RENODE_CMD="/opt/renode/renode" + else + echo "[ERROR] Renode was not found in PATH." + exit 1 + fi +fi + +echo "==========================================" +echo "Starting Renode Simulation" +echo "==========================================" +echo "Script: ${BOARD_DIR}/${RESC_REL_PATH}" +echo "Target ELF: ${ELF_PATH}" +echo "" + +cd "${BOARD_DIR}" +"${RENODE_CMD}" -e "include @\"${RESC_REL_PATH}\"" From fb3237ff8ef37d2bc34333069e6b7dc5de230c8a Mon Sep 17 00:00:00 2001 From: Ali Eissa Date: Thu, 10 Sep 2026 07:04:42 +0400 Subject: [PATCH 03/13] fetch sdk bug fixes --- .../app/startup/MIMXRT1064xxxxx_flexspi_nor.ld | 3 +-- NXP/MIMXRT1064-EVK/app/startup/startup_mimxrt1064.S | 12 ++++-------- NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 | 13 +++++-------- NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh | 8 +++----- 4 files changed, 13 insertions(+), 23 deletions(-) diff --git a/NXP/MIMXRT1064-EVK/app/startup/MIMXRT1064xxxxx_flexspi_nor.ld b/NXP/MIMXRT1064-EVK/app/startup/MIMXRT1064xxxxx_flexspi_nor.ld index e5dd1d68..8e79f28c 100644 --- a/NXP/MIMXRT1064-EVK/app/startup/MIMXRT1064xxxxx_flexspi_nor.ld +++ b/NXP/MIMXRT1064-EVK/app/startup/MIMXRT1064xxxxx_flexspi_nor.ld @@ -255,7 +255,7 @@ SECTIONS . += HEAP_SIZE; __HeapLimit = .; __heap_limit = .; /* Add for _sbrk */ - __RAM_segment_used_end__ = .; /* Used by ThreadX for first unused memory */ + __RAM_segment_used_end__ = .; } > m_data .stack : @@ -268,7 +268,6 @@ SECTIONS __StackTop = ORIGIN(m_data) + LENGTH(m_data); __StackLimit = __StackTop - STACK_SIZE; PROVIDE(__stack = __StackTop); - PROVIDE(_estack = __StackTop); .ARM.attributes 0 : { *(.ARM.attributes) } diff --git a/NXP/MIMXRT1064-EVK/app/startup/startup_mimxrt1064.S b/NXP/MIMXRT1064-EVK/app/startup/startup_mimxrt1064.S index a2137e4f..95442231 100644 --- a/NXP/MIMXRT1064-EVK/app/startup/startup_mimxrt1064.S +++ b/NXP/MIMXRT1064-EVK/app/startup/startup_mimxrt1064.S @@ -19,14 +19,14 @@ .section .isr_vector, "a" .align 2 .globl __isr_vector - .globl __VECTOR_TABLE - .globl __Vectors .globl _vectors + .globl __Vectors + .globl __VECTOR_TABLE .globl g_pfnVectors __isr_vector: -__VECTOR_TABLE: -__Vectors: _vectors: +__Vectors: +__VECTOR_TABLE: g_pfnVectors: .long __StackTop /* Top of Stack */ .long Reset_Handler /* Reset Handler */ @@ -406,10 +406,6 @@ Reset_Handler: blt .LC4 #endif /* __STARTUP_INITIALIZE_NONCACHEDATA */ -#ifndef __STARTUP_CLEAR_BSS -#define __STARTUP_CLEAR_BSS -#endif - #ifdef __STARTUP_CLEAR_BSS /* This part of work usually is done in C library startup code. Otherwise, * define this macro to enable it in this startup. diff --git a/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 index 1a0484c0..420f7ef9 100644 --- a/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 +++ b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 @@ -163,19 +163,16 @@ try { Download-WithRetry -Uri $item.Remote -OutFile $dest } - # Download official GNU GCC Linker Script & Startup File from official NXP mcux-sdk repository - Write-Host "[INFO] Downloading official NXP GNU GCC Linker Script and Startup File..." + # Download official GNU GCC Linker Script & Startup File for reference in lib/mcux-sdk/board/ + Write-Host "[INFO] Downloading official NXP GNU GCC Linker Script and Startup File into board directory..." $nxpGccBase = "https://raw.githubusercontent.com/nxp-mcuxpresso/mcux-sdk/main/devices/MIMXRT1064/gcc" $ldDestBoard = Join-Path $BoardFilesDir "MIMXRT1064xxxxx_flexspi_nor.ld" - $ldDestApp = Join-Path $AppStartupDir "MIMXRT1064xxxxx_flexspi_nor.ld" - $startupDest = Join-Path $AppStartupDir "startup_mimxrt1064.S" + $startupDestBoard = Join-Path $BoardFilesDir "startup_MIMXRT1064.S" Download-WithRetry -Uri "$nxpGccBase/MIMXRT1064xxxxx_flexspi_nor.ld" -OutFile $ldDestBoard - Copy-Item -Path $ldDestBoard -Destination $ldDestApp -Force + Download-WithRetry -Uri "$nxpGccBase/startup_MIMXRT1064.S" -OutFile $startupDestBoard - Download-WithRetry -Uri "$nxpGccBase/startup_MIMXRT1064.S" -OutFile $startupDest - - Write-Host "[OK] Board support and official GCC startup/linker files downloaded" + Write-Host "[OK] Board support and official GCC reference files downloaded" Write-Host "" # 3. Fetch CMSIS Core headers (standard ARM CMSIS-Core include files) diff --git a/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh index f4c6b3aa..b0a6e439 100644 --- a/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh +++ b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh @@ -113,14 +113,12 @@ curl -fsSL "${RAW_BASE}/dcd.h" -o "${BOARD_FILES_DIR}/dcd.h" curl -fsSL "${RAW_BASE}/xip/evkmimxrt1064_flexspi_nor_config.c" -o "${BOARD_FILES_DIR}/evkmimxrt1064_flexspi_nor_config.c" curl -fsSL "${RAW_BASE}/xip/evkmimxrt1064_flexspi_nor_config.h" -o "${BOARD_FILES_DIR}/evkmimxrt1064_flexspi_nor_config.h" -echo "[INFO] Downloading official NXP GNU GCC Linker Script and Startup File..." +echo "[INFO] Downloading official NXP GNU GCC Linker Script and Startup File into board directory..." NXP_GCC_BASE="https://raw.githubusercontent.com/nxp-mcuxpresso/mcux-sdk/main/devices/MIMXRT1064/gcc" curl --retry 3 -fsSL "${NXP_GCC_BASE}/MIMXRT1064xxxxx_flexspi_nor.ld" -o "${BOARD_FILES_DIR}/MIMXRT1064xxxxx_flexspi_nor.ld" -cp "${BOARD_FILES_DIR}/MIMXRT1064xxxxx_flexspi_nor.ld" "${APP_STARTUP_DIR}/MIMXRT1064xxxxx_flexspi_nor.ld" +curl --retry 3 -fsSL "${NXP_GCC_BASE}/startup_MIMXRT1064.S" -o "${BOARD_FILES_DIR}/startup_MIMXRT1064.S" -curl --retry 3 -fsSL "${NXP_GCC_BASE}/startup_MIMXRT1064.S" -o "${APP_STARTUP_DIR}/startup_mimxrt1064.S" - -echo "[OK] Board support and official GCC startup/linker files downloaded" +echo "[OK] Board support and official GCC reference files downloaded" echo "" # 3. Fetch CMSIS Core headers From 6ae0694b0b5d0247627f0149cd7a9199e744405d Mon Sep 17 00:00:00 2001 From: Ali Eissa Date: Thu, 10 Sep 2026 08:01:45 +0400 Subject: [PATCH 04/13] NXP i.MX RT1064-EVK: GPIO & Peripheral Indicator Demo --- NXP/MIMXRT1064-EVK/README.md | 33 +++++++++++++++-- NXP/MIMXRT1064-EVK/app/board_init.c | 20 +++++++++-- NXP/MIMXRT1064-EVK/app/main.c | 9 +++-- NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl | 35 +++++++++++++++++++ NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc | 6 ++-- 5 files changed, 94 insertions(+), 9 deletions(-) create mode 100644 NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl diff --git a/NXP/MIMXRT1064-EVK/README.md b/NXP/MIMXRT1064-EVK/README.md index c972249e..e625089f 100644 --- a/NXP/MIMXRT1064-EVK/README.md +++ b/NXP/MIMXRT1064-EVK/README.md @@ -13,7 +13,8 @@ The project is designed to run seamlessly both in the **Antmicro Renode** simula * **Flash Memory**: 4 MB internal FlexSPI NOR Flash (XIP) * **Internal SRAM**: 1 MB on-chip RAM (Configurable as ITCM, DTCM, and OCRAM) * **Debug Serial Console**: LPUART1 (115,200 baud, 8N1) -* **User LED**: GPIO9 Pin 3 (`GPIO_AD_B0_09`) / User LED (Green) +* **User LED**: GPIO1 Pin 9 (`GPIO_AD_B0_09`) / User LED D18 (Green) +* **User Button**: GPIO5 Pin 0 (SW8 WAKEUP button) * **Virtual Networking**: ENET1 (10/100M Fast Ethernet MAC via KSZ8081 PHY) --- @@ -25,17 +26,30 @@ NXP/MIMXRT1064-EVK/ ├── CMakeLists.txt # Top-level CMake build configuration ├── NOTICE.md # Third-party licensing notices (NXP BSD-3 & CMSIS) ├── README.md # This documentation file +├── app/ +│ ├── main.c # ThreadX application entry, Heartbeat & Worker threads +│ ├── board_init.c / .h # Clocks (600 MHz), MPU, pin muxing & User LED init +│ ├── console.c / .h # LPUART1 serial driver & POSIX printf retargeting +│ ├── syscalls.c / sysmem.c # Minimal C runtime system call stubs +│ └── startup/ +│ ├── startup_mimxrt1064.S # NXP vector table & reset handler +│ ├── tx_initialize_low_level.S # ThreadX Cortex-M7 low-level init & SysTick +│ └── MIMXRT1064xxxxx_flexspi_nor.ld # FlexSPI NOR XIP GNU linker script ├── cmake/ │ ├── arm-gcc-cortex-m7.cmake # CPU architecture and FPU definitions │ ├── arm-gcc-cortex-toolchain.cmake # GNU toolchain discovery and compiler flags │ └── utilities.cmake # Elf-to-bin/hex conversion and linker macros ├── lib/ │ ├── threadx/ -│ │ └── tx_user.h # ThreadX configuration (hardware FPU enabled) +│ │ └── tx_user.h # ThreadX configuration (hardware FPU enabled, 100 Hz tick) │ └── mcux-sdk/ # Official NXP SDK drivers (fetched via script) +├── renode/ +│ ├── mimxrt1064-evk.repl # Board platform description (memory, LED, button) +│ └── mimxrt1064-evk.resc # Renode simulation script (LPUART1 analyzer & LED logging) └── scripts/ ├── fetch_sdk.ps1 / .sh # Download official NXP drivers, device headers & CMSIS - └── build.ps1 / .sh # One-command build script with Ninja/CMake + ├── build.ps1 / .sh # One-command build script with Ninja/CMake + └── simulate.ps1 / .sh # Launch Renode simulation with serial monitor ``` --- @@ -80,6 +94,19 @@ Compile the application, vendor drivers, and Eclipse ThreadX kernel: ./scripts/build.sh --rebuild ``` +### 3. Run the Simulation in Renode +Launch the interactive Renode simulation: + +* **On Windows (PowerShell)**: + ```powershell + .\scripts\simulate.ps1 + ``` +* **On Linux / macOS (Bash)**: + ```bash + chmod +x ./scripts/simulate.sh + ./scripts/simulate.sh + ``` + --- ## Hardware Verification Status diff --git a/NXP/MIMXRT1064-EVK/app/board_init.c b/NXP/MIMXRT1064-EVK/app/board_init.c index 9586e39c..472a3c9b 100644 --- a/NXP/MIMXRT1064-EVK/app/board_init.c +++ b/NXP/MIMXRT1064-EVK/app/board_init.c @@ -13,6 +13,8 @@ #include "board_init.h" #include "console.h" +#include "fsl_iomuxc.h" +#include "fsl_gpio.h" void board_init(void) { @@ -25,9 +27,23 @@ void board_init(void) /* 2. Configure Pin Muxing (UART1 TX/RX pins) */ BOARD_InitPins(); - /* 3. Configure System Clocks (600 MHz AHB core clock) */ + /* 3. Configure User LED Pin Muxing (GPIO_AD_B0_09 -> GPIO1_IO09) */ + CLOCK_EnableClock(kCLOCK_Iomuxc); + IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, 0U); + IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, 0x10B0u); + + /* 4. Configure System Clocks (600 MHz AHB core clock) */ BOARD_BootClockRUN(); - /* 4. Initialize LPUART1 Serial Console at 115200 baud */ + /* 5. Initialize User LED GPIO (GPIO1 Pin 9, output, initial state OFF) */ + gpio_pin_config_t led_config = { + kGPIO_DigitalOutput, + 0, + kGPIO_NoIntmode + }; + GPIO_PinInit(BOARD_USER_LED_GPIO, BOARD_USER_LED_GPIO_PIN, &led_config); + USER_LED_OFF(); + + /* 6. Initialize LPUART1 Serial Console at 115200 baud */ console_init(); } diff --git a/NXP/MIMXRT1064-EVK/app/main.c b/NXP/MIMXRT1064-EVK/app/main.c index c3807225..b313f404 100644 --- a/NXP/MIMXRT1064-EVK/app/main.c +++ b/NXP/MIMXRT1064-EVK/app/main.c @@ -112,6 +112,7 @@ static void heartbeat_thread_entry(ULONG thread_input) { (void)thread_input; ULONG count = 0; + uint8_t led_state = 0; printf("[Heartbeat Thread] Started.\r\n"); @@ -121,8 +122,12 @@ static void heartbeat_thread_entry(ULONG thread_input) tx_thread_sleep(50); count++; - printf("[Heartbeat Thread] Heartbeat #%lu (System Tick: %lu)\r\n", - count, tx_time_get()); + /* Toggle User LED (D18) on GPIO1 Pin 9 */ + USER_LED_TOGGLE(); + led_state = !led_state; + + printf("[Heartbeat Thread] Heartbeat #%lu (System Tick: %lu | User LED: %s)\r\n", + count, tx_time_get(), led_state ? "ON" : "OFF"); } } diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl new file mode 100644 index 00000000..c15a32ae --- /dev/null +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl @@ -0,0 +1,35 @@ +// Copyright (c) 2026 Eclipse ThreadX contributors +// +// This program and the accompanying materials are made available +// under the terms of the MIT license which is available at +// https://opensource.org/license/mit. +// +// SPDX-License-Identifier: MIT +// +// Platform description for NXP i.MX RT1064-EVK (Simulated in Renode). + +using "platforms/cpus/imxrt1064.repl" + +// External SDRAM (32 MB @ 0x80000000) +sdram0: Memory.MappedMemory @ sysbus 0x80000000 + size: 0x2000000 + +// External/On-chip FlexSPI NOR Flash (4 MB @ 0x70000000) +flash_mem: Memory.MappedMemory @ sysbus 0x70000000 + size: 0x400000 + +// User Button SW8 (WAKEUP, active low, connected to GPIO5 Pin 0) +user_button: Miscellaneous.Button @ gpio5 + invert: true + -> gpio5@0 + +// User LED D18 (Green, active low, connected to GPIO1 Pin 9) +user_led: Miscellaneous.LED @ gpio1 9 + invert: true + +// On-chip ADCs +adc1: + referenceVoltage: 3.3 + +adc2: + referenceVoltage: 3.3 diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc index 40c039a3..ba8f9226 100644 --- a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc @@ -2,9 +2,11 @@ :description: This script runs the Eclipse ThreadX demo on NXP i.MX RT1064-EVK. mach create "mimxrt1064-evk" -machine LoadPlatformDescription @platforms/boards/mimxrt1064_evk.repl -$bin?=@$ORIGIN/../build/mimxrt1064_threadx.elf +$platform?=$ORIGIN/mimxrt1064-evk.repl +machine LoadPlatformDescription $platform + +$bin?=$ORIGIN/../build/mimxrt1064_threadx.elf showAnalyzer sysbus.lpuart1 From ad1e11b97f625fc9a5489740e49b22ee6e3442b2 Mon Sep 17 00:00:00 2001 From: Ali Eissa Date: Sat, 12 Sep 2026 22:27:36 +0400 Subject: [PATCH 05/13] small bug fix: renode user_led return value --- NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl index c15a32ae..81b1f8cd 100644 --- a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl @@ -24,6 +24,9 @@ user_button: Miscellaneous.Button @ gpio5 -> gpio5@0 // User LED D18 (Green, active low, connected to GPIO1 Pin 9) +gpio1: + 9 -> user_led@0 + user_led: Miscellaneous.LED @ gpio1 9 invert: true From b5978ee07e788da3b46fa233a588ce62a3a5a4be Mon Sep 17 00:00:00 2001 From: Ali Eissa Date: Sun, 13 Sep 2026 06:41:46 +0400 Subject: [PATCH 06/13] NXP i.MX RT1064-EVK: NetX Duo Virtual Ethernet Networking & Echo Demo --- NXP/MIMXRT1064-EVK/CMakeLists.txt | 164 +++++++-- NXP/MIMXRT1064-EVK/app/MIMXRT1062.h | 20 ++ NXP/MIMXRT1064-EVK/app/ansi_colors.h | 46 +++ NXP/MIMXRT1064-EVK/app/board_init.c | 5 +- NXP/MIMXRT1064-EVK/app/board_init.h | 2 +- NXP/MIMXRT1064-EVK/app/console.c | 2 +- NXP/MIMXRT1064-EVK/app/console.h | 2 +- .../app/demos/netx_echo/CMakeLists.txt | 108 ++++++ .../app/demos/netx_echo/client_main.c | 319 ++++++++++++++++++ NXP/MIMXRT1064-EVK/app/demos/netx_echo/main.c | 306 +++++++++++++++++ .../app/demos/netx_echo/nx_user.h | 21 ++ .../app/demos/netx_echo/test_echo.ps1 | 131 +++++++ .../app/demos/netx_echo/test_echo.sh | 97 ++++++ .../app/demos/threadx_basic/CMakeLists.txt | 55 +++ .../app/{ => demos/threadx_basic}/main.c | 0 NXP/MIMXRT1064-EVK/app/syscalls.c | 2 +- NXP/MIMXRT1064-EVK/app/sysmem.c | 2 +- NXP/MIMXRT1064-EVK/cmake/utilities.cmake | 4 +- NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl | 11 + NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc | 13 +- .../renode/mimxrt1064-network-multinode.resc | 51 +++ NXP/MIMXRT1064-EVK/scripts/build.ps1 | 53 +-- NXP/MIMXRT1064-EVK/scripts/build.sh | 45 ++- NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 | 50 ++- NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh | 36 +- NXP/MIMXRT1064-EVK/scripts/simulate.ps1 | 34 +- NXP/MIMXRT1064-EVK/scripts/simulate.sh | 25 +- 27 files changed, 1505 insertions(+), 99 deletions(-) create mode 100644 NXP/MIMXRT1064-EVK/app/MIMXRT1062.h create mode 100644 NXP/MIMXRT1064-EVK/app/ansi_colors.h create mode 100644 NXP/MIMXRT1064-EVK/app/demos/netx_echo/CMakeLists.txt create mode 100644 NXP/MIMXRT1064-EVK/app/demos/netx_echo/client_main.c create mode 100644 NXP/MIMXRT1064-EVK/app/demos/netx_echo/main.c create mode 100644 NXP/MIMXRT1064-EVK/app/demos/netx_echo/nx_user.h create mode 100644 NXP/MIMXRT1064-EVK/app/demos/netx_echo/test_echo.ps1 create mode 100644 NXP/MIMXRT1064-EVK/app/demos/netx_echo/test_echo.sh create mode 100644 NXP/MIMXRT1064-EVK/app/demos/threadx_basic/CMakeLists.txt rename NXP/MIMXRT1064-EVK/app/{ => demos/threadx_basic}/main.c (100%) create mode 100644 NXP/MIMXRT1064-EVK/renode/mimxrt1064-network-multinode.resc diff --git a/NXP/MIMXRT1064-EVK/CMakeLists.txt b/NXP/MIMXRT1064-EVK/CMakeLists.txt index 69036528..46546835 100644 --- a/NXP/MIMXRT1064-EVK/CMakeLists.txt +++ b/NXP/MIMXRT1064-EVK/CMakeLists.txt @@ -9,8 +9,9 @@ # Contributors: # Ali Eissa - 2026 version. -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) +cmake_minimum_required(VERSION 3.10 FATAL_ERROR) set(CMAKE_C_STANDARD 99) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Set the toolchain if not defined if(NOT CMAKE_TOOLCHAIN_FILE) @@ -24,9 +25,11 @@ include(utilities) # Define the Project project(mimxrt1064_threadx C CXX ASM) -# Define ThreadX User Configurations -set(TX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/lib/threadx/tx_user.h" CACHE STRING "Enable TX user configuration") -set(TX_USER_FILE_DIR "${CMAKE_CURRENT_LIST_DIR}/lib/threadx") +# Ensure executable output (elf, bin, hex) goes directly to the top-level build directory +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") + +# Select the active demo to build (default: netx_echo, or threadx_basic) +set(ACTIVE_DEMO "netx_echo" CACHE STRING "Active demo name to build: netx_echo, threadx_basic") # Set up paths for MCUXpresso SDK set(SDK_DIR "${CMAKE_CURRENT_LIST_DIR}/lib/mcux-sdk") @@ -34,6 +37,35 @@ if(NOT EXISTS "${SDK_DIR}/devices/MIMXRT1064/MIMXRT1064.h") message(FATAL_ERROR "NXP SDK dependencies missing! Please run 'scripts/fetch_sdk.ps1' or 'scripts/fetch_sdk.sh' first.") endif() +# Dynamic Middleware Auto-Detection +# Check if the active demo uses NetX Duo by looking for nx_user.h +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/nx_user.h") + set(USE_NETXDUO ON) + set(NX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/nx_user.h" CACHE STRING "Enable NetX Duo user configuration" FORCE) +else() + set(USE_NETXDUO OFF) +endif() + +# Check if the active demo has custom tx_user.h; otherwise fallback to lib/threadx/tx_user.h +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/tx_user.h") + set(TX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/tx_user.h" CACHE STRING "Enable TX user configuration" FORCE) + set(TX_USER_FILE_DIR "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}") +else() + set(TX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/lib/threadx/tx_user.h" CACHE STRING "Enable TX user configuration" FORCE) + set(TX_USER_FILE_DIR "${CMAKE_CURRENT_LIST_DIR}/lib/threadx") +endif() + +# Compile ThreadX Kernel from root shared libs submodule +set(THREADX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../libs/threadx") +add_subdirectory(${THREADX_DIR} threadx) + +if(USE_NETXDUO) + # Compile NetX Duo TCP/IP Stack from root shared libs submodule + set(NXD_ENABLE_FILE_SERVERS OFF CACHE BOOL "Disable FileX dependency in NetX Duo" FORCE) + set(NETXDUO_DIR "${CMAKE_CURRENT_LIST_DIR}/../../libs/netxduo") + add_subdirectory(${NETXDUO_DIR} netxduo) +endif() + # Compile the NXP MCUXpresso Driver & Board Library as an Object Library set(SDK_TARGET mcux_sdk) @@ -65,6 +97,7 @@ target_compile_definitions(${SDK_TARGET} FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE=1 SDK_DEBUGCONSOLE=1 SKIP_SYSCLK_INIT=1 + __STARTUP_INITIALIZE_NONCACHEDATA=1 ) target_include_directories(${SDK_TARGET} @@ -79,26 +112,18 @@ target_include_directories(${SDK_TARGET} ${TX_USER_FILE_DIR} ) -# Compile ThreadX Kernel from root shared libs submodule -set(THREADX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../libs/threadx") -add_subdirectory(${THREADX_DIR} threadx) - -# Create the Main Executable -set(EXE_TARGET mimxrt1064_threadx) - -add_executable(${EXE_TARGET} +# 1. Define Board BSP object library +add_library(board_bsp OBJECT app/startup/startup_mimxrt1064.S app/startup/tx_initialize_low_level.S app/board_init.c app/console.c - app/main.c app/sysmem.c app/syscalls.c ) -# Set compile definitions for our executable -target_compile_definitions(${EXE_TARGET} - PRIVATE +target_compile_definitions(board_bsp + PUBLIC CPU_MIMXRT1064DVL6A XIP_EXTERNAL_FLASH=1 XIP_BOOT_HEADER_ENABLE=1 @@ -106,11 +131,11 @@ target_compile_definitions(${EXE_TARGET} FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE=1 SDK_DEBUGCONSOLE=1 SKIP_SYSCLK_INIT=1 + __STARTUP_INITIALIZE_NONCACHEDATA=1 ) -# Include paths -target_include_directories(${EXE_TARGET} - PRIVATE +target_include_directories(board_bsp + PUBLIC ${CMAKE_CURRENT_LIST_DIR}/app ${SDK_DIR}/CMSIS/Include ${SDK_DIR}/devices/MIMXRT1064 @@ -121,16 +146,99 @@ target_include_directories(${EXE_TARGET} ${TX_USER_FILE_DIR} ) -# Link libraries (includes ThreadX kernel and MCUXpresso SDK object libraries) -target_link_libraries(${EXE_TARGET} - PRIVATE - threadx +target_link_libraries(board_bsp + PUBLIC mcux_sdk + threadx ) -# Apply GCC linker script and print memory usage (utilities.cmake function) -set_target_linker(${EXE_TARGET} "${CMAKE_CURRENT_LIST_DIR}/app/startup/MIMXRT1064xxxxx_flexspi_nor.ld") - -# Post-build commands to generate raw .bin and .hex files -post_build(${EXE_TARGET}) +# 2. Define conditional NetX Duo driver library target +if(USE_NETXDUO) + add_library(netx_imxrt_driver OBJECT + ${SDK_DIR}/drivers/netx_driver/nx_driver_imxrt1062.c + ${SDK_DIR}/drivers/netx_driver/gnu/nx_driver_imxrt1062_low_level.S + ${SDK_DIR}/components/phy/fsl_phy.c + ${SDK_DIR}/drivers/fsl_enet.c + ) + + target_compile_definitions(netx_imxrt_driver + PUBLIC + CPU_MIMXRT1064DVL6A + XIP_EXTERNAL_FLASH=1 + XIP_BOOT_HEADER_ENABLE=1 + XIP_BOOT_HEADER_DCD_ENABLE=1 + FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE=1 + SDK_DEBUGCONSOLE=1 + SKIP_SYSCLK_INIT=1 + __STARTUP_INITIALIZE_NONCACHEDATA=1 + ) + + target_include_directories(netx_imxrt_driver + PUBLIC + ${SDK_DIR}/drivers/netx_driver + ${SDK_DIR}/components/phy + ${CMAKE_CURRENT_LIST_DIR}/app + ${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO} + ${SDK_DIR}/CMSIS/Include + ${SDK_DIR}/devices/MIMXRT1064 + ${SDK_DIR}/drivers + ${SDK_DIR}/board + ${SDK_DIR}/utilities + ${SDK_DIR}/components/uart + ${TX_USER_FILE_DIR} + ) + + target_link_libraries(netx_imxrt_driver + PUBLIC + netxduo + threadx + mcux_sdk + ) + target_compile_options(netx_imxrt_driver PRIVATE -Wno-unused-variable) + + add_library(netx_imxrt_driver_client OBJECT + ${SDK_DIR}/drivers/netx_driver/nx_driver_imxrt1062.c + ${SDK_DIR}/drivers/netx_driver/gnu/nx_driver_imxrt1062_low_level.S + ${SDK_DIR}/components/phy/fsl_phy.c + ${SDK_DIR}/drivers/fsl_enet.c + ) + + target_compile_definitions(netx_imxrt_driver_client + PUBLIC + NETX_CLIENT_NODE=1 + CPU_MIMXRT1064DVL6A + XIP_EXTERNAL_FLASH=1 + XIP_BOOT_HEADER_ENABLE=1 + XIP_BOOT_HEADER_DCD_ENABLE=1 + FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE=1 + SDK_DEBUGCONSOLE=1 + SKIP_SYSCLK_INIT=1 + __STARTUP_INITIALIZE_NONCACHEDATA=1 + ) + + target_include_directories(netx_imxrt_driver_client + PUBLIC + ${SDK_DIR}/drivers/netx_driver + ${SDK_DIR}/components/phy + ${CMAKE_CURRENT_LIST_DIR}/app + ${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO} + ${SDK_DIR}/CMSIS/Include + ${SDK_DIR}/devices/MIMXRT1064 + ${SDK_DIR}/drivers + ${SDK_DIR}/board + ${SDK_DIR}/utilities + ${SDK_DIR}/components/uart + ${TX_USER_FILE_DIR} + ) + + target_link_libraries(netx_imxrt_driver_client + PUBLIC + netxduo + threadx + mcux_sdk + ) + target_compile_options(netx_imxrt_driver_client PRIVATE -Wno-unused-variable) +endif() +# 3. Add the active demo subdirectory to build the executable target +add_subdirectory(app/demos/${ACTIVE_DEMO}) diff --git a/NXP/MIMXRT1064-EVK/app/MIMXRT1062.h b/NXP/MIMXRT1064-EVK/app/MIMXRT1062.h new file mode 100644 index 00000000..5c20680c --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/MIMXRT1062.h @@ -0,0 +1,20 @@ +/* + * Compatibility header: redirects MIMXRT1062.h from stock NetX Duo driver + * to MIMXRT1064 device registers without modifying vendor source files. + */ +#ifndef _MIMXRT1062_H_ +#define _MIMXRT1062_H_ + +#include "fsl_device_registers.h" + +/* + * Assign distinct MAC addresses to server and client nodes + * to prevent address collision on the Renode virtual switch. + */ +#if defined(NETX_CLIENT_NODE) +#define NX_DRIVER_ETHERNET_MAC {0x02, 0x11, 0x22, 0x33, 0x44, 0x53} +#else +#define NX_DRIVER_ETHERNET_MAC {0x02, 0x11, 0x22, 0x33, 0x44, 0x52} +#endif + +#endif /* _MIMXRT1062_H_ */ diff --git a/NXP/MIMXRT1064-EVK/app/ansi_colors.h b/NXP/MIMXRT1064-EVK/app/ansi_colors.h new file mode 100644 index 00000000..5b448d0c --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/ansi_colors.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available + * under the terms of the MIT license which is available at + * https://opensource.org/license/mit. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#ifndef ANSI_COLORS_H +#define ANSI_COLORS_H + +/* ANSI Terminal Escape Codes for Colored Serial Output */ +#define ANSI_RESET "\x1b[0m" +#define ANSI_BOLD "\x1b[1m" + +/* Standard Primary Colors for Banners */ +#define ANSI_RED "\x1b[31m" +#define ANSI_GREEN "\x1b[32m" +#define ANSI_YELLOW "\x1b[33m" +#define ANSI_BLUE "\x1b[34m" +#define ANSI_MAGENTA "\x1b[35m" +#define ANSI_CYAN "\x1b[36m" +#define ANSI_WHITE "\x1b[37m" + +/* Subsystem Tags: Muted Slate Gray (256-color 243) */ +#define TAG_SYSTEM "\x1b[38;5;243m[System]" +#define TAG_HAL "\x1b[38;5;243m[HAL]" +#define TAG_NETWORK "\x1b[38;5;243m[NetX]" +#define TAG_NET_THREAD "\x1b[38;5;243m[Network Thread]" +#define TAG_ECHO "\x1b[38;5;243m[Echo]" +#define TAG_SERVER "\x1b[38;5;243m[Server]" +#define TAG_CLIENT "\x1b[38;5;243m[Client]" + +/* Message Colors: Soft, pastel feedback colors */ +#define MSG_INFO "\x1b[38;5;250m" /* Soft White/Gray for normal logs */ +#define MSG_SUCCESS "\x1b[38;5;114m" /* Soft Pastel Green for success */ +#define MSG_WARNING "\x1b[38;5;215m" /* Muted Gold/Orange for warnings */ +#define MSG_ERROR "\x1b[38;5;203m" /* Muted Coral/Red for failures */ +#define MSG_METRIC "\x1b[38;5;111m" /* Soft Sky Blue for data/measurements */ + +#endif /* ANSI_COLORS_H */ diff --git a/NXP/MIMXRT1064-EVK/app/board_init.c b/NXP/MIMXRT1064-EVK/app/board_init.c index 472a3c9b..0517fb0b 100644 --- a/NXP/MIMXRT1064-EVK/app/board_init.c +++ b/NXP/MIMXRT1064-EVK/app/board_init.c @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT * * Contributors: - * Ali Eissa - 2026 NXP i.MX RT1064 port. + * Ali Eissa - 2026 version. */ #include "board_init.h" @@ -46,4 +46,7 @@ void board_init(void) /* 6. Initialize LPUART1 Serial Console at 115200 baud */ console_init(); + + /* 7. Configure Ethernet Pin Muxing (RMII and MDC/MDIO) */ + BOARD_InitENET(); } diff --git a/NXP/MIMXRT1064-EVK/app/board_init.h b/NXP/MIMXRT1064-EVK/app/board_init.h index 3080890b..c87f7a40 100644 --- a/NXP/MIMXRT1064-EVK/app/board_init.h +++ b/NXP/MIMXRT1064-EVK/app/board_init.h @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT * * Contributors: - * Ali Eissa - 2026 NXP i.MX RT1064 port. + * Ali Eissa - 2026 version. */ #ifndef BOARD_INIT_H diff --git a/NXP/MIMXRT1064-EVK/app/console.c b/NXP/MIMXRT1064-EVK/app/console.c index 9c95756f..5befef29 100644 --- a/NXP/MIMXRT1064-EVK/app/console.c +++ b/NXP/MIMXRT1064-EVK/app/console.c @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT * * Contributors: - * Ali Eissa - 2026 NXP i.MX RT1064 port. + * Ali Eissa - 2026 version. */ #include "console.h" diff --git a/NXP/MIMXRT1064-EVK/app/console.h b/NXP/MIMXRT1064-EVK/app/console.h index 89140a90..3907e183 100644 --- a/NXP/MIMXRT1064-EVK/app/console.h +++ b/NXP/MIMXRT1064-EVK/app/console.h @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT * * Contributors: - * Ali Eissa - 2026 NXP i.MX RT1064 port. + * Ali Eissa - 2026 version. */ #ifndef CONSOLE_H diff --git a/NXP/MIMXRT1064-EVK/app/demos/netx_echo/CMakeLists.txt b/NXP/MIMXRT1064-EVK/app/demos/netx_echo/CMakeLists.txt new file mode 100644 index 00000000..a3a4ec5c --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/demos/netx_echo/CMakeLists.txt @@ -0,0 +1,108 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. + +# Server Executable Target (mimxrt1064_threadx) +add_executable(${PROJECT_NAME} + main.c +) + +# Set compile definitions for server +target_compile_definitions(${PROJECT_NAME} + PRIVATE + CPU_MIMXRT1064DVL6A + XIP_EXTERNAL_FLASH=1 + XIP_BOOT_HEADER_ENABLE=1 + XIP_BOOT_HEADER_DCD_ENABLE=1 + FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE=1 + SDK_DEBUGCONSOLE=1 + SKIP_SYSCLK_INIT=1 + __STARTUP_INITIALIZE_NONCACHEDATA=1 +) + +# Include paths for server +target_include_directories(${PROJECT_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../.. + ${SDK_DIR}/drivers/netx_driver + ${SDK_DIR}/CMSIS/Include + ${SDK_DIR}/devices/MIMXRT1064 + ${SDK_DIR}/drivers + ${SDK_DIR}/board + ${SDK_DIR}/utilities + ${SDK_DIR}/components/uart + ${SDK_DIR}/components/phy + ${TX_USER_FILE_DIR} +) + +# Link libraries for server +target_link_libraries(${PROJECT_NAME} + PRIVATE + board_bsp + threadx + netxduo + netx_imxrt_driver + mcux_sdk +) + +# Apply GCC linker script and post-build outputs for server +set_target_linker(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/MIMXRT1064xxxxx_flexspi_nor.ld") +post_build(${PROJECT_NAME}) + +# Automated Verification Client Executable Target (mimxrt1064_client) +set(CLIENT_TARGET "mimxrt1064_client") +add_executable(${CLIENT_TARGET} + client_main.c +) + +# Set compile definitions for client +target_compile_definitions(${CLIENT_TARGET} + PRIVATE + NETX_CLIENT_NODE=1 + CPU_MIMXRT1064DVL6A + XIP_EXTERNAL_FLASH=1 + XIP_BOOT_HEADER_ENABLE=1 + XIP_BOOT_HEADER_DCD_ENABLE=1 + FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE=1 + SDK_DEBUGCONSOLE=1 + SKIP_SYSCLK_INIT=1 + __STARTUP_INITIALIZE_NONCACHEDATA=1 +) + +# Include paths for client +target_include_directories(${CLIENT_TARGET} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../.. + ${SDK_DIR}/drivers/netx_driver + ${SDK_DIR}/CMSIS/Include + ${SDK_DIR}/devices/MIMXRT1064 + ${SDK_DIR}/drivers + ${SDK_DIR}/board + ${SDK_DIR}/utilities + ${SDK_DIR}/components/uart + ${SDK_DIR}/components/phy + ${TX_USER_FILE_DIR} +) + +# Link libraries for client +target_link_libraries(${CLIENT_TARGET} + PRIVATE + board_bsp + threadx + netxduo + netx_imxrt_driver_client + mcux_sdk +) + +# Apply GCC linker script and post-build outputs for client +set_target_linker(${CLIENT_TARGET} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/MIMXRT1064xxxxx_flexspi_nor.ld") +post_build(${CLIENT_TARGET}) diff --git a/NXP/MIMXRT1064-EVK/app/demos/netx_echo/client_main.c b/NXP/MIMXRT1064-EVK/app/demos/netx_echo/client_main.c new file mode 100644 index 00000000..a9032e6e --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/demos/netx_echo/client_main.c @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available + * under the terms of the MIT license which is available at + * https://opensource.org/license/mit. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#include "board_init.h" +#include "console.h" +#include "tx_api.h" +#include "nx_api.h" +#include "ansi_colors.h" +#include +#include + +#define DEMO_STACK_SIZE 2048 +#define PACKET_SIZE 1536 +#define PACKET_POOL_SIZE (PACKET_SIZE * 24) +#define ECHO_SERVER_PORT 7 +#define ARP_CACHE_SIZE 1024 + +/* Static IP Configuration for Automated Verification Client */ +#define CLIENT_IP_ADDRESS IP_ADDRESS(192, 168, 0, 101) +#define SERVER_IP_ADDRESS IP_ADDRESS(192, 168, 0, 100) +#define NETWORK_MASK_VAL IP_ADDRESS(255, 255, 255, 0) +#define GATEWAY_ADDRESS_VAL IP_ADDRESS(192, 168, 0, 1) + +static TX_THREAD client_thread; +static uint8_t client_thread_stack[DEMO_STACK_SIZE]; + +static uint8_t ip_thread_stack[DEMO_STACK_SIZE]; +static uint8_t arp_cache_area[ARP_CACHE_SIZE]; + +static NX_PACKET_POOL client_pool; +static NX_IP client_ip; + +/* Place the NetX Duo packet pool in the NonCacheable section to ensure DMA coherency */ +__attribute__((section("NonCacheable"), aligned(64))) +static uint8_t packet_pool_area[PACKET_POOL_SIZE]; + +/* External hardware driver entry point for NXP i.MX RT ENET MAC */ +extern VOID nx_driver_imx(NX_IP_DRIVER *driver_req_ptr); + +static void client_thread_entry(ULONG thread_input); + +int main(void) +{ + /* Initialize MPU, system clocks (600 MHz), pins, LED GPIO, console, and ENET pins */ + board_init(); + + printf(ANSI_BOLD ANSI_CYAN "\r\n==================================================\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN " Eclipse ThreadX & NetX Duo on NXP i.MX RT1064-EVK\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN " Automated Network Verification Client (Renode)\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN "==================================================\r\n\r\n" ANSI_RESET); + + printf(TAG_SYSTEM " " MSG_INFO "Core Clock: %lu MHz | Tick Rate: %u Hz\r\n" ANSI_RESET, + SystemCoreClock / 1000000UL, TX_TIMER_TICKS_PER_SECOND); + + /* Enter ThreadX kernel */ + tx_kernel_enter(); + + return 0; +} + +void tx_application_define(void *first_unused_memory) +{ + (void)first_unused_memory; + UINT status; + + printf(TAG_CLIENT " " MSG_INFO "Initializing NetX Duo System...\r\n" ANSI_RESET); + nx_system_initialize(); + + /* 1. Create packet pool in NonCacheable memory */ + status = nx_packet_pool_create(&client_pool, "Client Packet Pool", + PACKET_SIZE, packet_pool_area, PACKET_POOL_SIZE); + if (status != NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR "Failed to create packet pool: 0x%02X\r\n" ANSI_RESET, status); + return; + } + printf(TAG_CLIENT " " MSG_SUCCESS "Packet pool created (size: %u bytes in NonCacheable memory)\r\n" ANSI_RESET, + (unsigned int)sizeof(packet_pool_area)); + + /* 2. Create IP instance using the NXP i.MX RT ENET driver */ + status = nx_ip_create(&client_ip, "NetX Client IP", CLIENT_IP_ADDRESS, + NETWORK_MASK_VAL, &client_pool, nx_driver_imx, + ip_thread_stack, DEMO_STACK_SIZE, 1); + if (status != NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR "Failed to create IP instance: 0x%02X\r\n" ANSI_RESET, status); + return; + } + printf(TAG_CLIENT " " MSG_SUCCESS "IP instance created (192.168.0.101)\r\n" ANSI_RESET); + + /* 3. Set Gateway Address */ + nx_ip_gateway_address_set(&client_ip, GATEWAY_ADDRESS_VAL); + + /* 4. Enable ARP */ + printf(TAG_CLIENT " " MSG_INFO "Enabling ARP...\r\n" ANSI_RESET); + status = nx_arp_enable(&client_ip, (VOID *)arp_cache_area, ARP_CACHE_SIZE); + if (status != NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR "Failed to enable ARP: 0x%02X\r\n" ANSI_RESET, status); + } + + /* 5. Enable ICMP (Ping) */ + printf(TAG_CLIENT " " MSG_INFO "Enabling ICMP...\r\n" ANSI_RESET); + status = nx_icmp_enable(&client_ip); + if (status != NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR "Failed to enable ICMP: 0x%02X\r\n" ANSI_RESET, status); + } + + /* 6. Enable UDP */ + printf(TAG_CLIENT " " MSG_INFO "Enabling UDP...\r\n" ANSI_RESET); + status = nx_udp_enable(&client_ip); + if (status != NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR "Failed to enable UDP: 0x%02X\r\n" ANSI_RESET, status); + } + + /* 7. Enable TCP */ + printf(TAG_CLIENT " " MSG_INFO "Enabling TCP...\r\n" ANSI_RESET); + status = nx_tcp_enable(&client_ip); + if (status != NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR "Failed to enable TCP: 0x%02X\r\n" ANSI_RESET, status); + } + + /* 8. Start Automated Verification Thread */ + tx_thread_create(&client_thread, "Client Verification Thread", client_thread_entry, 0, + client_thread_stack, DEMO_STACK_SIZE, 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START); + + printf(TAG_CLIENT " " MSG_SUCCESS "Verification thread registered.\r\n" ANSI_RESET); +} + +static void client_thread_entry(ULONG thread_input) +{ + (void)thread_input; + ULONG actual_status = 0; + UINT status; + int test_ping_passed = 0; + int test_udp_passed = 0; + int test_tcp_passed = 0; + + printf(TAG_CLIENT " " MSG_INFO "Bringing Ethernet Link UP...\r\n" ANSI_RESET); + status = nx_ip_driver_direct_command(&client_ip, NX_LINK_ENABLE, &actual_status); + if (status == NX_SUCCESS || status == NX_ALREADY_ENABLED) + { + printf(TAG_CLIENT " " MSG_SUCCESS "Ethernet link is UP!\r\n" ANSI_RESET); + } + else + { + printf(TAG_CLIENT " " MSG_WARNING "nx_ip_driver_direct_command NX_LINK_ENABLE status: 0x%02X\r\n" ANSI_RESET, status); + } + + /* Allow network stack and server node to settle */ + printf(TAG_CLIENT " " MSG_INFO "Waiting for network convergence...\r\n" ANSI_RESET); + tx_thread_sleep(150); + + printf("\r\n" ANSI_BOLD ANSI_CYAN "==================================================\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN " Starting Multi-Node Network Verification Suite\r\n" ANSI_RESET); + printf(ANSI_CYAN " Target Echo Server: 192.168.0.100 (Port 7)\r\n" ANSI_RESET); + printf(ANSI_CYAN " Local Client Node: 192.168.0.101\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN "==================================================\r\n\r\n" ANSI_RESET); + + /* ------------------------------------------------------------------ + * Test 1: ICMP Ping (Echo Request & Reply) + * ------------------------------------------------------------------ */ + printf(TAG_CLIENT " [Test 1/3] Testing ICMP Ping to 192.168.0.100...\r\n"); + NX_PACKET *ping_response = NX_NULL; + status = nx_icmp_ping(&client_ip, SERVER_IP_ADDRESS, "ThreadX_Ping", 12, &ping_response, 200); + if (status == NX_SUCCESS && ping_response != NX_NULL) + { + printf(TAG_CLIENT " " MSG_SUCCESS "[PASS] ICMP Ping successful! Response received from 192.168.0.100\r\n" ANSI_RESET); + nx_packet_release(ping_response); + test_ping_passed = 1; + } + else + { + printf(TAG_CLIENT " " MSG_ERROR "[FAIL] ICMP Ping timed out or failed: status 0x%02X\r\n" ANSI_RESET, status); + } + + /* Small delay between tests */ + tx_thread_sleep(50); + + /* ------------------------------------------------------------------ + * Test 2: UDP Echo (Datagram Tx & Rx on Port 7) + * ------------------------------------------------------------------ */ + printf("\r\n" TAG_CLIENT " [Test 2/3] Testing UDP Echo on port 7...\r\n"); + NX_UDP_SOCKET udp_client_socket; + status = nx_udp_socket_create(&client_ip, &udp_client_socket, "Client UDP Socket", + NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5); + if (status == NX_SUCCESS) + { + status = nx_udp_socket_bind(&udp_client_socket, NX_ANY_PORT, TX_WAIT_FOREVER); + if (status == NX_SUCCESS) + { + NX_PACKET *tx_packet = NX_NULL; + if (nx_packet_allocate(&client_pool, &tx_packet, NX_UDP_PACKET, TX_WAIT_FOREVER) == NX_SUCCESS) + { + const char *udp_payload = "Hello ThreadX UDP Echo!"; + nx_packet_data_append(tx_packet, (VOID *)udp_payload, strlen(udp_payload), &client_pool, TX_WAIT_FOREVER); + printf(TAG_CLIENT " " MSG_INFO "Sent UDP payload: '%s'\r\n" ANSI_RESET, udp_payload); + nx_udp_socket_send(&udp_client_socket, tx_packet, SERVER_IP_ADDRESS, ECHO_SERVER_PORT); + + NX_PACKET *rx_packet = NX_NULL; + status = nx_udp_socket_receive(&udp_client_socket, &rx_packet, 200); + if (status == NX_SUCCESS && rx_packet != NX_NULL) + { + printf(TAG_CLIENT " " MSG_SUCCESS "[PASS] Received UDP Echo: '%.*s' (%lu bytes)\r\n" ANSI_RESET, + (int)rx_packet->nx_packet_length, rx_packet->nx_packet_prepend_ptr, rx_packet->nx_packet_length); + nx_packet_release(rx_packet); + test_udp_passed = 1; + } + else + { + printf(TAG_CLIENT " " MSG_ERROR "[FAIL] UDP Echo receive timed out or failed: 0x%02X\r\n" ANSI_RESET, status); + } + } + nx_udp_socket_unbind(&udp_client_socket); + } + nx_udp_socket_delete(&udp_client_socket); + } + else + { + printf(TAG_CLIENT " " MSG_ERROR "[FAIL] Failed to create UDP socket: 0x%02X\r\n" ANSI_RESET, status); + } + + /* Small delay between tests */ + tx_thread_sleep(50); + + /* ------------------------------------------------------------------ + * Test 3: TCP Echo (Connection, Stream Tx & Rx on Port 7) + * ------------------------------------------------------------------ */ + printf("\r\n" TAG_CLIENT " [Test 3/3] Testing TCP Echo on port 7...\r\n"); + NX_TCP_SOCKET tcp_client_socket; + status = nx_tcp_socket_create(&client_ip, &tcp_client_socket, "Client TCP Socket", + NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 512, NX_NULL, NX_NULL); + if (status == NX_SUCCESS) + { + status = nx_tcp_client_socket_bind(&tcp_client_socket, NX_ANY_PORT, TX_WAIT_FOREVER); + if (status == NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_INFO "Connecting to 192.168.0.100:7...\r\n" ANSI_RESET); + status = nx_tcp_client_socket_connect(&tcp_client_socket, SERVER_IP_ADDRESS, ECHO_SERVER_PORT, 200); + if (status == NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_SUCCESS "TCP Connected! Sending stream payload...\r\n" ANSI_RESET); + NX_PACKET *tx_packet = NX_NULL; + if (nx_packet_allocate(&client_pool, &tx_packet, NX_TCP_PACKET, TX_WAIT_FOREVER) == NX_SUCCESS) + { + const char *tcp_payload = "Hello ThreadX TCP Echo!"; + nx_packet_data_append(tx_packet, (VOID *)tcp_payload, strlen(tcp_payload), &client_pool, TX_WAIT_FOREVER); + printf(TAG_CLIENT " " MSG_INFO "Sent TCP payload: '%s'\r\n" ANSI_RESET, tcp_payload); + nx_tcp_socket_send(&tcp_client_socket, tx_packet, 200); + + NX_PACKET *rx_packet = NX_NULL; + status = nx_tcp_socket_receive(&tcp_client_socket, &rx_packet, 200); + if (status == NX_SUCCESS && rx_packet != NX_NULL) + { + printf(TAG_CLIENT " " MSG_SUCCESS "[PASS] Received TCP Echo: '%.*s' (%lu bytes)\r\n" ANSI_RESET, + (int)rx_packet->nx_packet_length, rx_packet->nx_packet_prepend_ptr, rx_packet->nx_packet_length); + nx_packet_release(rx_packet); + test_tcp_passed = 1; + } + else + { + printf(TAG_CLIENT " " MSG_ERROR "[FAIL] TCP Echo receive timed out or failed: 0x%02X\r\n" ANSI_RESET, status); + } + } + nx_tcp_socket_disconnect(&tcp_client_socket, 100); + } + else + { + printf(TAG_CLIENT " " MSG_ERROR "[FAIL] TCP connect to 192.168.0.100:7 failed: 0x%02X\r\n" ANSI_RESET, status); + } + nx_tcp_client_socket_unbind(&tcp_client_socket); + } + nx_tcp_socket_delete(&tcp_client_socket); + } + else + { + printf(TAG_CLIENT " " MSG_ERROR "[FAIL] Failed to create TCP socket: 0x%02X\r\n" ANSI_RESET, status); + } + + /* ------------------------------------------------------------------ + * Verification Summary + * ------------------------------------------------------------------ */ + printf("\r\n" ANSI_BOLD "==================================================\r\n" ANSI_RESET); + if (test_ping_passed && test_udp_passed && test_tcp_passed) + { + printf(ANSI_BOLD ANSI_GREEN " [VERIFICATION SUCCESS] ALL NETWORK TESTS PASSED!\r\n" ANSI_RESET); + printf(ANSI_GREEN " - [PASS] ICMP Ping (Echo Request & Reply)\r\n" ANSI_RESET); + printf(ANSI_GREEN " - [PASS] UDP Echo (Datagram Tx & Rx)\r\n" ANSI_RESET); + printf(ANSI_GREEN " - [PASS] TCP Echo (Connection, Stream Tx & Rx)\r\n" ANSI_RESET); + } + else + { + printf(ANSI_BOLD ANSI_RED " [VERIFICATION INCOMPLETE] SOME TESTS FAILED!\r\n" ANSI_RESET); + if (!test_ping_passed) printf(ANSI_RED " - [FAIL] ICMP Ping\r\n" ANSI_RESET); + if (!test_udp_passed) printf(ANSI_RED " - [FAIL] UDP Echo\r\n" ANSI_RESET); + if (!test_tcp_passed) printf(ANSI_RED " - [FAIL] TCP Echo\r\n" ANSI_RESET); + } + printf(ANSI_BOLD "==================================================\r\n\r\n" ANSI_RESET); + + /* Heartbeat loop */ + while (1) + { + tx_thread_sleep(50); + USER_LED_TOGGLE(); + } +} diff --git a/NXP/MIMXRT1064-EVK/app/demos/netx_echo/main.c b/NXP/MIMXRT1064-EVK/app/demos/netx_echo/main.c new file mode 100644 index 00000000..0e9fff45 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/demos/netx_echo/main.c @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available + * under the terms of the MIT license which is available at + * https://opensource.org/license/mit. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#include "board_init.h" +#include "console.h" +#include "tx_api.h" +#include "nx_api.h" +#include "ansi_colors.h" +#include + +#define DEMO_STACK_SIZE 2048 +#define PACKET_SIZE 1536 +#define PACKET_POOL_SIZE (PACKET_SIZE * 24) +#define ECHO_SERVER_PORT 7 +#define ARP_CACHE_SIZE 1024 + +/* Static IP Configuration for Renode Simulation & Physical Testing */ +#define IP_ADDRESS_VAL IP_ADDRESS(192, 168, 0, 100) +#define NETWORK_MASK_VAL IP_ADDRESS(255, 255, 255, 0) +#define GATEWAY_ADDRESS_VAL IP_ADDRESS(192, 168, 0, 1) + +static TX_THREAD monitor_thread; +static uint8_t monitor_thread_stack[DEMO_STACK_SIZE]; + +static TX_THREAD udp_echo_thread; +static uint8_t udp_echo_thread_stack[DEMO_STACK_SIZE]; + +static TX_THREAD tcp_echo_thread; +static uint8_t tcp_echo_thread_stack[DEMO_STACK_SIZE]; + +static uint8_t ip_thread_stack[DEMO_STACK_SIZE]; +static uint8_t arp_cache_area[ARP_CACHE_SIZE]; + +static NX_PACKET_POOL pool_0; +static NX_IP ip_0; + +/* Place the NetX Duo packet pool in the NonCacheable section to ensure DMA coherency */ +__attribute__((section("NonCacheable"), aligned(64))) +static uint8_t packet_pool_area[PACKET_POOL_SIZE]; + +/* External hardware driver entry point for NXP i.MX RT ENET MAC */ +extern VOID nx_driver_imx(NX_IP_DRIVER *driver_req_ptr); + +static void monitor_thread_entry(ULONG thread_input); +static void udp_echo_thread_entry(ULONG thread_input); +static void tcp_echo_thread_entry(ULONG thread_input); + +int main(void) +{ + /* Initialize MPU, system clocks (600 MHz), pins, LED GPIO, console, and ENET pins */ + board_init(); + + printf(ANSI_BOLD ANSI_CYAN "\r\n==================================================\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN " Eclipse ThreadX & NetX Duo on NXP i.MX RT1064-EVK\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN " Virtual Ethernet Networking & Echo Demo (Renode)\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN "==================================================\r\n\r\n" ANSI_RESET); + + printf(TAG_SYSTEM " " MSG_INFO "Core Clock: %lu MHz | Tick Rate: %u Hz\r\n" ANSI_RESET, + SystemCoreClock / 1000000UL, TX_TIMER_TICKS_PER_SECOND); + + /* Enter ThreadX kernel */ + tx_kernel_enter(); + + return 0; +} + +void tx_application_define(void *first_unused_memory) +{ + (void)first_unused_memory; + UINT status; + + printf(TAG_NETWORK " " MSG_INFO "Initializing NetX Duo System...\r\n" ANSI_RESET); + nx_system_initialize(); + + /* 1. Create packet pool in NonCacheable memory */ + status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", + PACKET_SIZE, packet_pool_area, PACKET_POOL_SIZE); + if (status != NX_SUCCESS) + { + printf(TAG_NETWORK " " MSG_ERROR "Failed to create packet pool: 0x%02X\r\n" ANSI_RESET, status); + return; + } + printf(TAG_NETWORK " " MSG_SUCCESS "Packet pool created (size: %u bytes in NonCacheable memory)\r\n" ANSI_RESET, + (unsigned int)sizeof(packet_pool_area)); + + /* 2. Create IP instance using the NXP i.MX RT ENET driver */ + status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS_VAL, + NETWORK_MASK_VAL, &pool_0, nx_driver_imx, + ip_thread_stack, DEMO_STACK_SIZE, 1); + if (status != NX_SUCCESS) + { + printf(TAG_NETWORK " " MSG_ERROR "Failed to create IP instance: 0x%02X\r\n" ANSI_RESET, status); + return; + } + printf(TAG_NETWORK " " MSG_SUCCESS "IP instance created\r\n" ANSI_RESET); + + /* 3. Set Gateway Address */ + nx_ip_gateway_address_set(&ip_0, GATEWAY_ADDRESS_VAL); + + /* 4. Enable ARP */ + printf(TAG_NETWORK " " MSG_INFO "Enabling ARP...\r\n" ANSI_RESET); + status = nx_arp_enable(&ip_0, (VOID *)arp_cache_area, ARP_CACHE_SIZE); + if (status != NX_SUCCESS) + { + printf(TAG_NETWORK " " MSG_ERROR "Failed to enable ARP: 0x%02X\r\n" ANSI_RESET, status); + } + + /* 5. Enable ICMP (Ping) */ + printf(TAG_NETWORK " " MSG_INFO "Enabling ICMP (Ping responder)...\r\n" ANSI_RESET); + status = nx_icmp_enable(&ip_0); + if (status != NX_SUCCESS) + { + printf(TAG_NETWORK " " MSG_ERROR "Failed to enable ICMP: 0x%02X\r\n" ANSI_RESET, status); + } + + /* 6. Enable UDP */ + printf(TAG_NETWORK " " MSG_INFO "Enabling UDP...\r\n" ANSI_RESET); + status = nx_udp_enable(&ip_0); + if (status != NX_SUCCESS) + { + printf(TAG_NETWORK " " MSG_ERROR "Failed to enable UDP: 0x%02X\r\n" ANSI_RESET, status); + } + + /* 7. Enable TCP */ + printf(TAG_NETWORK " " MSG_INFO "Enabling TCP...\r\n" ANSI_RESET); + status = nx_tcp_enable(&ip_0); + if (status != NX_SUCCESS) + { + printf(TAG_NETWORK " " MSG_ERROR "Failed to enable TCP: 0x%02X\r\n" ANSI_RESET, status); + } + + /* 8. Start Monitor / Heartbeat Thread */ + tx_thread_create(&monitor_thread, "Network Monitor", monitor_thread_entry, 0, + monitor_thread_stack, DEMO_STACK_SIZE, 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* 9. Start UDP Echo Server Thread */ + tx_thread_create(&udp_echo_thread, "UDP Echo Thread", udp_echo_thread_entry, 0, + udp_echo_thread_stack, DEMO_STACK_SIZE, 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* 10. Start TCP Echo Server Thread */ + tx_thread_create(&tcp_echo_thread, "TCP Echo Thread", tcp_echo_thread_entry, 0, + tcp_echo_thread_stack, DEMO_STACK_SIZE, 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START); + + printf(TAG_NETWORK " " MSG_SUCCESS "All network threads registered successfully.\r\n" ANSI_RESET); +} + +static void monitor_thread_entry(ULONG thread_input) +{ + (void)thread_input; + ULONG ip_address = 0; + ULONG network_mask = 0; + ULONG actual_status = 0; + uint8_t led_state = 0; + + printf(TAG_NETWORK " " MSG_INFO "Bringing Ethernet Link UP...\r\n" ANSI_RESET); + UINT status = nx_ip_driver_direct_command(&ip_0, NX_LINK_ENABLE, &actual_status); + if (status == NX_SUCCESS || status == NX_ALREADY_ENABLED) + { + printf(TAG_NETWORK " " MSG_SUCCESS "Ethernet link is UP!\r\n" ANSI_RESET); + } + else + { + printf(TAG_NETWORK " " MSG_WARNING "nx_ip_driver_direct_command NX_LINK_ENABLE status: 0x%02X\r\n" ANSI_RESET, status); + } + + nx_ip_address_get(&ip_0, &ip_address, &network_mask); + printf("\r\n" ANSI_BOLD ANSI_GREEN "================ Network Ready ================\r\n" ANSI_RESET); + printf(ANSI_GREEN " Static IPv4 : %lu.%lu.%lu.%lu\r\n" ANSI_RESET, + (ip_address >> 24) & 0xFF, (ip_address >> 16) & 0xFF, + (ip_address >> 8) & 0xFF, ip_address & 0xFF); + printf(ANSI_GREEN " Subnet Mask : %lu.%lu.%lu.%lu\r\n" ANSI_RESET, + (network_mask >> 24) & 0xFF, (network_mask >> 16) & 0xFF, + (network_mask >> 8) & 0xFF, network_mask & 0xFF); + printf(ANSI_GREEN " Services : ICMP Ping, UDP Echo (Port 7), TCP Echo (Port 7)\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_GREEN "===============================================\r\n\r\n" ANSI_RESET); + + while (1) + { + /* Sleep 500 ms (50 ticks) */ + tx_thread_sleep(50); + + /* Toggle User LED to indicate active heartbeat */ + USER_LED_TOGGLE(); + led_state = !led_state; + } +} + +static void udp_echo_thread_entry(ULONG thread_input) +{ + NX_UDP_SOCKET udp_socket; + NX_PACKET *rx_packet; + UINT status; + + (void)thread_input; + + status = nx_udp_socket_create(&ip_0, &udp_socket, "UDP Echo Socket", + NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5); + if (status != NX_SUCCESS) + { + printf(TAG_ECHO " " MSG_ERROR "Failed to create UDP socket: 0x%02X\r\n" ANSI_RESET, status); + return; + } + + status = nx_udp_socket_bind(&udp_socket, ECHO_SERVER_PORT, TX_WAIT_FOREVER); + if (status != NX_SUCCESS) + { + printf(TAG_ECHO " " MSG_ERROR "Failed to bind UDP port %u: 0x%02X\r\n" ANSI_RESET, ECHO_SERVER_PORT, status); + nx_udp_socket_delete(&udp_socket); + return; + } + + printf(TAG_ECHO " " MSG_INFO "UDP Echo Server listening on port %d\r\n" ANSI_RESET, ECHO_SERVER_PORT); + + while (1) + { + status = nx_udp_socket_receive(&udp_socket, &rx_packet, TX_WAIT_FOREVER); + if (status == NX_SUCCESS) + { + ULONG peer_ip = 0; + UINT peer_port = 0; + nx_udp_source_extract(rx_packet, &peer_ip, &peer_port); + + printf(TAG_ECHO " " MSG_SUCCESS "UDP Rx from %lu.%lu.%lu.%lu:%u (%lu bytes), echoing...\r\n" ANSI_RESET, + (peer_ip >> 24) & 0xFF, (peer_ip >> 16) & 0xFF, + (peer_ip >> 8) & 0xFF, peer_ip & 0xFF, + peer_port, rx_packet->nx_packet_length); + + /* Allocate a response packet from the pool */ + NX_PACKET *tx_packet = NX_NULL; + if (nx_packet_allocate(&pool_0, &tx_packet, NX_UDP_PACKET, TX_NO_WAIT) == NX_SUCCESS) + { + nx_packet_data_append(tx_packet, rx_packet->nx_packet_prepend_ptr, + rx_packet->nx_packet_length, &pool_0, TX_NO_WAIT); + nx_udp_socket_send(&udp_socket, tx_packet, peer_ip, peer_port); + } + + /* Release the received packet */ + nx_packet_release(rx_packet); + } + } +} + +static void tcp_echo_thread_entry(ULONG thread_input) +{ + NX_TCP_SOCKET echo_socket; + NX_PACKET *packet_ptr; + UINT status; + + (void)thread_input; + + status = nx_tcp_socket_create(&ip_0, &echo_socket, "TCP Echo Socket", + NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, + 512, NX_NULL, NX_NULL); + if (status != NX_SUCCESS) + { + printf(TAG_ECHO " " MSG_ERROR "Failed to create TCP socket: 0x%02X\r\n" ANSI_RESET, status); + return; + } + + printf(TAG_ECHO " " MSG_INFO "TCP Echo Server listening on port %d\r\n" ANSI_RESET, ECHO_SERVER_PORT); + + while (1) + { + status = nx_tcp_server_socket_listen(&ip_0, ECHO_SERVER_PORT, &echo_socket, 5, NX_NULL); + if (status != NX_SUCCESS) + { + nx_tcp_server_socket_unlisten(&ip_0, ECHO_SERVER_PORT); + tx_thread_sleep(10); + continue; + } + + if (nx_tcp_server_socket_accept(&echo_socket, NX_WAIT_FOREVER) == NX_SUCCESS) + { + printf(TAG_ECHO " " MSG_SUCCESS "TCP Client connected.\r\n" ANSI_RESET); + + while (nx_tcp_socket_receive(&echo_socket, &packet_ptr, NX_WAIT_FOREVER) == NX_SUCCESS) + { + printf(TAG_ECHO " " MSG_SUCCESS "TCP Rx %lu bytes, echoing...\r\n" ANSI_RESET, + packet_ptr->nx_packet_length); + NX_PACKET *tx_packet = NX_NULL; + if (nx_packet_allocate(&pool_0, &tx_packet, NX_TCP_PACKET, TX_WAIT_FOREVER) == NX_SUCCESS) + { + nx_packet_data_append(tx_packet, packet_ptr->nx_packet_prepend_ptr, + packet_ptr->nx_packet_length, &pool_0, TX_WAIT_FOREVER); + nx_tcp_socket_send(&echo_socket, tx_packet, NX_WAIT_FOREVER); + } + nx_packet_release(packet_ptr); + } + + printf(TAG_ECHO " " MSG_WARNING "TCP Client disconnected.\r\n" ANSI_RESET); + nx_tcp_socket_disconnect(&echo_socket, NX_WAIT_FOREVER); + nx_tcp_server_socket_unaccept(&echo_socket); + } + nx_tcp_server_socket_unlisten(&ip_0, ECHO_SERVER_PORT); + } +} diff --git a/NXP/MIMXRT1064-EVK/app/demos/netx_echo/nx_user.h b/NXP/MIMXRT1064-EVK/app/demos/netx_echo/nx_user.h new file mode 100644 index 00000000..eccf436a --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/demos/netx_echo/nx_user.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available + * under the terms of the MIT license which is available at + * https://opensource.org/license/mit. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#ifndef NX_USER_H +#define NX_USER_H + +#define NX_DISABLE_IPV6 +#define NX_PHYSICAL_HEADER 16 +#define NX_ENABLE_EXTENDED_NOTIFY_SUPPORT + +#endif /* NX_USER_H */ diff --git a/NXP/MIMXRT1064-EVK/app/demos/netx_echo/test_echo.ps1 b/NXP/MIMXRT1064-EVK/app/demos/netx_echo/test_echo.ps1 new file mode 100644 index 00000000..cf1e5d0a --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/demos/netx_echo/test_echo.ps1 @@ -0,0 +1,131 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. + +param ( + [string]$IP = "192.168.0.100", + [int]$Port = 7 +) + +Write-Host "==========================================" -ForegroundColor Cyan +Write-Host " NetX Duo Virtual Networking Verification" -ForegroundColor Cyan +Write-Host " Target Device: $IP (Port: $Port)" -ForegroundColor Cyan +Write-Host "==========================================" -ForegroundColor Cyan +Write-Host "" + +$AllPassed = $true + +# ---------------------------------------------------- +# Test 1: ICMP Ping +# ---------------------------------------------------- +Write-Host "[Test 1/3] Testing ICMP Ping (Echo Request)..." -ForegroundColor Yellow +$PingSuccess = $false +try { + $pingRes = Test-Connection -ComputerName $IP -Count 2 -Quiet -ErrorAction Stop + if ($pingRes) { + $PingSuccess = $true + } +} catch { + # Fallback to ping.exe + $res = ping -n 2 -w 1000 $IP + if ($LASTEXITCODE -eq 0) { + $PingSuccess = $true + } +} + +if ($PingSuccess) { + Write-Host "[PASS] ICMP Ping responded successfully from $IP" -ForegroundColor Green +} else { + Write-Host "[FAIL] ICMP Ping timed out or failed to reach $IP" -ForegroundColor Red + $AllPassed = $false +} +Write-Host "" + +# ---------------------------------------------------- +# Test 2: UDP Echo +# ---------------------------------------------------- +Write-Host "[Test 2/3] Testing UDP Echo on port $Port..." -ForegroundColor Yellow +$UdpClient = New-Object System.Net.Sockets.UdpClient +$UdpClient.Client.ReceiveTimeout = 3000 + +$UdpMsg = "Hello ThreadX UDP Echo!" +$UdpBytes = [System.Text.Encoding]::ASCII.GetBytes($UdpMsg) + +try { + $UdpClient.Connect($IP, $Port) + [void]$UdpClient.Send($UdpBytes, $UdpBytes.Length) + Write-Host "Sent UDP: '$UdpMsg'" + + $RemoteEndpoint = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Any, 0) + $ReceivedBytes = $UdpClient.Receive([ref]$RemoteEndpoint) + $ReceivedMsg = [System.Text.Encoding]::ASCII.GetString($ReceivedBytes) + Write-Host "Received UDP: '$ReceivedMsg'" + + if ($ReceivedMsg -eq $UdpMsg) { + Write-Host "[PASS] UDP Echo verified successfully!" -ForegroundColor Green + } else { + Write-Host "[FAIL] UDP payload mismatch: expected '$UdpMsg', got '$ReceivedMsg'" -ForegroundColor Red + $AllPassed = $false + } +} catch { + Write-Host "[FAIL] UDP Echo failed: $_" -ForegroundColor Red + $AllPassed = $false +} finally { + $UdpClient.Close() +} +Write-Host "" + +# ---------------------------------------------------- +# Test 3: TCP Echo +# ---------------------------------------------------- +Write-Host "[Test 3/3] Testing TCP Echo on port $Port..." -ForegroundColor Yellow +$TcpClient = $null +try { + $TcpClient = New-Object System.Net.Sockets.TcpClient + $TcpClient.ReceiveTimeout = 3000 + $TcpClient.SendTimeout = 3000 + $TcpClient.Connect($IP, $Port) + + $Stream = $TcpClient.GetStream() + $Writer = New-Object System.IO.StreamWriter($Stream) + $Reader = New-Object System.IO.StreamReader($Stream) + + $TcpMsg = "Hello ThreadX TCP Echo!" + Write-Host "Sent TCP: '$TcpMsg'" + $Writer.WriteLine($TcpMsg) + $Writer.Flush() + + $TcpResponse = $Reader.ReadLine() + Write-Host "Received TCP: '$TcpResponse'" + + if ($TcpResponse -eq $TcpMsg) { + Write-Host "[PASS] TCP Echo verified successfully!" -ForegroundColor Green + } else { + Write-Host "[FAIL] TCP payload mismatch: expected '$TcpMsg', got '$TcpResponse'" -ForegroundColor Red + $AllPassed = $false + } +} catch { + Write-Host "[FAIL] TCP Echo failed: $_" -ForegroundColor Red + $AllPassed = $false +} finally { + if ($TcpClient) { $TcpClient.Close() } +} +Write-Host "" + +# ---------------------------------------------------- +# Summary +# ---------------------------------------------------- +Write-Host "==========================================" -ForegroundColor Cyan +if ($AllPassed) { + Write-Host " ALL TESTS PASSED! NetX Duo is fully verified." -ForegroundColor Green +} else { + Write-Host " SOME TESTS FAILED. Verify Renode TAP and network connection." -ForegroundColor Red +} +Write-Host "==========================================" -ForegroundColor Cyan diff --git a/NXP/MIMXRT1064-EVK/app/demos/netx_echo/test_echo.sh b/NXP/MIMXRT1064-EVK/app/demos/netx_echo/test_echo.sh new file mode 100644 index 00000000..ec316cec --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/demos/netx_echo/test_echo.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. + +set -e + +IP=${1:-"192.168.0.100"} +PORT=7 + +echo "==========================================" +echo " NetX Duo Virtual Networking Verification" +echo " Target Device: ${IP} (Port: ${PORT})" +echo "==========================================" +echo "" + +ALL_PASSED=1 + +# 1. ICMP Ping Test +echo "[Test 1/3] Testing ICMP Ping (Echo Request)..." +if ping -c 2 -W 2 "${IP}" > /dev/null 2>&1; then + echo "[PASS] ICMP Ping responded successfully from ${IP}" +else + echo "[FAIL] ICMP Ping timed out or failed to reach ${IP}" + ALL_PASSED=0 +fi +echo "" + +# 2. UDP Echo Test +echo "[Test 2/3] Testing UDP Echo on port ${PORT}..." +UDP_MSG="Hello ThreadX UDP Echo!" +UDP_RES=$(python3 -c " +import socket, sys +try: + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.settimeout(3.0) + s.sendto(b'${UDP_MSG}', ('${IP}', ${PORT})) + data, _ = s.recvfrom(1024) + print(data.decode('ascii', errors='ignore')) +except Exception as e: + sys.exit(1) +finally: + s.close() +" 2>/dev/null || true) + +if [ "${UDP_RES}" = "${UDP_MSG}" ]; then + echo "Sent UDP: '${UDP_MSG}'" + echo "Received UDP: '${UDP_RES}'" + echo "[PASS] UDP Echo verified successfully!" +else + echo "[FAIL] UDP Echo failed (got '${UDP_RES}')" + ALL_PASSED=0 +fi +echo "" + +# 3. TCP Echo Test +echo "[Test 3/3] Testing TCP Echo on port ${PORT}..." +TCP_MSG="Hello ThreadX TCP Echo!" +TCP_RES=$(python3 -c " +import socket, sys +try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(3.0) + s.connect(('${IP}', ${PORT})) + s.sendall(b'${TCP_MSG}\n') + data = s.recv(1024) + print(data.decode('ascii', errors='ignore').strip()) +except Exception as e: + sys.exit(1) +finally: + s.close() +" 2>/dev/null || true) + +if [ "${TCP_RES}" = "${TCP_MSG}" ]; then + echo "Sent TCP: '${TCP_MSG}'" + echo "Received TCP: '${TCP_RES}'" + echo "[PASS] TCP Echo verified successfully!" +else + echo "[FAIL] TCP Echo failed (got '${TCP_RES}')" + ALL_PASSED=0 +fi +echo "" + +echo "==========================================" +if [ "${ALL_PASSED}" -eq 1 ]; then + echo " ALL TESTS PASSED! NetX Duo is fully verified." +else + echo " SOME TESTS FAILED. Verify Renode TAP and network connection." +fi +echo "==========================================" diff --git a/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/CMakeLists.txt b/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/CMakeLists.txt new file mode 100644 index 00000000..41f8f3bb --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/CMakeLists.txt @@ -0,0 +1,55 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. + +add_executable(${PROJECT_NAME} + main.c +) + +# Set compile definitions for our executable +target_compile_definitions(${PROJECT_NAME} + PRIVATE + CPU_MIMXRT1064DVL6A + XIP_EXTERNAL_FLASH=1 + XIP_BOOT_HEADER_ENABLE=1 + XIP_BOOT_HEADER_DCD_ENABLE=1 + FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE=1 + SDK_DEBUGCONSOLE=1 + SKIP_SYSCLK_INIT=1 + __STARTUP_INITIALIZE_NONCACHEDATA=1 +) + +# Include paths for the executable target +target_include_directories(${PROJECT_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../.. + ${SDK_DIR}/CMSIS/Include + ${SDK_DIR}/devices/MIMXRT1064 + ${SDK_DIR}/drivers + ${SDK_DIR}/board + ${SDK_DIR}/utilities + ${SDK_DIR}/components/uart + ${TX_USER_FILE_DIR} +) + +# Link libraries +target_link_libraries(${PROJECT_NAME} + PRIVATE + board_bsp + threadx + mcux_sdk +) + +# Apply GCC linker script and print memory usage (utilities.cmake function) +set_target_linker(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/MIMXRT1064xxxxx_flexspi_nor.ld") + +# Post-build commands to generate raw .bin and .hex files +post_build(${PROJECT_NAME}) diff --git a/NXP/MIMXRT1064-EVK/app/main.c b/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/main.c similarity index 100% rename from NXP/MIMXRT1064-EVK/app/main.c rename to NXP/MIMXRT1064-EVK/app/demos/threadx_basic/main.c diff --git a/NXP/MIMXRT1064-EVK/app/syscalls.c b/NXP/MIMXRT1064-EVK/app/syscalls.c index fa3d9e88..2411304a 100644 --- a/NXP/MIMXRT1064-EVK/app/syscalls.c +++ b/NXP/MIMXRT1064-EVK/app/syscalls.c @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT * * Contributors: - * Ali Eissa - 2026 NXP i.MX RT1064 port. + * Ali Eissa - 2026 version. */ #include diff --git a/NXP/MIMXRT1064-EVK/app/sysmem.c b/NXP/MIMXRT1064-EVK/app/sysmem.c index 98235ab8..4d7954bc 100644 --- a/NXP/MIMXRT1064-EVK/app/sysmem.c +++ b/NXP/MIMXRT1064-EVK/app/sysmem.c @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT * * Contributors: - * Ali Eissa - 2026 NXP i.MX RT1064 port. + * Ali Eissa - 2026 version. */ #include diff --git a/NXP/MIMXRT1064-EVK/cmake/utilities.cmake b/NXP/MIMXRT1064-EVK/cmake/utilities.cmake index b86454da..d584424d 100644 --- a/NXP/MIMXRT1064-EVK/cmake/utilities.cmake +++ b/NXP/MIMXRT1064-EVK/cmake/utilities.cmake @@ -20,8 +20,8 @@ function(post_build TARGET) elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU") add_custom_target(${TARGET}.bin ALL DEPENDS ${TARGET} - COMMAND ${CMAKE_OBJCOPY} -Obinary ${TARGET}.elf ${TARGET}.bin - COMMAND ${CMAKE_OBJCOPY} -Oihex ${TARGET}.elf ${TARGET}.hex) + COMMAND ${CMAKE_OBJCOPY} -Obinary $ $/${TARGET}.bin + COMMAND ${CMAKE_OBJCOPY} -Oihex $ $/${TARGET}.hex) else() message(FATAL_ERROR "Unknown CMAKE_C_COMPILER_ID ${CMAKE_C_COMPILER_ID}") endif() diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl index 81b1f8cd..ee18a571 100644 --- a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl @@ -36,3 +36,14 @@ adc1: adc2: referenceVoltage: 3.3 + +// Ethernet Physical Layer (KSZ8081 PHY at address 2 on enet) +phy: Network.EthernetPhysicalLayer @ enet 2 + Id1: 0x0022 + Id2: 0x1560 + BasicControl: 0x3100 + BasicStatus: 0x782D + AutoNegotiationAdvertisement: 0x01E1 + AutoNegotiationLinkPartnerBasePageAbility: 0x01E1 + VendorSpecific14: 0x0116 + VendorSpecific15: 0x0080 diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc index ba8f9226..6ba323b0 100644 --- a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc @@ -1,5 +1,5 @@ :name: MIMXRT1064-EVK ThreadX Demo -:description: This script runs the Eclipse ThreadX demo on NXP i.MX RT1064-EVK. +:description: This script runs the Eclipse ThreadX & NetX Duo demo on NXP i.MX RT1064-EVK. mach create "mimxrt1064-evk" @@ -8,6 +8,17 @@ machine LoadPlatformDescription $platform $bin?=$ORIGIN/../build/mimxrt1064_threadx.elf +# Create Ethernet Switch and connect ENET peripheral +emulation CreateSwitch "switch" +connector Connect sysbus.enet switch + +# Host TAP networking configuration (for ICMP ping and UDP/TCP echo from host PC): +# On Windows, install OpenVPN/TAP adapter named "renode-tap" configured with IP 192.168.0.1 / 255.255.255.0. +# On Linux, create tap interface: `sudo ip tuntap add mode tap tap0 && sudo ifconfig tap0 192.168.0.1 up` +# Uncomment below lines to bridge the simulated switch to your host TAP device: +# emulation CreateTap "renode-tap" "tap" +# connector Connect host.tap switch + showAnalyzer sysbus.lpuart1 macro reset diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-network-multinode.resc b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-network-multinode.resc new file mode 100644 index 00000000..88be9668 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-network-multinode.resc @@ -0,0 +1,51 @@ +:name: MIMXRT1064-EVK NetX Duo Two-Node Virtual Network Verification +:description: This script creates two MIMXRT1064-EVK nodes connected via a virtual Ethernet switch: +: - "server": Echo Server on 192.168.0.100 (ICMP Ping, UDP port 7, TCP port 7) +: - "client": Verification Client on 192.168.0.101 (tests ICMP, UDP Echo, TCP Echo) + +# 1. Create Virtual Ethernet Switch +emulation CreateSwitch "switch" + +# 2. Server Machine (192.168.0.100) +mach create "server" +machine LoadPlatformDescription $ORIGIN/mimxrt1064-evk.repl +connector Connect sysbus.enet switch +showAnalyzer sysbus.lpuart1 + +$bin_server?=$ORIGIN/../build/mimxrt1064_threadx.elf +macro reset_server +""" + cpu VectorTableOffset 0x70002000 + sysbus LoadELF $bin_server + cpu PC `sysbus ReadDoubleWord 0x70002004` + cpu SP `sysbus ReadDoubleWord 0x70002000` +""" +runMacro $reset_server + +# 3. Client Machine (192.168.0.101) +mach create "client" +machine LoadPlatformDescription $ORIGIN/mimxrt1064-evk.repl +connector Connect sysbus.enet switch +showAnalyzer sysbus.lpuart1 + +$bin_client?=$ORIGIN/../build/mimxrt1064_client.elf +macro reset_client +""" + cpu VectorTableOffset 0x70002000 + sysbus LoadELF $bin_client + cpu PC `sysbus ReadDoubleWord 0x70002004` + cpu SP `sysbus ReadDoubleWord 0x70002000` +""" +runMacro $reset_client + +# 4. Global reset macro to reset both nodes simultaneously +macro reset +""" + mach set "server" + runMacro $reset_server + mach set "client" + runMacro $reset_client +""" + +# 5. Start Simulation +start diff --git a/NXP/MIMXRT1064-EVK/scripts/build.ps1 b/NXP/MIMXRT1064-EVK/scripts/build.ps1 index e688610d..a0cd9c99 100644 --- a/NXP/MIMXRT1064-EVK/scripts/build.ps1 +++ b/NXP/MIMXRT1064-EVK/scripts/build.ps1 @@ -11,7 +11,8 @@ param( [switch]$Clean, - [switch]$Rebuild + [switch]$Rebuild, + [string]$Demo = "netx_echo" ) $BoardDir = Resolve-Path "$PSScriptRoot/.." @@ -21,8 +22,9 @@ $NUM_JOBS = 4 Write-Host "==========================================" Write-Host "NXP MIMXRT1064-EVK - Build Script" Write-Host "==========================================" -Write-Host "Board Dir: $BoardDir" -Write-Host "Build Dir: $BUILD_DIR" +Write-Host "Board Dir: $BoardDir" +Write-Host "Build Dir: $BUILD_DIR" +Write-Host "Active Demo: $Demo" Write-Host "" # Check for ARM GCC compiler @@ -48,11 +50,20 @@ if (!(Test-Path $BUILD_DIR)) { Push-Location $BUILD_DIR -# Reconfigure if CMakeCache.txt or build.ninja is missing, or if forced -if (!(Test-Path "CMakeCache.txt") -or !(Test-Path "build.ninja") -or $Rebuild) { - Write-Host "[INFO] Configuring CMake..." +# Reconfigure if CMakeCache.txt or build.ninja is missing, or demo changed, or if forced +$needConfig = !(Test-Path "CMakeCache.txt") -or !(Test-Path "build.ninja") -or $Rebuild +if (!$needConfig -and (Test-Path "CMakeCache.txt")) { + $cachedDemo = (Select-String -Path "CMakeCache.txt" -Pattern "^ACTIVE_DEMO:STRING=(.*)$" | ForEach-Object { $_.Matches.Groups[1].Value.Trim() }) + if ($cachedDemo -ne $Demo) { + $needConfig = $true + } +} + +if ($needConfig) { + Write-Host "[INFO] Configuring CMake for demo: $Demo..." cmake -G Ninja ` "-DCMAKE_BUILD_TYPE=Release" ` + "-DACTIVE_DEMO=$Demo" ` .. if ($LASTEXITCODE -ne 0) { Write-Host "[ERROR] CMake configuration failed!" -ForegroundColor Red @@ -63,22 +74,24 @@ if (!(Test-Path "CMakeCache.txt") -or !(Test-Path "build.ninja") -or $Rebuild) { Write-Host "" } -Write-Host "[INFO] Building with $NUM_JOBS parallel jobs..." -if (Get-Command ninja -ErrorAction SilentlyContinue) { - ninja -j $NUM_JOBS -} else { - cmake --build . --parallel $NUM_JOBS --config Release -} - -$buildExitCode = $LASTEXITCODE -Pop-Location - -if ($buildExitCode -ne 0) { +# Run build using Ninja +Write-Host "[INFO] Building target with Ninja ($NUM_JOBS parallel jobs)..." +ninja -j $NUM_JOBS +if ($LASTEXITCODE -ne 0) { Write-Host "[ERROR] Build failed!" -ForegroundColor Red + Pop-Location exit 1 } Write-Host "" -Write-Host "==========================================" -Write-Host "[OK] Build completed successfully!" -Write-Host "==========================================" +Write-Host "[SUCCESS] Build finished successfully!" -ForegroundColor Green +Write-Host "Server Firmware ELF: $(Join-Path $BUILD_DIR 'mimxrt1064_threadx.elf')" +Write-Host "Server Firmware BIN: $(Join-Path $BUILD_DIR 'mimxrt1064_threadx.bin')" +Write-Host "Server Firmware HEX: $(Join-Path $BUILD_DIR 'mimxrt1064_threadx.hex')" +if (Test-Path (Join-Path $BUILD_DIR 'mimxrt1064_client.elf')) { + Write-Host "Client Firmware ELF: $(Join-Path $BUILD_DIR 'mimxrt1064_client.elf')" + Write-Host "Client Firmware BIN: $(Join-Path $BUILD_DIR 'mimxrt1064_client.bin')" + Write-Host "Client Firmware HEX: $(Join-Path $BUILD_DIR 'mimxrt1064_client.hex')" +} + +Pop-Location diff --git a/NXP/MIMXRT1064-EVK/scripts/build.sh b/NXP/MIMXRT1064-EVK/scripts/build.sh index a202f82f..48d5327e 100644 --- a/NXP/MIMXRT1064-EVK/scripts/build.sh +++ b/NXP/MIMXRT1064-EVK/scripts/build.sh @@ -19,12 +19,14 @@ NUM_JOBS=4 CLEAN=0 REBUILD=0 +DEMO="netx_echo" # Parse arguments while [[ "$#" -gt 0 ]]; do case $1 in --clean) CLEAN=1 ;; --rebuild) REBUILD=1 ;; + --demo) DEMO="$2"; shift ;; *) echo "Unknown parameter passed: $1"; exit 1 ;; esac shift @@ -33,8 +35,9 @@ done echo "==========================================" echo "NXP MIMXRT1064-EVK - Build Script (POSIX)" echo "==========================================" -echo "Board Dir: ${BOARD_DIR}" -echo "Build Dir: ${BUILD_DIR}" +echo "Board Dir: ${BOARD_DIR}" +echo "Build Dir: ${BUILD_DIR}" +echo "Active Demo: ${DEMO}" echo "" # Check for ARM GCC compiler @@ -54,24 +57,38 @@ fi mkdir -p "${BUILD_DIR}" cd "${BUILD_DIR}" -# Reconfigure if CMakeCache.txt or build.ninja is missing, or if forced +# Reconfigure if CMakeCache.txt or build.ninja is missing, or demo changed, or if forced +NEED_CONFIG=0 if [ ! -f "CMakeCache.txt" ] || [ ! -f "build.ninja" ] || [ "${REBUILD}" -eq 1 ]; then - echo "[INFO] Configuring CMake..." + NEED_CONFIG=1 +else + CACHED_DEMO=$(grep "^ACTIVE_DEMO:STRING=" CMakeCache.txt 2>/dev/null | cut -d'=' -f2 | tr -d '[:space:]') + if [ "${CACHED_DEMO}" != "${DEMO}" ]; then + NEED_CONFIG=1 + fi +fi + +if [ "${NEED_CONFIG}" -eq 1 ]; then + echo "[INFO] Configuring CMake for demo: ${DEMO}..." cmake -G Ninja \ - -DCMAKE_BUILD_TYPE=Release \ + "-DCMAKE_BUILD_TYPE=Release" \ + "-DACTIVE_DEMO=${DEMO}" \ .. echo "[OK] CMake configured" echo "" fi -echo "[INFO] Building with ${NUM_JOBS} parallel jobs..." -if command -v ninja &> /dev/null; then - ninja -j "${NUM_JOBS}" -else - cmake --build . --parallel "${NUM_JOBS}" --config Release -fi +# Run build using Ninja +echo "[INFO] Building target with Ninja (${NUM_JOBS} parallel jobs)..." +ninja -j ${NUM_JOBS} echo "" -echo "==========================================" -echo "[OK] Build completed successfully!" -echo "==========================================" +echo "[SUCCESS] Build finished successfully!" +echo "Server Firmware ELF: ${BUILD_DIR}/mimxrt1064_threadx.elf" +echo "Server Firmware BIN: ${BUILD_DIR}/mimxrt1064_threadx.bin" +echo "Server Firmware HEX: ${BUILD_DIR}/mimxrt1064_threadx.hex" +if [ -f "${BUILD_DIR}/mimxrt1064_client.elf" ]; then + echo "Client Firmware ELF: ${BUILD_DIR}/mimxrt1064_client.elf" + echo "Client Firmware BIN: ${BUILD_DIR}/mimxrt1064_client.bin" + echo "Client Firmware HEX: ${BUILD_DIR}/mimxrt1064_client.hex" +fi diff --git a/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 index 420f7ef9..76d585a7 100644 --- a/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 +++ b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 @@ -132,6 +132,12 @@ try { param([string]$Uri, [string]$OutFile, [int]$MaxAttempts = 4) for ($i = 1; $i -le $MaxAttempts; $i++) { try { + if (Get-Command curl.exe -ErrorAction SilentlyContinue) { + & curl.exe --retry 3 --retry-delay 2 -fsSL $Uri -o $OutFile + if ($LASTEXITCODE -eq 0 -and (Test-Path $OutFile) -and ((Get-Item $OutFile).Length -gt 0)) { + return + } + } Invoke-WebRequest -Uri $Uri -OutFile $OutFile -UseBasicParsing -TimeoutSec 30 return } @@ -163,16 +169,18 @@ try { Download-WithRetry -Uri $item.Remote -OutFile $dest } - # Download official GNU GCC Linker Script & Startup File for reference in lib/mcux-sdk/board/ - Write-Host "[INFO] Downloading official NXP GNU GCC Linker Script and Startup File into board directory..." - $nxpGccBase = "https://raw.githubusercontent.com/nxp-mcuxpresso/mcux-sdk/main/devices/MIMXRT1064/gcc" - $ldDestBoard = Join-Path $BoardFilesDir "MIMXRT1064xxxxx_flexspi_nor.ld" - $startupDestBoard = Join-Path $BoardFilesDir "startup_MIMXRT1064.S" - - Download-WithRetry -Uri "$nxpGccBase/MIMXRT1064xxxxx_flexspi_nor.ld" -OutFile $ldDestBoard - Download-WithRetry -Uri "$nxpGccBase/startup_MIMXRT1064.S" -OutFile $startupDestBoard - - Write-Host "[OK] Board support and official GCC reference files downloaded" + # Copy official GNU GCC Linker Script & Startup File from DFP pack into board directory + Write-Host "[INFO] Copying official NXP GNU GCC Linker Script and Startup File into board directory..." + $gccSource = Join-Path $packExtract "gcc" + if (Test-Path $gccSource) { + if (Test-Path "$gccSource/MIMXRT1064xxxxx_flexspi_nor.ld") { + Copy-Item -Path "$gccSource/MIMXRT1064xxxxx_flexspi_nor.ld" -Destination $BoardFilesDir -Force + } + if (Test-Path "$gccSource/startup_MIMXRT1064.S") { + Copy-Item -Path "$gccSource/startup_MIMXRT1064.S" -Destination $BoardFilesDir -Force + } + } + Write-Host "[OK] Board support and official GCC reference files copied" Write-Host "" # 3. Fetch CMSIS Core headers (standard ARM CMSIS-Core include files) @@ -186,6 +194,28 @@ try { Write-Host "[OK] CMSIS Core headers copied" Write-Host "" + # 4. Fetch official NXP KSZ8081 PHY driver (100% stock upstream) + Write-Host "[INFO] Downloading official KSZ8081 PHY driver..." + $phyRawBase = "https://raw.githubusercontent.com/eclipse-threadx/getting-started/master/NXP/MIMXRT1060-EVK/lib/MIMXRT1060-evk/src/components/phyksz8081" + $phyDestDir = Join-Path $ComponentsDir "phy" + New-Item -ItemType Directory -Path $phyDestDir -Force | Out-Null + Download-WithRetry -Uri "$phyRawBase/fsl_phy.c" -OutFile (Join-Path $phyDestDir "fsl_phy.c") + Download-WithRetry -Uri "$phyRawBase/fsl_phy.h" -OutFile (Join-Path $phyDestDir "fsl_phy.h") + Write-Host "[OK] Stock KSZ8081 PHY driver downloaded" + Write-Host "" + + # 5. Fetch official NetX Duo NXP Ethernet driver (100% stock upstream) + Write-Host "[INFO] Downloading official NetX Duo NXP Ethernet driver..." + $netxRawBase = "https://raw.githubusercontent.com/eclipse-threadx/getting-started/master/NXP/MIMXRT1060-EVK/lib/netx_driver" + $netxDriverDestDir = Join-Path $DriversDir "netx_driver" + $netxDriverGnuDir = Join-Path $netxDriverDestDir "gnu" + New-Item -ItemType Directory -Path $netxDriverGnuDir -Force | Out-Null + Download-WithRetry -Uri "$netxRawBase/src/nx_driver_imxrt1062.c" -OutFile (Join-Path $netxDriverDestDir "nx_driver_imxrt1062.c") + Download-WithRetry -Uri "$netxRawBase/src/nx_driver_imxrt1062.h" -OutFile (Join-Path $netxDriverDestDir "nx_driver_imxrt1062.h") + Download-WithRetry -Uri "$netxRawBase/src/gnu/nx_driver_imxrt1062_low_level.S" -OutFile (Join-Path $netxDriverGnuDir "nx_driver_imxrt1062_low_level.S") + Write-Host "[OK] Stock NetX Duo NXP Ethernet driver downloaded" + Write-Host "" + Write-Host "==========================================" Write-Host "[SUCCESS] NXP i.MX RT1064 drivers successfully fetched!" Write-Host "==========================================" diff --git a/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh index b0a6e439..c89fa6df 100644 --- a/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh +++ b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh @@ -113,12 +113,16 @@ curl -fsSL "${RAW_BASE}/dcd.h" -o "${BOARD_FILES_DIR}/dcd.h" curl -fsSL "${RAW_BASE}/xip/evkmimxrt1064_flexspi_nor_config.c" -o "${BOARD_FILES_DIR}/evkmimxrt1064_flexspi_nor_config.c" curl -fsSL "${RAW_BASE}/xip/evkmimxrt1064_flexspi_nor_config.h" -o "${BOARD_FILES_DIR}/evkmimxrt1064_flexspi_nor_config.h" -echo "[INFO] Downloading official NXP GNU GCC Linker Script and Startup File into board directory..." -NXP_GCC_BASE="https://raw.githubusercontent.com/nxp-mcuxpresso/mcux-sdk/main/devices/MIMXRT1064/gcc" -curl --retry 3 -fsSL "${NXP_GCC_BASE}/MIMXRT1064xxxxx_flexspi_nor.ld" -o "${BOARD_FILES_DIR}/MIMXRT1064xxxxx_flexspi_nor.ld" -curl --retry 3 -fsSL "${NXP_GCC_BASE}/startup_MIMXRT1064.S" -o "${BOARD_FILES_DIR}/startup_MIMXRT1064.S" - -echo "[OK] Board support and official GCC reference files downloaded" +echo "[INFO] Copying official NXP GNU GCC Linker Script and Startup File into board directory..." +if [ -d "${PACK_EXTRACT}/gcc" ]; then + if [ -f "${PACK_EXTRACT}/gcc/MIMXRT1064xxxxx_flexspi_nor.ld" ]; then + cp "${PACK_EXTRACT}/gcc/MIMXRT1064xxxxx_flexspi_nor.ld" "${BOARD_FILES_DIR}/" + fi + if [ -f "${PACK_EXTRACT}/gcc/startup_MIMXRT1064.S" ]; then + cp "${PACK_EXTRACT}/gcc/startup_MIMXRT1064.S" "${BOARD_FILES_DIR}/" + fi +fi +echo "[OK] Board support and official GCC reference files copied" echo "" # 3. Fetch CMSIS Core headers @@ -129,6 +133,26 @@ cp -r "${CMSIS_CLONE_DIR}/CMSIS/Core/Include/"* "${CMSIS_INCLUDE_DEST}/" echo "[OK] CMSIS Core headers copied" echo "" +# 4. Fetch official NXP KSZ8081 PHY driver (100% stock upstream) +echo "[INFO] Downloading official KSZ8081 PHY driver..." +PHY_RAW_BASE="https://raw.githubusercontent.com/eclipse-threadx/getting-started/master/NXP/MIMXRT1060-EVK/lib/MIMXRT1060-evk/src/components/phyksz8081" +mkdir -p "${COMPONENTS_DIR}/phy" +curl --retry 3 -fsSL "${PHY_RAW_BASE}/fsl_phy.c" -o "${COMPONENTS_DIR}/phy/fsl_phy.c" +curl --retry 3 -fsSL "${PHY_RAW_BASE}/fsl_phy.h" -o "${COMPONENTS_DIR}/phy/fsl_phy.h" +echo "[OK] Stock KSZ8081 PHY driver downloaded" +echo "" + +# 5. Fetch official NetX Duo NXP Ethernet driver (100% stock upstream) +echo "[INFO] Downloading official NetX Duo NXP Ethernet driver..." +NETX_RAW_BASE="https://raw.githubusercontent.com/eclipse-threadx/getting-started/master/NXP/MIMXRT1060-EVK/lib/netx_driver" +NETX_DIR="${DRIVERS_DIR}/netx_driver" +mkdir -p "${NETX_DIR}/gnu" +curl --retry 3 -fsSL "${NETX_RAW_BASE}/src/nx_driver_imxrt1062.c" -o "${NETX_DIR}/nx_driver_imxrt1062.c" +curl --retry 3 -fsSL "${NETX_RAW_BASE}/src/nx_driver_imxrt1062.h" -o "${NETX_DIR}/nx_driver_imxrt1062.h" +curl --retry 3 -fsSL "${NETX_RAW_BASE}/src/gnu/nx_driver_imxrt1062_low_level.S" -o "${NETX_DIR}/gnu/nx_driver_imxrt1062_low_level.S" +echo "[OK] Stock NetX Duo NXP Ethernet driver downloaded" +echo "" + echo "==========================================" echo "[SUCCESS] NXP i.MX RT1064 drivers successfully fetched!" echo "==========================================" diff --git a/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 b/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 index 3d2ba2ad..3fba4e35 100644 --- a/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 +++ b/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 @@ -9,16 +9,32 @@ # Contributors: # Ali Eissa - 2026 version. +param( + [string]$Resc +) + $BoardDir = Resolve-Path "$PSScriptRoot/.." -$ElfPath = Join-Path $BoardDir "build/mimxrt1064_threadx.elf" -$RescRelPath = "renode/mimxrt1064-evk.resc" -$RescFullPath = Join-Path $BoardDir $RescRelPath +$ServerElf = Join-Path $BoardDir "build/mimxrt1064_threadx.elf" +$ClientElf = Join-Path $BoardDir "build/mimxrt1064_client.elf" -if (-not (Test-Path $ElfPath)) { - Write-Error "Binary $ElfPath not found. Please build the project first using .\scripts\build.ps1" +if (-not (Test-Path $ServerElf)) { + Write-Error "Binary $ServerElf not found. Please build the project first using .\scripts\build.ps1" exit 1 } +# Determine RESC script: custom argument, or auto-detect multi-node vs single-node +if ($Resc) { + $RescRelPath = $Resc + $Mode = "Custom Script" +} elseif (Test-Path $ClientElf) { + $RescRelPath = "renode/mimxrt1064-network-multinode.resc" + $Mode = "Multi-Node Network Verification (Server: 192.168.0.100, Client: 192.168.0.101)" +} else { + $RescRelPath = "renode/mimxrt1064-evk.resc" + $Mode = "Single-Node Demo" +} +$RescFullPath = Join-Path $BoardDir $RescRelPath + # Find Renode executable $RenodeExe = (Get-Command renode -ErrorAction SilentlyContinue).Source if (-not $RenodeExe -and (Test-Path "C:\Program Files\Renode\renode.exe")) { @@ -34,10 +50,14 @@ Write-Host "==========================================" Write-Host "Starting Renode Simulation" Write-Host "==========================================" Write-Host "Renode: $RenodeExe" +Write-Host "Mode: $Mode" Write-Host "Script: $RescFullPath" -Write-Host "Target ELF: $ElfPath" +Write-Host "Server ELF: $ServerElf" +if (Test-Path $ClientElf) { + Write-Host "Client ELF: $ClientElf" +} Write-Host "" -Write-Host "Opening Renode Monitor and LPUART1 terminal analyzer..." +Write-Host "Opening Renode Monitor and LPUART1 terminal analyzer(s)..." Write-Host "To exit Renode, type 'quit' in the Renode Monitor or close the window." Write-Host "==========================================" diff --git a/NXP/MIMXRT1064-EVK/scripts/simulate.sh b/NXP/MIMXRT1064-EVK/scripts/simulate.sh index f47a8a43..80552a54 100644 --- a/NXP/MIMXRT1064-EVK/scripts/simulate.sh +++ b/NXP/MIMXRT1064-EVK/scripts/simulate.sh @@ -14,14 +14,25 @@ set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" BOARD_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" -ELF_PATH="${BOARD_DIR}/build/mimxrt1064_threadx.elf" -RESC_REL_PATH="renode/mimxrt1064-evk.resc" +SERVER_ELF="${BOARD_DIR}/build/mimxrt1064_threadx.elf" +CLIENT_ELF="${BOARD_DIR}/build/mimxrt1064_client.elf" -if [ ! -f "${ELF_PATH}" ]; then - echo "[ERROR] Binary ${ELF_PATH} not found. Please build first using ./scripts/build.sh" +if [ ! -f "${SERVER_ELF}" ]; then + echo "[ERROR] Binary ${SERVER_ELF} not found. Please build first using ./scripts/build.sh" exit 1 fi +if [ -n "$1" ]; then + RESC_REL_PATH="$1" + MODE="Custom Script" +elif [ -f "${CLIENT_ELF}" ]; then + RESC_REL_PATH="renode/mimxrt1064-network-multinode.resc" + MODE="Multi-Node Network Verification (Server: 192.168.0.100, Client: 192.168.0.101)" +else + RESC_REL_PATH="renode/mimxrt1064-evk.resc" + MODE="Single-Node Demo" +fi + RENODE_CMD="renode" if ! command -v renode &> /dev/null; then if [ -f "/opt/renode/renode" ]; then @@ -35,8 +46,12 @@ fi echo "==========================================" echo "Starting Renode Simulation" echo "==========================================" +echo "Mode: ${MODE}" echo "Script: ${BOARD_DIR}/${RESC_REL_PATH}" -echo "Target ELF: ${ELF_PATH}" +echo "Server ELF: ${SERVER_ELF}" +if [ -f "${CLIENT_ELF}" ]; then + echo "Client ELF: ${CLIENT_ELF}" +fi echo "" cd "${BOARD_DIR}" From ce7fb573918e339a541ca3986036762411a53d70 Mon Sep 17 00:00:00 2001 From: Ali Eissa Date: Sun, 13 Sep 2026 21:34:04 +0400 Subject: [PATCH 07/13] feat(mimxrt1064): add Hardware TRNG & Network Diagnostic Shell demo --- NXP/MIMXRT1064-EVK/CMakeLists.txt | 5 +- .../demos/netx_trng_console/CMakeLists.txt | 108 ++++++ .../app/demos/netx_trng_console/client_main.c | 262 +++++++++++++ .../app/demos/netx_trng_console/main.c | 352 ++++++++++++++++++ .../app/demos/netx_trng_console/nx_user.h | 21 ++ NXP/MIMXRT1064-EVK/app/trng.c | 91 +++++ NXP/MIMXRT1064-EVK/app/trng.h | 54 +++ .../renode/mimxrt1064-trng-console.resc | 51 +++ NXP/MIMXRT1064-EVK/scripts/simulate.ps1 | 17 +- NXP/MIMXRT1064-EVK/scripts/simulate.sh | 11 + 10 files changed, 969 insertions(+), 3 deletions(-) create mode 100644 NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/CMakeLists.txt create mode 100644 NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/client_main.c create mode 100644 NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/main.c create mode 100644 NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/nx_user.h create mode 100644 NXP/MIMXRT1064-EVK/app/trng.c create mode 100644 NXP/MIMXRT1064-EVK/app/trng.h create mode 100644 NXP/MIMXRT1064-EVK/renode/mimxrt1064-trng-console.resc diff --git a/NXP/MIMXRT1064-EVK/CMakeLists.txt b/NXP/MIMXRT1064-EVK/CMakeLists.txt index 46546835..6a26381a 100644 --- a/NXP/MIMXRT1064-EVK/CMakeLists.txt +++ b/NXP/MIMXRT1064-EVK/CMakeLists.txt @@ -28,8 +28,8 @@ project(mimxrt1064_threadx C CXX ASM) # Ensure executable output (elf, bin, hex) goes directly to the top-level build directory set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") -# Select the active demo to build (default: netx_echo, or threadx_basic) -set(ACTIVE_DEMO "netx_echo" CACHE STRING "Active demo name to build: netx_echo, threadx_basic") +# Select the active demo to build (default: netx_echo, netx_trng_console, or threadx_basic) +set(ACTIVE_DEMO "netx_echo" CACHE STRING "Active demo name to build: netx_echo, netx_trng_console, threadx_basic") # Set up paths for MCUXpresso SDK set(SDK_DIR "${CMAKE_CURRENT_LIST_DIR}/lib/mcux-sdk") @@ -118,6 +118,7 @@ add_library(board_bsp OBJECT app/startup/tx_initialize_low_level.S app/board_init.c app/console.c + app/trng.c app/sysmem.c app/syscalls.c ) diff --git a/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/CMakeLists.txt b/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/CMakeLists.txt new file mode 100644 index 00000000..a3a4ec5c --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/CMakeLists.txt @@ -0,0 +1,108 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. + +# Server Executable Target (mimxrt1064_threadx) +add_executable(${PROJECT_NAME} + main.c +) + +# Set compile definitions for server +target_compile_definitions(${PROJECT_NAME} + PRIVATE + CPU_MIMXRT1064DVL6A + XIP_EXTERNAL_FLASH=1 + XIP_BOOT_HEADER_ENABLE=1 + XIP_BOOT_HEADER_DCD_ENABLE=1 + FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE=1 + SDK_DEBUGCONSOLE=1 + SKIP_SYSCLK_INIT=1 + __STARTUP_INITIALIZE_NONCACHEDATA=1 +) + +# Include paths for server +target_include_directories(${PROJECT_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../.. + ${SDK_DIR}/drivers/netx_driver + ${SDK_DIR}/CMSIS/Include + ${SDK_DIR}/devices/MIMXRT1064 + ${SDK_DIR}/drivers + ${SDK_DIR}/board + ${SDK_DIR}/utilities + ${SDK_DIR}/components/uart + ${SDK_DIR}/components/phy + ${TX_USER_FILE_DIR} +) + +# Link libraries for server +target_link_libraries(${PROJECT_NAME} + PRIVATE + board_bsp + threadx + netxduo + netx_imxrt_driver + mcux_sdk +) + +# Apply GCC linker script and post-build outputs for server +set_target_linker(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/MIMXRT1064xxxxx_flexspi_nor.ld") +post_build(${PROJECT_NAME}) + +# Automated Verification Client Executable Target (mimxrt1064_client) +set(CLIENT_TARGET "mimxrt1064_client") +add_executable(${CLIENT_TARGET} + client_main.c +) + +# Set compile definitions for client +target_compile_definitions(${CLIENT_TARGET} + PRIVATE + NETX_CLIENT_NODE=1 + CPU_MIMXRT1064DVL6A + XIP_EXTERNAL_FLASH=1 + XIP_BOOT_HEADER_ENABLE=1 + XIP_BOOT_HEADER_DCD_ENABLE=1 + FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE=1 + SDK_DEBUGCONSOLE=1 + SKIP_SYSCLK_INIT=1 + __STARTUP_INITIALIZE_NONCACHEDATA=1 +) + +# Include paths for client +target_include_directories(${CLIENT_TARGET} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../.. + ${SDK_DIR}/drivers/netx_driver + ${SDK_DIR}/CMSIS/Include + ${SDK_DIR}/devices/MIMXRT1064 + ${SDK_DIR}/drivers + ${SDK_DIR}/board + ${SDK_DIR}/utilities + ${SDK_DIR}/components/uart + ${SDK_DIR}/components/phy + ${TX_USER_FILE_DIR} +) + +# Link libraries for client +target_link_libraries(${CLIENT_TARGET} + PRIVATE + board_bsp + threadx + netxduo + netx_imxrt_driver_client + mcux_sdk +) + +# Apply GCC linker script and post-build outputs for client +set_target_linker(${CLIENT_TARGET} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/MIMXRT1064xxxxx_flexspi_nor.ld") +post_build(${CLIENT_TARGET}) diff --git a/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/client_main.c b/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/client_main.c new file mode 100644 index 00000000..f95fff17 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/client_main.c @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available + * under the terms of the MIT license which is available at + * https://opensource.org/license/mit. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#include "board_init.h" +#include "console.h" +#include "ansi_colors.h" +#include "tx_api.h" +#include "nx_api.h" +#include +#include + +#define DEMO_STACK_SIZE 2048 +#define PACKET_SIZE 1536 +#define PACKET_POOL_SIZE ((PACKET_SIZE + sizeof(NX_PACKET)) * 24) +#define ARP_CACHE_SIZE 512 +#define CONSOLE_SERVER_PORT 23 + +#define CLIENT_IP_ADDRESS_VAL IP_ADDRESS(192, 168, 0, 101) +#define SERVER_IP_ADDRESS IP_ADDRESS(192, 168, 0, 100) +#define NETWORK_MASK_VAL IP_ADDRESS(255, 255, 255, 0) +#define GATEWAY_ADDRESS_VAL IP_ADDRESS(192, 168, 0, 1) + + + +static ULONG client_ip_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static ULONG client_test_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static ULONG client_arp_cache[ARP_CACHE_SIZE / sizeof(ULONG)]; + +__attribute__((section(".NonCacheable"))) +static uint8_t client_packet_pool_area[PACKET_POOL_SIZE]; + +static NX_PACKET_POOL client_pool; +static NX_IP client_ip; +static TX_THREAD client_test_thread; + +VOID nx_driver_imx(NX_IP_DRIVER *driver_req_ptr); +static void client_test_thread_entry(ULONG thread_input); + +int main(void) +{ + board_init(); + + printf(ANSI_BOLD ANSI_YELLOW "\r\n==================================================\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_YELLOW " MIMXRT1064 TRNG & Console Verification Client\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_YELLOW " Running on Simulated Node 2 (192.168.0.101)\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_YELLOW "==================================================\r\n\r\n" ANSI_RESET); + + tx_kernel_enter(); + + return 0; +} + +void tx_application_define(void *first_unused_memory) +{ + (void)first_unused_memory; + UINT status; + + nx_system_initialize(); + + status = nx_packet_pool_create(&client_pool, "Client Packet Pool", + PACKET_SIZE, client_packet_pool_area, PACKET_POOL_SIZE); + if (status != NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR " Failed to create packet pool: 0x%02X\r\n", status); + return; + } + + status = nx_ip_create(&client_ip, "Client IP", CLIENT_IP_ADDRESS_VAL, + NETWORK_MASK_VAL, &client_pool, nx_driver_imx, + client_ip_stack, DEMO_STACK_SIZE, 1); + if (status != NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR " Failed to create IP instance: 0x%02X\r\n", status); + return; + } + + nx_ip_gateway_address_set(&client_ip, GATEWAY_ADDRESS_VAL); + nx_arp_enable(&client_ip, (VOID *)client_arp_cache, ARP_CACHE_SIZE); + nx_icmp_enable(&client_ip); + nx_tcp_enable(&client_ip); + + status = tx_thread_create(&client_test_thread, "Client Test Thread", + client_test_thread_entry, 0, + client_test_stack, DEMO_STACK_SIZE, + 10, 10, TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR " Failed to create test thread: 0x%02X\r\n", status); + } +} + +static UINT send_and_receive(NX_TCP_SOCKET *socket, const char *cmd, char *rx_buf, size_t rx_buf_size, ULONG timeout) +{ + NX_PACKET *tx_packet = NX_NULL; + NX_PACKET *rx_packet = NX_NULL; + UINT status; + + status = nx_packet_allocate(&client_pool, &tx_packet, NX_TCP_PACKET, TX_WAIT_FOREVER); + if (status != NX_SUCCESS) return status; + + nx_packet_data_append(tx_packet, (VOID *)cmd, strlen(cmd), &client_pool, TX_WAIT_FOREVER); + status = nx_tcp_socket_send(socket, tx_packet, TX_WAIT_FOREVER); + if (status != NX_SUCCESS) return status; + + status = nx_tcp_socket_receive(socket, &rx_packet, timeout); + if (status == NX_SUCCESS && rx_packet != NX_NULL) + { + ULONG len = rx_packet->nx_packet_length; + if (len >= rx_buf_size) len = rx_buf_size - 1; + memcpy(rx_buf, rx_packet->nx_packet_prepend_ptr, len); + rx_buf[len] = '\0'; + nx_packet_release(rx_packet); + } + return status; +} + +static void client_test_thread_entry(ULONG thread_input) +{ + (void)thread_input; + UINT status; + ULONG actual_status; + int all_passed = 1; + char buffer[256]; + + printf(TAG_CLIENT " " MSG_INFO " Bringing Ethernet Link UP...\r\n"); + status = nx_ip_driver_direct_command(&client_ip, NX_LINK_ENABLE, &actual_status); + if (status == NX_SUCCESS || status == NX_ALREADY_ENABLED) + { + printf(TAG_CLIENT " " MSG_SUCCESS " Ethernet link is UP!\r\n"); + } + + printf(TAG_CLIENT " " MSG_INFO " Waiting for network convergence...\r\n"); + tx_thread_sleep(150); + + printf("\r\n" ANSI_BOLD ANSI_CYAN "==================================================\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN " Starting Hardware TRNG & Console Verification Suite\r\n" ANSI_RESET); + printf(ANSI_CYAN " Target Server: 192.168.0.100 (Port %d)\r\n" ANSI_RESET, CONSOLE_SERVER_PORT); + printf(ANSI_BOLD ANSI_CYAN "==================================================\r\n\r\n" ANSI_RESET); + + /* Test 1: ICMP Ping */ + printf(TAG_CLIENT " [Test 1/5] Testing ICMP Ping to 192.168.0.100...\r\n"); + NX_PACKET *ping_resp = NX_NULL; + status = nx_icmp_ping(&client_ip, SERVER_IP_ADDRESS, "TRNG_Ping", 9, &ping_resp, 200); + if (status == NX_SUCCESS && ping_resp != NX_NULL) + { + printf(TAG_CLIENT " " MSG_SUCCESS " ICMP Ping successful! Response from 192.168.0.100\r\n"); + nx_packet_release(ping_resp); + } + else + { + printf(TAG_CLIENT " " MSG_ERROR " ICMP Ping failed: 0x%02X\r\n", status); + all_passed = 0; + } + + tx_thread_sleep(30); + + /* Test 2: Connect to TCP Port 23 */ + printf("\r\n" TAG_CLIENT " [Test 2/5] Connecting to TRNG Console Server on port %d...\r\n", CONSOLE_SERVER_PORT); + NX_TCP_SOCKET client_socket; + status = nx_tcp_socket_create(&client_ip, &client_socket, "Client Shell Socket", + NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, + 512, NX_NULL, NX_NULL); + if (status != NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR " Failed to create TCP socket: 0x%02X\r\n", status); + return; + } + + nx_tcp_client_socket_bind(&client_socket, NX_ANY_PORT, TX_WAIT_FOREVER); + status = nx_tcp_client_socket_connect(&client_socket, SERVER_IP_ADDRESS, CONSOLE_SERVER_PORT, 200); + if (status == NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_SUCCESS " TCP Connected! Receiving greeting banner...\r\n"); + + /* Receive welcome banner */ + NX_PACKET *banner_packet = NX_NULL; + if (nx_tcp_socket_receive(&client_socket, &banner_packet, 100) == NX_SUCCESS) + { + nx_packet_release(banner_packet); + } + + /* Test 3: Query Hardware TRNG Entropy */ + printf("\r\n" TAG_CLIENT " [Test 3/5] Querying on-chip TRNG entropy ('trng')...\r\n"); + memset(buffer, 0, sizeof(buffer)); + status = send_and_receive(&client_socket, "trng\r\n", buffer, sizeof(buffer), 200); + if (status == NX_SUCCESS && strstr(buffer, "[TRNG] Hardware Entropy:")) + { + printf(TAG_CLIENT " " MSG_SUCCESS " Hardware TRNG Entropy Received:\r\n %s", buffer); + } + else + { + printf(TAG_CLIENT " " MSG_ERROR " TRNG query failed (status: 0x%02X)\r\n", status); + all_passed = 0; + } + + /* Test 4: Remote LED Control */ + printf("\r\n" TAG_CLIENT " [Test 4/5] Testing Remote LED Control ('led toggle')...\r\n"); + memset(buffer, 0, sizeof(buffer)); + status = send_and_receive(&client_socket, "led toggle\r\n", buffer, sizeof(buffer), 200); + if (status == NX_SUCCESS && strstr(buffer, "[LED] State: TOGGLED")) + { + printf(TAG_CLIENT " " MSG_SUCCESS " Remote LED toggle acknowledged by server!\r\n"); + } + else + { + printf(TAG_CLIENT " " MSG_ERROR " LED control failed (status: 0x%02X)\r\n", status); + all_passed = 0; + } + + /* Test 5: Target Info Query */ + printf("\r\n" TAG_CLIENT " [Test 5/5] Querying processor and RTOS status ('info')...\r\n"); + memset(buffer, 0, sizeof(buffer)); + status = send_and_receive(&client_socket, "info\r\n", buffer, sizeof(buffer), 200); + if (status == NX_SUCCESS && strstr(buffer, "MIMXRT1064-EVK")) + { + printf(TAG_CLIENT " " MSG_SUCCESS " Processor & ThreadX status verified:\r\n %s", buffer); + } + else + { + printf(TAG_CLIENT " " MSG_ERROR " Info query failed (status: 0x%02X)\r\n", status); + all_passed = 0; + } + + /* Graceful disconnect */ + send_and_receive(&client_socket, "quit\r\n", buffer, sizeof(buffer), 50); + nx_tcp_socket_disconnect(&client_socket, 10); + } + else + { + printf(TAG_CLIENT " " MSG_ERROR " Failed to connect to server: 0x%02X\r\n", status); + all_passed = 0; + } + + nx_tcp_client_socket_unbind(&client_socket); + nx_tcp_socket_delete(&client_socket); + + printf("\r\n==================================================\r\n"); + if (all_passed) + { + printf(ANSI_BOLD ANSI_GREEN " [VERIFICATION SUCCESS] ALL TRNG & CONSOLE TESTS PASSED!\r\n" ANSI_RESET); + } + else + { + printf(ANSI_BOLD ANSI_RED " [VERIFICATION FAILED] One or more tests failed.\r\n" ANSI_RESET); + } + printf("==================================================\r\n\r\n"); + + while (1) + { + tx_thread_sleep(100); + } +} diff --git a/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/main.c b/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/main.c new file mode 100644 index 00000000..b107371b --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/main.c @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available + * under the terms of the MIT license which is available at + * https://opensource.org/license/mit. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#include "board_init.h" +#include "console.h" +#include "ansi_colors.h" +#include "trng.h" +#include "tx_api.h" +#include "nx_api.h" +#include +#include + +#define DEMO_STACK_SIZE 2048 +#define PACKET_SIZE 1536 +#define PACKET_POOL_SIZE ((PACKET_SIZE + sizeof(NX_PACKET)) * 24) +#define ARP_CACHE_SIZE 512 +#define CONSOLE_SERVER_PORT 23 + +#define IP_ADDRESS_VAL IP_ADDRESS(192, 168, 0, 100) +#define NETWORK_MASK_VAL IP_ADDRESS(255, 255, 255, 0) +#define GATEWAY_ADDRESS_VAL IP_ADDRESS(192, 168, 0, 1) + +#define TAG_SHELL "\x1b[38;5;243m[Shell]" +#define TAG_TRNG "\x1b[38;5;243m[TRNG]" + +/* Memory buffers */ +static ULONG ip_thread_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static ULONG heartbeat_thread_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static ULONG shell_thread_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static ULONG arp_cache_area[ARP_CACHE_SIZE / sizeof(ULONG)]; + +__attribute__((section(".NonCacheable"))) +static uint8_t packet_pool_area[PACKET_POOL_SIZE]; + +/* NetX Duo & ThreadX objects */ +static NX_PACKET_POOL pool_0; +static NX_IP ip_0; +static TX_THREAD heartbeat_thread; +static TX_THREAD shell_thread; + +/* External driver entry point */ +VOID nx_driver_imx(NX_IP_DRIVER *driver_req_ptr); + +/* Thread prototypes */ +static void heartbeat_thread_entry(ULONG thread_input); +static void shell_thread_entry(ULONG thread_input); + +int main(void) +{ + /* Initialize MPU, clocks (600 MHz), pins, LED GPIO, console, and ENET */ + board_init(); + + /* Initialize on-chip Hardware TRNG */ + trng_init(); + + printf(ANSI_BOLD ANSI_CYAN "\r\n==================================================\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN " Eclipse ThreadX & NetX Duo on NXP i.MX RT1064-EVK\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN " Hardware TRNG & Network Diagnostic Shell (Renode)\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN "==================================================\r\n\r\n" ANSI_RESET); + + printf(TAG_SYSTEM " " MSG_INFO "Core Clock: %lu MHz | Tick Rate: %u Hz\r\n" ANSI_RESET, + SystemCoreClock / 1000000UL, TX_TIMER_TICKS_PER_SECOND); + printf(TAG_TRNG " " MSG_INFO "On-chip True Random Number Generator initialized @ 0x400CC000\r\n" ANSI_RESET); + + /* Enter ThreadX kernel */ + tx_kernel_enter(); + + return 0; +} + +void tx_application_define(void *first_unused_memory) +{ + (void)first_unused_memory; + UINT status; + + printf(TAG_NETWORK " " MSG_INFO "Initializing NetX Duo System...\r\n" ANSI_RESET); + nx_system_initialize(); + + /* 1. Create packet pool in NonCacheable memory */ + status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", + PACKET_SIZE, packet_pool_area, PACKET_POOL_SIZE); + if (status != NX_SUCCESS) + { + printf(TAG_NETWORK " " MSG_ERROR "Failed to create packet pool: 0x%02X\r\n" ANSI_RESET, status); + return; + } + printf(TAG_NETWORK " " MSG_SUCCESS "Packet pool created (%u bytes in NonCacheable memory)\r\n" ANSI_RESET, + (unsigned int)sizeof(packet_pool_area)); + + /* 2. Create IP instance */ + status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS_VAL, + NETWORK_MASK_VAL, &pool_0, nx_driver_imx, + ip_thread_stack, DEMO_STACK_SIZE, 1); + if (status != NX_SUCCESS) + { + printf(TAG_NETWORK " " MSG_ERROR "Failed to create IP instance: 0x%02X\r\n" ANSI_RESET, status); + return; + } + printf(TAG_NETWORK " " MSG_SUCCESS "IP instance created\r\n" ANSI_RESET); + + /* 3. Gateway & Services */ + nx_ip_gateway_address_set(&ip_0, GATEWAY_ADDRESS_VAL); + + printf(TAG_NETWORK " " MSG_INFO "Enabling ARP...\r\n" ANSI_RESET); + nx_arp_enable(&ip_0, (VOID *)arp_cache_area, ARP_CACHE_SIZE); + + printf(TAG_NETWORK " " MSG_INFO "Enabling ICMP (Ping responder)...\r\n" ANSI_RESET); + nx_icmp_enable(&ip_0); + + printf(TAG_NETWORK " " MSG_INFO "Enabling TCP...\r\n" ANSI_RESET); + nx_tcp_enable(&ip_0); + + /* 4. Create Heartbeat Thread */ + status = tx_thread_create(&heartbeat_thread, "Heartbeat Thread", + heartbeat_thread_entry, 0, + heartbeat_thread_stack, DEMO_STACK_SIZE, + 15, 15, TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) + { + printf(TAG_SYSTEM " " MSG_ERROR "Failed to create Heartbeat thread: 0x%02X\r\n" ANSI_RESET, status); + } + + /* 5. Create TRNG Console Shell Thread */ + status = tx_thread_create(&shell_thread, "TRNG Shell Thread", + shell_thread_entry, 0, + shell_thread_stack, DEMO_STACK_SIZE, + 10, 10, TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) + { + printf(TAG_SYSTEM " " MSG_ERROR "Failed to create Shell thread: 0x%02X\r\n" ANSI_RESET, status); + } + + printf(TAG_NETWORK " " MSG_SUCCESS "Network threads registered successfully.\r\n" ANSI_RESET); +} + +static void heartbeat_thread_entry(ULONG thread_input) +{ + (void)thread_input; + UINT status; + ULONG actual_status; + ULONG ip_address, network_mask; + + printf(TAG_NETWORK " " MSG_INFO "Bringing Ethernet Link UP...\r\n" ANSI_RESET); + status = nx_ip_driver_direct_command(&ip_0, NX_LINK_ENABLE, &actual_status); + if (status == NX_SUCCESS || status == NX_ALREADY_ENABLED) + { + printf(TAG_NETWORK " " MSG_SUCCESS "Ethernet link is UP!\r\n" ANSI_RESET); + } + else + { + printf(TAG_NETWORK " " MSG_ERROR "nx_ip_driver_direct_command NX_LINK_ENABLE status: 0x%02X\r\n" ANSI_RESET, status); + } + + nx_ip_address_get(&ip_0, &ip_address, &network_mask); + printf("\r\n" ANSI_BOLD ANSI_GREEN "================ Network Ready ================\r\n" ANSI_RESET); + printf(ANSI_GREEN " Static IPv4 : %lu.%lu.%lu.%lu\r\n" ANSI_RESET, + (ip_address >> 24) & 0xFF, (ip_address >> 16) & 0xFF, + (ip_address >> 8) & 0xFF, ip_address & 0xFF); + printf(ANSI_GREEN " Subnet Mask : %lu.%lu.%lu.%lu\r\n" ANSI_RESET, + (network_mask >> 24) & 0xFF, (network_mask >> 16) & 0xFF, + (network_mask >> 8) & 0xFF, network_mask & 0xFF); + printf(ANSI_GREEN " Services : ICMP Ping, Hardware TRNG Shell (TCP Port %d)\r\n" ANSI_RESET, CONSOLE_SERVER_PORT); + printf(ANSI_BOLD ANSI_GREEN "===============================================\r\n\r\n" ANSI_RESET); + + while (1) + { + tx_thread_sleep(50); + USER_LED_TOGGLE(); + } +} + +static void send_tcp_response(NX_TCP_SOCKET *socket, const char *msg) +{ + NX_PACKET *tx_packet = NX_NULL; + UINT status; + size_t len = strlen(msg); + + status = nx_packet_allocate(&pool_0, &tx_packet, NX_TCP_PACKET, TX_WAIT_FOREVER); + if (status == NX_SUCCESS) + { + nx_packet_data_append(tx_packet, (VOID *)msg, len, &pool_0, TX_WAIT_FOREVER); + nx_tcp_socket_send(socket, tx_packet, TX_WAIT_FOREVER); + } +} + +static void shell_thread_entry(ULONG thread_input) +{ + NX_TCP_SOCKET shell_socket; + NX_PACKET *packet_ptr; + UINT status; + char line_buffer[128]; + char resp_buffer[256]; + + (void)thread_input; + + status = nx_tcp_socket_create(&ip_0, &shell_socket, "TRNG Shell Socket", + NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, + 1024, NX_NULL, NX_NULL); + if (status != NX_SUCCESS) + { + printf(TAG_SHELL " " MSG_ERROR "Failed to create TCP socket: 0x%02X\r\n" ANSI_RESET, status); + return; + } + + printf(TAG_SHELL " " MSG_INFO "TRNG Diagnostic Shell listening on port %d\r\n" ANSI_RESET, CONSOLE_SERVER_PORT); + + while (1) + { + status = nx_tcp_server_socket_listen(&ip_0, CONSOLE_SERVER_PORT, &shell_socket, 5, NX_NULL); + if (status != NX_SUCCESS) + { + nx_tcp_server_socket_unlisten(&ip_0, CONSOLE_SERVER_PORT); + tx_thread_sleep(10); + continue; + } + + status = nx_tcp_server_socket_accept(&shell_socket, NX_WAIT_FOREVER); + if (status == NX_SUCCESS) + { + ULONG peer_ip = 0; + ULONG peer_port = 0; + nx_tcp_socket_peer_info_get(&shell_socket, &peer_ip, &peer_port); + + printf(TAG_SHELL " " MSG_SUCCESS "Client connected from %lu.%lu.%lu.%lu:%lu\r\n" ANSI_RESET, + (peer_ip >> 24) & 0xFF, (peer_ip >> 16) & 0xFF, + (peer_ip >> 8) & 0xFF, peer_ip & 0xFF, peer_port); + + /* Send Welcome Banner */ + send_tcp_response(&shell_socket, + "\r\n==================================================\r\n" + " NXP i.MX RT1064-EVK Hardware TRNG Console\r\n" + " Eclipse ThreadX & NetX Duo Management Shell\r\n" + "==================================================\r\n" + "Type 'help' for available commands.\r\n\r\nmimxrt1064> "); + + while (1) + { + status = nx_tcp_socket_receive(&shell_socket, &packet_ptr, NX_WAIT_FOREVER); + if (status != NX_SUCCESS) + { + break; + } + + ULONG copy_len = packet_ptr->nx_packet_length; + if (copy_len >= sizeof(line_buffer)) + { + copy_len = sizeof(line_buffer) - 1; + } + memcpy(line_buffer, packet_ptr->nx_packet_prepend_ptr, copy_len); + line_buffer[copy_len] = '\0'; + nx_packet_release(packet_ptr); + + /* Trim trailing CRLF */ + char *p = line_buffer + strlen(line_buffer) - 1; + while (p >= line_buffer && (*p == '\r' || *p == '\n' || *p == ' ')) + { + *p-- = '\0'; + } + + if (strlen(line_buffer) == 0) + { + send_tcp_response(&shell_socket, "mimxrt1064> "); + continue; + } + + printf(TAG_SHELL " Received command: '%s'\r\n", line_buffer); + + if (strcmp(line_buffer, "help") == 0) + { + send_tcp_response(&shell_socket, + "Available commands:\r\n" + " trng - Read 4x 32-bit hardware entropy words from on-chip TRNG\r\n" + " info - Print processor clock, memory, and ThreadX ticks\r\n" + " led on|off|toggle - Control or toggle User LED D18\r\n" + " ping - Connection health check\r\n" + " quit - Terminate console session\r\n\r\nmimxrt1064> "); + } + else if (strcmp(line_buffer, "trng") == 0 || strcmp(line_buffer, "rand") == 0) + { + uint32_t r1 = 0, r2 = 0, r3 = 0, r4 = 0; + trng_get_random_u32(&r1); + trng_get_random_u32(&r2); + trng_get_random_u32(&r3); + trng_get_random_u32(&r4); + + snprintf(resp_buffer, sizeof(resp_buffer), + "[TRNG] Hardware Entropy: 0x%08lX 0x%08lX 0x%08lX 0x%08lX\r\n\r\nmimxrt1064> ", + (unsigned long)r1, (unsigned long)r2, (unsigned long)r3, (unsigned long)r4); + printf(TAG_TRNG " Generated entropy: 0x%08lX 0x%08lX 0x%08lX 0x%08lX\r\n", + (unsigned long)r1, (unsigned long)r2, (unsigned long)r3, (unsigned long)r4); + send_tcp_response(&shell_socket, resp_buffer); + } + else if (strcmp(line_buffer, "info") == 0) + { + snprintf(resp_buffer, sizeof(resp_buffer), + "[INFO] Target: NXP MIMXRT1064-EVK (ARM Cortex-M7 @ 600 MHz)\r\n" + "[INFO] RTOS: Eclipse ThreadX | Uptime: %lu ticks\r\n" + "[INFO] TRNG: On-chip hardware entropy engine active @ 0x400CC000\r\n\r\nmimxrt1064> ", + tx_time_get()); + send_tcp_response(&shell_socket, resp_buffer); + } + else if (strncmp(line_buffer, "led", 3) == 0) + { + if (strstr(line_buffer, "on")) + { + USER_LED_ON(); + send_tcp_response(&shell_socket, "[LED] State: ON\r\n\r\nmimxrt1064> "); + } + else if (strstr(line_buffer, "off")) + { + USER_LED_OFF(); + send_tcp_response(&shell_socket, "[LED] State: OFF\r\n\r\nmimxrt1064> "); + } + else + { + USER_LED_TOGGLE(); + send_tcp_response(&shell_socket, "[LED] State: TOGGLED\r\n\r\nmimxrt1064> "); + } + } + else if (strcmp(line_buffer, "ping") == 0) + { + send_tcp_response(&shell_socket, "[PONG] Network connection alive\r\n\r\nmimxrt1064> "); + } + else if (strcmp(line_buffer, "quit") == 0 || strcmp(line_buffer, "exit") == 0) + { + send_tcp_response(&shell_socket, "Goodbye!\r\n"); + break; + } + else + { + send_tcp_response(&shell_socket, "Unknown command. Type 'help' for options.\r\n\r\nmimxrt1064> "); + } + } + + printf(TAG_SHELL " Client disconnected\r\n"); + nx_tcp_socket_disconnect(&shell_socket, 10); + nx_tcp_server_socket_unaccept(&shell_socket); + } + + nx_tcp_server_socket_unlisten(&ip_0, CONSOLE_SERVER_PORT); + } +} diff --git a/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/nx_user.h b/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/nx_user.h new file mode 100644 index 00000000..eccf436a --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/nx_user.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available + * under the terms of the MIT license which is available at + * https://opensource.org/license/mit. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#ifndef NX_USER_H +#define NX_USER_H + +#define NX_DISABLE_IPV6 +#define NX_PHYSICAL_HEADER 16 +#define NX_ENABLE_EXTENDED_NOTIFY_SUPPORT + +#endif /* NX_USER_H */ diff --git a/NXP/MIMXRT1064-EVK/app/trng.c b/NXP/MIMXRT1064-EVK/app/trng.c new file mode 100644 index 00000000..6424f67f --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/trng.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available + * under the terms of the MIT license which is available at + * https://opensource.org/license/mit. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#include "trng.h" +#include "fsl_device_registers.h" +#include "fsl_clock.h" +#include + +#define TRNG_TIMEOUT_CYCLES 1000000UL + +int trng_init(void) +{ + /* Enable TRNG peripheral clock in CCM */ + CLOCK_EnableClock(kCLOCK_Trng); + + /* Check if TRNG is reporting error, clear if needed */ + if (TRNG->MCTL & TRNG_MCTL_ERR_MASK) + { + /* Clear error by resetting to defaults */ + TRNG->MCTL |= TRNG_MCTL_RST_DEF_MASK; + } + + return 0; +} + +int trng_get_random_u32(uint32_t *random_val) +{ + uint32_t timeout = TRNG_TIMEOUT_CYCLES; + + if (!random_val) + { + return -1; + } + + /* Wait for Entropy Valid (ENT_VAL) bit */ + while (!(TRNG->MCTL & TRNG_MCTL_ENT_VAL_MASK)) + { + if (--timeout == 0) + { + return -2; /* Timeout waiting for entropy */ + } + } + + /* Read a 32-bit random word from the first entropy register */ + *random_val = TRNG->ENT[0]; + + return 0; +} + +int trng_get_random_data(void *buffer, size_t length) +{ + uint8_t *out = (uint8_t *)buffer; + size_t offset = 0; + uint32_t rand_word; + int status; + + if (!buffer) + { + return -1; + } + + while (offset < length) + { + status = trng_get_random_u32(&rand_word); + if (status != 0) + { + return status; + } + + size_t chunk = length - offset; + if (chunk > sizeof(uint32_t)) + { + chunk = sizeof(uint32_t); + } + + memcpy(out + offset, &rand_word, chunk); + offset += chunk; + } + + return (int)length; +} diff --git a/NXP/MIMXRT1064-EVK/app/trng.h b/NXP/MIMXRT1064-EVK/app/trng.h new file mode 100644 index 00000000..6e1c0aa9 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/app/trng.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available + * under the terms of the MIT license which is available at + * https://opensource.org/license/mit. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#ifndef TRNG_H +#define TRNG_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize the on-chip True Random Number Generator (TRNG) peripheral. + * Enables TRNG peripheral clock gating and initializes default sampling parameters. + * + * @return 0 on success, non-zero on error. + */ +int trng_init(void); + +/** + * @brief Read a single 32-bit hardware random word from TRNG entropy registers. + * + * @param[out] random_val Pointer to uint32_t to receive the random word. + * @return 0 on success, non-zero on error or timeout. + */ +int trng_get_random_u32(uint32_t *random_val); + +/** + * @brief Fill a buffer with hardware random bytes from TRNG entropy registers. + * + * @param[out] buffer Output buffer to receive random bytes. + * @param[in] length Number of bytes to generate. + * @return Number of bytes filled on success, or negative on error. + */ +int trng_get_random_data(void *buffer, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif /* TRNG_H */ diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-trng-console.resc b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-trng-console.resc new file mode 100644 index 00000000..ca877e09 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-trng-console.resc @@ -0,0 +1,51 @@ +:name: MIMXRT1064-EVK Hardware TRNG & Console Two-Node Verification +:description: This script creates two MIMXRT1064-EVK nodes connected via a virtual Ethernet switch: +: - "server": TRNG Console Server on 192.168.0.100 (TCP Port 23, ICMP Ping) +: - "client": Verification Client on 192.168.0.101 (tests TRNG entropy, LED control, Info) + +# 1. Create Virtual Ethernet Switch +emulation CreateSwitch "switch" + +# 2. Server Machine (192.168.0.100) +mach create "server" +machine LoadPlatformDescription $ORIGIN/mimxrt1064-evk.repl +connector Connect sysbus.enet switch +showAnalyzer sysbus.lpuart1 + +$bin_server?=$ORIGIN/../build/mimxrt1064_threadx.elf +macro reset_server +""" + cpu VectorTableOffset 0x70002000 + sysbus LoadELF $bin_server + cpu PC `sysbus ReadDoubleWord 0x70002004` + cpu SP `sysbus ReadDoubleWord 0x70002000` +""" +runMacro $reset_server + +# 3. Client Machine (192.168.0.101) +mach create "client" +machine LoadPlatformDescription $ORIGIN/mimxrt1064-evk.repl +connector Connect sysbus.enet switch +showAnalyzer sysbus.lpuart1 + +$bin_client?=$ORIGIN/../build/mimxrt1064_client.elf +macro reset_client +""" + cpu VectorTableOffset 0x70002000 + sysbus LoadELF $bin_client + cpu PC `sysbus ReadDoubleWord 0x70002004` + cpu SP `sysbus ReadDoubleWord 0x70002000` +""" +runMacro $reset_client + +# 4. Global reset macro to reset both nodes simultaneously +macro reset +""" + mach set "server" + runMacro $reset_server + mach set "client" + runMacro $reset_client +""" + +# 5. Start Simulation +start diff --git a/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 b/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 index 3fba4e35..842c5de4 100644 --- a/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 +++ b/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 @@ -22,10 +22,25 @@ if (-not (Test-Path $ServerElf)) { exit 1 } -# Determine RESC script: custom argument, or auto-detect multi-node vs single-node +# Determine RESC script: custom argument, or auto-detect based on cached demo +$cachedDemo = "" +$cacheFile = Join-Path $BoardDir "build/CMakeCache.txt" +if (Test-Path $cacheFile) { + $match = Select-String -Path $cacheFile -Pattern "^ACTIVE_DEMO:STRING=(.*)$" + if ($match) { + $cachedDemo = $match.Matches.Groups[1].Value.Trim() + } +} + if ($Resc) { $RescRelPath = $Resc $Mode = "Custom Script" +} elseif ($cachedDemo -eq "netx_trng_console") { + $RescRelPath = "renode/mimxrt1064-trng-console.resc" + $Mode = "Hardware TRNG Console (Server: 192.168.0.100, Client: 192.168.0.101)" +} elseif ($cachedDemo -eq "netx_echo") { + $RescRelPath = "renode/mimxrt1064-network-multinode.resc" + $Mode = "Multi-Node Network Echo Verification (Server: 192.168.0.100, Client: 192.168.0.101)" } elseif (Test-Path $ClientElf) { $RescRelPath = "renode/mimxrt1064-network-multinode.resc" $Mode = "Multi-Node Network Verification (Server: 192.168.0.100, Client: 192.168.0.101)" diff --git a/NXP/MIMXRT1064-EVK/scripts/simulate.sh b/NXP/MIMXRT1064-EVK/scripts/simulate.sh index 80552a54..dcf574be 100644 --- a/NXP/MIMXRT1064-EVK/scripts/simulate.sh +++ b/NXP/MIMXRT1064-EVK/scripts/simulate.sh @@ -22,9 +22,20 @@ if [ ! -f "${SERVER_ELF}" ]; then exit 1 fi +CACHED_DEMO="" +if [ -f "${BOARD_DIR}/build/CMakeCache.txt" ]; then + CACHED_DEMO=$(grep -E "^ACTIVE_DEMO:STRING=" "${BOARD_DIR}/build/CMakeCache.txt" | cut -d'=' -f2 | tr -d ' \r\n') +fi + if [ -n "$1" ]; then RESC_REL_PATH="$1" MODE="Custom Script" +elif [ "$CACHED_DEMO" = "netx_trng_console" ]; then + RESC_REL_PATH="renode/mimxrt1064-trng-console.resc" + MODE="Hardware TRNG Console (Server: 192.168.0.100, Client: 192.168.0.101)" +elif [ "$CACHED_DEMO" = "netx_echo" ]; then + RESC_REL_PATH="renode/mimxrt1064-network-multinode.resc" + MODE="Multi-Node Network Echo Verification (Server: 192.168.0.100, Client: 192.168.0.101)" elif [ -f "${CLIENT_ELF}" ]; then RESC_REL_PATH="renode/mimxrt1064-network-multinode.resc" MODE="Multi-Node Network Verification (Server: 192.168.0.100, Client: 192.168.0.101)" From 4e7be41a56f397e4909296dd1ff0cd4019d66179 Mon Sep 17 00:00:00 2001 From: Ali Eissa Date: Mon, 14 Sep 2026 04:47:38 +0400 Subject: [PATCH 08/13] feat(MIMXRT1064): Renode CI for MIMXRT1064 and CMake architecture overhaul --- NXP/MIMXRT1064-EVK/CMakeLists.txt | 48 ++- NXP/MIMXRT1064-EVK/NOTICE.md | 34 ++- NXP/MIMXRT1064-EVK/README.md | 286 +++++++++++++----- NXP/MIMXRT1064-EVK/app/MIMXRT1062.h | 13 + .../app/demos/netx_echo/CMakeLists.txt | 17 +- .../demos/netx_trng_console/CMakeLists.txt | 17 +- .../app/demos/netx_trng_console/nx_user.h | 21 -- .../app/demos/threadx_basic/CMakeLists.txt | 14 +- .../app/demos/threadx_basic/main.c | 2 +- .../startup/MIMXRT1064xxxxx_flexspi_nor.ld | 4 + .../app/startup/tx_initialize_low_level.S | 2 +- NXP/MIMXRT1064-EVK/cmake/utilities.cmake | 10 +- .../demos/netx_echo => lib/netxduo}/nx_user.h | 0 NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc | 11 + .../renode/mimxrt1064-headless-multinode.resc | 43 +++ .../renode/mimxrt1064-headless-single.resc | 26 ++ .../renode/mimxrt1064-network-multinode.resc | 11 + .../renode/mimxrt1064-trng-console.resc | 11 + NXP/MIMXRT1064-EVK/scripts/build.ps1 | 32 +- NXP/MIMXRT1064-EVK/scripts/build.sh | 31 +- NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 | 2 +- NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh | 2 +- NXP/MIMXRT1064-EVK/scripts/simulate.ps1 | 107 +++++-- NXP/MIMXRT1064-EVK/scripts/simulate.sh | 122 ++++++-- NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 | 153 ++++++++++ NXP/MIMXRT1064-EVK/scripts/test_headless.sh | 150 +++++++++ 26 files changed, 939 insertions(+), 230 deletions(-) delete mode 100644 NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/nx_user.h rename NXP/MIMXRT1064-EVK/{app/demos/netx_echo => lib/netxduo}/nx_user.h (100%) create mode 100644 NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc create mode 100644 NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc create mode 100644 NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 create mode 100644 NXP/MIMXRT1064-EVK/scripts/test_headless.sh diff --git a/NXP/MIMXRT1064-EVK/CMakeLists.txt b/NXP/MIMXRT1064-EVK/CMakeLists.txt index 6a26381a..83dad0c1 100644 --- a/NXP/MIMXRT1064-EVK/CMakeLists.txt +++ b/NXP/MIMXRT1064-EVK/CMakeLists.txt @@ -25,11 +25,8 @@ include(utilities) # Define the Project project(mimxrt1064_threadx C CXX ASM) -# Ensure executable output (elf, bin, hex) goes directly to the top-level build directory -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") - -# Select the active demo to build (default: netx_echo, netx_trng_console, or threadx_basic) -set(ACTIVE_DEMO "netx_echo" CACHE STRING "Active demo name to build: netx_echo, netx_trng_console, threadx_basic") +# Select demo to build: all (default), threadx_basic, netx_echo, netx_trng_console +set(ACTIVE_DEMO "all" CACHE STRING "Active demo name to build: all, netx_echo, netx_trng_console, threadx_basic") # Set up paths for MCUXpresso SDK set(SDK_DIR "${CMAKE_CURRENT_LIST_DIR}/lib/mcux-sdk") @@ -37,17 +34,14 @@ if(NOT EXISTS "${SDK_DIR}/devices/MIMXRT1064/MIMXRT1064.h") message(FATAL_ERROR "NXP SDK dependencies missing! Please run 'scripts/fetch_sdk.ps1' or 'scripts/fetch_sdk.sh' first.") endif() -# Dynamic Middleware Auto-Detection -# Check if the active demo uses NetX Duo by looking for nx_user.h -if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/nx_user.h") - set(USE_NETXDUO ON) +# Dynamic Middleware Configuration +if(NOT ACTIVE_DEMO STREQUAL "all" AND EXISTS "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/nx_user.h") set(NX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/nx_user.h" CACHE STRING "Enable NetX Duo user configuration" FORCE) else() - set(USE_NETXDUO OFF) + set(NX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/lib/netxduo/nx_user.h" CACHE STRING "Enable NetX Duo user configuration" FORCE) endif() -# Check if the active demo has custom tx_user.h; otherwise fallback to lib/threadx/tx_user.h -if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/tx_user.h") +if(NOT ACTIVE_DEMO STREQUAL "all" AND EXISTS "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/tx_user.h") set(TX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/tx_user.h" CACHE STRING "Enable TX user configuration" FORCE) set(TX_USER_FILE_DIR "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}") else() @@ -59,12 +53,10 @@ endif() set(THREADX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../libs/threadx") add_subdirectory(${THREADX_DIR} threadx) -if(USE_NETXDUO) - # Compile NetX Duo TCP/IP Stack from root shared libs submodule - set(NXD_ENABLE_FILE_SERVERS OFF CACHE BOOL "Disable FileX dependency in NetX Duo" FORCE) - set(NETXDUO_DIR "${CMAKE_CURRENT_LIST_DIR}/../../libs/netxduo") - add_subdirectory(${NETXDUO_DIR} netxduo) -endif() +# Compile NetX Duo TCP/IP Stack from root shared libs submodule (cached for networking demos) +set(NXD_ENABLE_FILE_SERVERS OFF CACHE BOOL "Disable FileX dependency in NetX Duo" FORCE) +set(NETXDUO_DIR "${CMAKE_CURRENT_LIST_DIR}/../../libs/netxduo") +add_subdirectory(${NETXDUO_DIR} netxduo) # Compile the NXP MCUXpresso Driver & Board Library as an Object Library set(SDK_TARGET mcux_sdk) @@ -153,9 +145,8 @@ target_link_libraries(board_bsp threadx ) -# 2. Define conditional NetX Duo driver library target -if(USE_NETXDUO) - add_library(netx_imxrt_driver OBJECT +# 2. Define NetX Duo driver library targets (cached for networking demos) +add_library(netx_imxrt_driver OBJECT ${SDK_DIR}/drivers/netx_driver/nx_driver_imxrt1062.c ${SDK_DIR}/drivers/netx_driver/gnu/nx_driver_imxrt1062_low_level.S ${SDK_DIR}/components/phy/fsl_phy.c @@ -179,7 +170,7 @@ if(USE_NETXDUO) ${SDK_DIR}/drivers/netx_driver ${SDK_DIR}/components/phy ${CMAKE_CURRENT_LIST_DIR}/app - ${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO} + ${CMAKE_CURRENT_LIST_DIR}/lib/netxduo ${SDK_DIR}/CMSIS/Include ${SDK_DIR}/devices/MIMXRT1064 ${SDK_DIR}/drivers @@ -222,7 +213,7 @@ if(USE_NETXDUO) ${SDK_DIR}/drivers/netx_driver ${SDK_DIR}/components/phy ${CMAKE_CURRENT_LIST_DIR}/app - ${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO} + ${CMAKE_CURRENT_LIST_DIR}/lib/netxduo ${SDK_DIR}/CMSIS/Include ${SDK_DIR}/devices/MIMXRT1064 ${SDK_DIR}/drivers @@ -239,7 +230,12 @@ if(USE_NETXDUO) mcux_sdk ) target_compile_options(netx_imxrt_driver_client PRIVATE -Wno-unused-variable) -endif() -# 3. Add the active demo subdirectory to build the executable target -add_subdirectory(app/demos/${ACTIVE_DEMO}) +# 3. Add demo subdirectories to build executable targets +if(ACTIVE_DEMO STREQUAL "all") + add_subdirectory(app/demos/threadx_basic) + add_subdirectory(app/demos/netx_echo) + add_subdirectory(app/demos/netx_trng_console) +else() + add_subdirectory(app/demos/${ACTIVE_DEMO}) +endif() diff --git a/NXP/MIMXRT1064-EVK/NOTICE.md b/NXP/MIMXRT1064-EVK/NOTICE.md index 854858e9..d60251c0 100644 --- a/NXP/MIMXRT1064-EVK/NOTICE.md +++ b/NXP/MIMXRT1064-EVK/NOTICE.md @@ -1,34 +1,37 @@ # Third-Party Software Notices -This directory contains build automation scripts and configurations that download and compile third-party software components. This notice lists the licenses and copyrights applicable to those components. +This directory contains third-party software components included in the repository as well as build automation scripts and configurations that download and compile external dependencies. This notice lists the licenses and copyrights applicable to those components. --- -## 1. NXP MCUXpresso SDK Drivers & Device Support -* **Source**: https://github.com/nxp-mcuxpresso/mcuxsdk-core / https://mcuxpresso.nxp.com/ +## 1. NXP MCUXpresso SDK Drivers, Device Support & Startup Files +* **Source**: https://github.com/nxp-mcuxpresso/mcuxsdk-core / https://github.com/nxp-mcuxpresso/mcuxsdk-examples / https://mcuxpresso.nxp.com +* **Location**: `app/startup/startup_mimxrt1064.S`, `app/startup/MIMXRT1064xxxxx_flexspi_nor.ld`, and `lib/mcux-sdk/` * **License**: BSD 3-Clause ```text -Copyright 2016-2026 NXP -All rights reserved. +Copyright (c) 2015-2016, Freescale Semiconductor, Inc. +Copyright 2018-2025 NXP + +The BSD 3 Clause License Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. +may be used to endorse or promote products derived from this software without +specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR @@ -41,7 +44,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --- ## 2. ARM CMSIS Core -* **Source**: https://github.com/ARM-software/CMSIS_5 / https://github.com/STMicroelectronics/cmsis-core +* **Source**: https://github.com/ARM-software/CMSIS_5 +* **Location**: `lib/mcux-sdk/CMSIS/Include/` * **License**: Apache License 2.0 ```text diff --git a/NXP/MIMXRT1064-EVK/README.md b/NXP/MIMXRT1064-EVK/README.md index e625089f..944aded2 100644 --- a/NXP/MIMXRT1064-EVK/README.md +++ b/NXP/MIMXRT1064-EVK/README.md @@ -1,115 +1,259 @@ -# NXP i.MX RT1064-EVK Board Support Package & Demos +# NXP i.MX RT1064-EVK Board Enablement Demos -This directory contains the Board Support Package (BSP) and build environment for running the **Eclipse ThreadX RTOS** and **NetX Duo** on the **NXP i.MX RT1064-EVK** evaluation board (ARM Cortex-M7 @ 600 MHz). +This directory contains the Board Support Package (BSP) and build configurations for running the **Eclipse ThreadX RTOS** and **NetX Duo TCP/IP stack** on the **NXP i.MX RT1064-EVK** evaluation board (ARM Cortex-M7 @ 600 MHz). -The project is designed to run seamlessly both in the **Antmicro Renode** simulation framework and on physical silicon. +The project features a decoupled Board Support Package (`board_bsp`) that hides all low-level hardware initializations (clocks, power, caches, MPU regions, pin muxing, Ethernet MAC/PHY descriptors, and on-chip cryptographic peripherals) from the high-level application code. + +> [!NOTE] +> **Hardware Verification Status**: *Simulated in Renode, Pending Physical Hardware Verification* +> +> All peripheral drivers, hardware cryptographic subsystems, and network stacks documented in this repository have been fully verified under multi-node system emulation in Antmicro Renode. Flashing instructions for physical silicon follow standard NXP OpenSDA, Segger J-Link, pyOCD, and MCUXpresso workflows as detailed in the [Physical Board Deployment & Flashing](#physical-board-deployment--flashing) section below. --- -## Hardware Configuration +## Supported Demos -* **Development Board**: MIMXRT1064-EVK -* **Microcontroller**: NXP i.MX RT1064 (MIMXRT1064DVL6A, ARM Cortex-M7 @ 600 MHz) -* **Flash Memory**: 4 MB internal FlexSPI NOR Flash (XIP) -* **Internal SRAM**: 1 MB on-chip RAM (Configurable as ITCM, DTCM, and OCRAM) -* **Debug Serial Console**: LPUART1 (115,200 baud, 8N1) -* **User LED**: GPIO1 Pin 9 (`GPIO_AD_B0_09`) / User LED D18 (Green) -* **User Button**: GPIO5 Pin 0 (SW8 WAKEUP button) -* **Virtual Networking**: ENET1 (10/100M Fast Ethernet MAC via KSZ8081 PHY) +Each demo outputs into its own isolated directory in `build/app/demos//`: + +| Demo Name | Description | Output Directory | +| :--- | :--- | :--- | +| **`threadx_basic`** | Core ThreadX RTOS demo: preemptive thread scheduling, timer callbacks, and User LED D18 heartbeat blinking. | `build/app/demos/threadx_basic/` | +| **`netx_echo`** | NetX Duo networking demo: KSZ8081 Ethernet PHY, ARP, ICMP Ping responder, UDP echo (port 7), and TCP echo server (port 7). | `build/app/demos/netx_echo/` | +| **`netx_trng_console`** *(Default)* | Hardware cryptographic True Random Number Generator (TRNG @ `0x400CC000`) with an interactive TCP diagnostic management shell on port 23. | `build/app/demos/netx_trng_console/` | --- -## Project Structure - -```text -NXP/MIMXRT1064-EVK/ -├── CMakeLists.txt # Top-level CMake build configuration -├── NOTICE.md # Third-party licensing notices (NXP BSD-3 & CMSIS) -├── README.md # This documentation file -├── app/ -│ ├── main.c # ThreadX application entry, Heartbeat & Worker threads -│ ├── board_init.c / .h # Clocks (600 MHz), MPU, pin muxing & User LED init -│ ├── console.c / .h # LPUART1 serial driver & POSIX printf retargeting -│ ├── syscalls.c / sysmem.c # Minimal C runtime system call stubs -│ └── startup/ -│ ├── startup_mimxrt1064.S # NXP vector table & reset handler -│ ├── tx_initialize_low_level.S # ThreadX Cortex-M7 low-level init & SysTick -│ └── MIMXRT1064xxxxx_flexspi_nor.ld # FlexSPI NOR XIP GNU linker script -├── cmake/ -│ ├── arm-gcc-cortex-m7.cmake # CPU architecture and FPU definitions -│ ├── arm-gcc-cortex-toolchain.cmake # GNU toolchain discovery and compiler flags -│ └── utilities.cmake # Elf-to-bin/hex conversion and linker macros -├── lib/ -│ ├── threadx/ -│ │ └── tx_user.h # ThreadX configuration (hardware FPU enabled, 100 Hz tick) -│ └── mcux-sdk/ # Official NXP SDK drivers (fetched via script) -├── renode/ -│ ├── mimxrt1064-evk.repl # Board platform description (memory, LED, button) -│ └── mimxrt1064-evk.resc # Renode simulation script (LPUART1 analyzer & LED logging) -└── scripts/ - ├── fetch_sdk.ps1 / .sh # Download official NXP drivers, device headers & CMSIS - ├── build.ps1 / .sh # One-command build script with Ninja/CMake - └── simulate.ps1 / .sh # Launch Renode simulation with serial monitor -``` +## Hardware Overview + +* **Evaluation Board**: NXP MIMXRT1064-EVK (ARM Cortex-M7 @ 600 MHz) +* **Memory**: 4 MB on-chip FlexSPI NOR Flash (`0x70000000`), 1 MB on-chip SRAM (ITCM, DTCM, NonCacheable OCRAM) +* **Serial Console**: LPUART1 via OpenSDA micro-USB (`J41`), 115,200 baud, 8N1 +* **User LED & Button**: Green LED `D18` (`GPIO1_IO09`), SW8 WAKEUP button (`GPIO5_IO00`) +* **Ethernet**: ENET MAC + Microchip KSZ8081RNA PHY via RMII +* **TRNG Hardware**: On-chip True Random Number Generator (`0x400CC000`) --- ## Prerequisites -Before building, ensure the following cross-compilation tools are installed and present on your `PATH`: - -* **ARM GNU Toolchain** (`arm-none-eabi-gcc` 10.3 or newer) -* **CMake** (version 3.5 or newer) -* **Ninja** (or **Make**) +* **ARM GNU Toolchain** (`arm-none-eabi-gcc` 10.3+) +* **CMake** (3.20+) and **Ninja** (recommended) or Make * **Git** (for downloading SDK dependencies) -* **Antmicro Renode** (v1.15 or newer, for simulation) +* **Antmicro Renode** (1.15.3+, for simulation) --- ## Quick Start Guide ### 1. Download SDK Dependencies -Run the driver fetcher script to retrieve official NXP MCUXpresso SDK drivers, CMSIS device headers, and board files: +Download the stock NXP MCUXpresso SDK drivers, CMSIS headers, and board files: -* **On Windows (PowerShell)**: +* **Windows**: ```powershell powershell -ExecutionPolicy Bypass -File .\scripts\fetch_sdk.ps1 ``` -* **On Linux / macOS (Bash)**: +* **Linux / macOS**: + ```bash + chmod +x ./scripts/fetch_sdk.sh && ./scripts/fetch_sdk.sh + ``` + +### 2. Build the Demos + +#### Option A: Build All Demos (Default & Recommended) +Build all three demos at once. Once built, you can switch between simulations instantly without rebuilding! + +* **Windows**: + ```powershell + powershell -ExecutionPolicy Bypass -File .\scripts\build.ps1 + ``` +* **Linux / macOS**: + ```bash + chmod +x ./scripts/build.sh && ./scripts/build.sh + ``` +* **Direct CMake**: ```bash - chmod +x ./scripts/fetch_sdk.sh - ./scripts/fetch_sdk.sh + cmake -B build -G Ninja -DACTIVE_DEMO=all + cmake --build build ``` -### 2. Build the Project -Compile the application, vendor drivers, and Eclipse ThreadX kernel: +#### Option B: Build a Specific Demo +To build only one specific demo: + +```powershell +# Windows PowerShell +.\scripts\build.ps1 -Demo threadx_basic +.\scripts\build.ps1 -Demo netx_echo +.\scripts\build.ps1 -Demo netx_trng_console +``` + +```bash +# Linux / macOS Bash +./scripts/build.sh -d threadx_basic +./scripts/build.sh -d netx_echo +./scripts/build.sh -d netx_trng_console +``` + +Each demo's artifacts (`.elf`, `.bin`, `.hex`, `.map`) are placed in `build/app/demos//`. + +--- + +## Renode Simulation + +The project includes preconfigured Renode emulation environments for both single-node and multi-node scenarios. + +### 1. Interactive Simulation +Simulate any demo simply by passing the `-Demo` configuration variable: -* **On Windows (PowerShell)**: +* **Windows (PowerShell)**: ```powershell - powershell -ExecutionPolicy Bypass -File .\scripts\build.ps1 -Rebuild + # ThreadX Core Basic (single node) + powershell -ExecutionPolicy Bypass -File .\scripts\simulate.ps1 -Demo threadx_basic + + # NetX Duo Network Echo (multi-node server + client) + powershell -ExecutionPolicy Bypass -File .\scripts\simulate.ps1 -Demo netx_echo + + # Hardware TRNG Diagnostic Console (multi-node server + client) + powershell -ExecutionPolicy Bypass -File .\scripts\simulate.ps1 -Demo netx_trng_console ``` -* **On Linux / macOS (Bash)**: + +* **Linux / macOS (Bash)**: ```bash - chmod +x ./scripts/build.sh - ./scripts/build.sh --rebuild + ./scripts/simulate.sh -d threadx_basic + ./scripts/simulate.sh -d netx_echo + ./scripts/simulate.sh -d netx_trng_console ``` -### 3. Run the Simulation in Renode -Launch the interactive Renode simulation: +#### Deterministic Seeding Option: +For deterministic execution and repeatable TRNG random sequences in simulation, pass `-Seed `: +```powershell +powershell -ExecutionPolicy Bypass -File .\scripts\simulate.ps1 -Demo netx_trng_console -Seed 12345 +``` +```bash +./scripts/simulate.sh -d netx_trng_console -s 12345 +``` -* **On Windows (PowerShell)**: +### 2. Headless Automated Regression Testing (CI/CD) +The project provides headless test runners (`test_headless.ps1` and `test_headless.sh`) designed for continuous integration pipelines without a graphical display. The runner boots the simulation, monitors the virtual UART logs, and exits with code `0` on success or code `1` on timeout/failure. + +* **Windows (PowerShell)**: ```powershell - .\scripts\simulate.ps1 + powershell -ExecutionPolicy Bypass -File .\scripts\test_headless.ps1 ``` -* **On Linux / macOS (Bash)**: +* **Linux / macOS (Bash)**: ```bash - chmod +x ./scripts/simulate.sh - ./scripts/simulate.sh + chmod +x ./scripts/test_headless.sh + ./scripts/test_headless.sh ``` +Test any specific demo headlessly: +```powershell +powershell -ExecutionPolicy Bypass -File .\scripts\test_headless.ps1 -Demo threadx_basic -TimeoutSeconds 8 +``` + --- -## Hardware Verification Status +## Physical Board Deployment & Flashing > [!NOTE] -> This Board Support Package is developed and validated using **Antmicro Renode simulation**. Physical hardware verification on the EVK-MIMXRT1064 evaluation board is welcome and encouraged! +> *Simulated in Renode, Pending Physical Hardware Verification* + +When flashing to physical hardware, ensure the EVK board boot mode switches (`SW7`: `1-OFF, 2-ON, 3-OFF, 4-ON`) are configured for **Internal Boot (FlexSPI NOR Flash)**. Connect your PC to the OpenSDA USB port (`J41`). + +### Flashing Method 1: OpenSDA Drag-and-Drop (DAP-Link) +1. Connect the EVK board to your PC via micro-USB connector `J41`. +2. The onboard OpenSDA circuit mounts as a USB mass storage drive (e.g., `RT1064-EVK`). +3. Copy `build/app/demos//mimxrt1064_threadx.bin` and paste it directly into the `RT1064-EVK` drive. +4. The OpenSDA LED blinks rapidly during programming. Once complete, press the `SW3` (RESET) button to boot. + +### Flashing Method 2: SEGGER J-Link +If using a SEGGER J-Link probe (or OpenSDA programmed with J-Link firmware): +1. Connect via J-Link Commander: + ```text + JLink.exe -device MIMXRT1064xxx6A -if SWD -speed 4000 -autoconnect 1 + ``` +2. Flash the raw binary or hex file: + ```text + loadfile build/app/demos//mimxrt1064_threadx.hex + r + g + ``` + +### Flashing Method 3: pyOCD Command Line +Using the open-source pyOCD programmer: +1. Install pyOCD and the NXP device pack: + ```bash + pip install pyocd && pyocd pack install MIMXRT1064 + ``` +2. Program the target: + ```bash + pyocd flash -t mimxrt1064 build/app/demos//mimxrt1064_threadx.hex + ``` + +### Flashing Method 4: NXP MCUXpresso IDE / GUI Flash Tool +1. Open MCUXpresso IDE and select **GUI Flash Tool** from the toolbar. +2. Select target device `MIMXRT1064xxxxA` and target memory `PROGRAM_FLASH` (`0x70000000`). +3. Select `build/app/demos//mimxrt1064_threadx.elf` (or `.bin`) and click **Program**. + +--- + +## Developer Guide: How to Add a New Demo + +The decoupled architecture of `board_bsp` makes adding custom applications straightforward: + +### Step 1: Create the Demo Directory +Create a folder under `app/demos/` (e.g., `app/demos/my_new_demo/`). + +### Step 2: Write Application Code +Create `main.c` utilizing the clean BSP initialization API: +```c +#include "board_init.h" +#include "console.h" +#include "tx_api.h" + +int main(void) +{ + /* Initialize MPU, 600 MHz system clocks, and GPIO pins */ + board_init(); + + /* Initialize LPUART1 serial console */ + console_init(); + + /* Optional: Initialize Ethernet MAC/PHY if using networking */ + // board_ethernet_init(); + + /* Enter ThreadX RTOS Kernel */ + tx_kernel_enter(); + return 0; +} +``` + +### Step 3: Create `CMakeLists.txt` +In your demo directory: +```cmake +set(DEMO_TARGET "demo_my_new_demo") +add_executable(${DEMO_TARGET} + main.c +) +set_target_properties(${DEMO_TARGET} PROPERTIES OUTPUT_NAME "mimxrt1064_threadx") + +target_include_directories(${DEMO_TARGET} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../.. +) + +target_link_libraries(${DEMO_TARGET} PRIVATE + board_bsp + threadx + # netxduo # Uncomment if using network + # netx_imxrt_driver # Uncomment if using network +) + +set_target_linker(${DEMO_TARGET} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/MIMXRT1064xxxxx_flexspi_nor.ld") +post_build(${DEMO_TARGET}) +``` + +### Step 4: Build and Simulate +```bash +cmake -DACTIVE_DEMO=my_new_demo -B build -G Ninja +cmake --build build +``` diff --git a/NXP/MIMXRT1064-EVK/app/MIMXRT1062.h b/NXP/MIMXRT1064-EVK/app/MIMXRT1062.h index 5c20680c..fcfe2f66 100644 --- a/NXP/MIMXRT1064-EVK/app/MIMXRT1062.h +++ b/NXP/MIMXRT1064-EVK/app/MIMXRT1062.h @@ -1,3 +1,16 @@ +/* + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available + * under the terms of the MIT license which is available at + * https://opensource.org/license/mit. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 version. + */ + /* * Compatibility header: redirects MIMXRT1062.h from stock NetX Duo driver * to MIMXRT1064 device registers without modifying vendor source files. diff --git a/NXP/MIMXRT1064-EVK/app/demos/netx_echo/CMakeLists.txt b/NXP/MIMXRT1064-EVK/app/demos/netx_echo/CMakeLists.txt index a3a4ec5c..9aa97bf7 100644 --- a/NXP/MIMXRT1064-EVK/app/demos/netx_echo/CMakeLists.txt +++ b/NXP/MIMXRT1064-EVK/app/demos/netx_echo/CMakeLists.txt @@ -10,12 +10,14 @@ # Ali Eissa - 2026 version. # Server Executable Target (mimxrt1064_threadx) -add_executable(${PROJECT_NAME} +set(SERVER_TARGET "demo_netx_echo_server") +add_executable(${SERVER_TARGET} main.c ) +set_target_properties(${SERVER_TARGET} PROPERTIES OUTPUT_NAME "mimxrt1064_threadx") # Set compile definitions for server -target_compile_definitions(${PROJECT_NAME} +target_compile_definitions(${SERVER_TARGET} PRIVATE CPU_MIMXRT1064DVL6A XIP_EXTERNAL_FLASH=1 @@ -28,7 +30,7 @@ target_compile_definitions(${PROJECT_NAME} ) # Include paths for server -target_include_directories(${PROJECT_NAME} +target_include_directories(${SERVER_TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../.. @@ -44,7 +46,7 @@ target_include_directories(${PROJECT_NAME} ) # Link libraries for server -target_link_libraries(${PROJECT_NAME} +target_link_libraries(${SERVER_TARGET} PRIVATE board_bsp threadx @@ -54,14 +56,15 @@ target_link_libraries(${PROJECT_NAME} ) # Apply GCC linker script and post-build outputs for server -set_target_linker(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/MIMXRT1064xxxxx_flexspi_nor.ld") -post_build(${PROJECT_NAME}) +set_target_linker(${SERVER_TARGET} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/MIMXRT1064xxxxx_flexspi_nor.ld") +post_build(${SERVER_TARGET}) # Automated Verification Client Executable Target (mimxrt1064_client) -set(CLIENT_TARGET "mimxrt1064_client") +set(CLIENT_TARGET "demo_netx_echo_client") add_executable(${CLIENT_TARGET} client_main.c ) +set_target_properties(${CLIENT_TARGET} PROPERTIES OUTPUT_NAME "mimxrt1064_client") # Set compile definitions for client target_compile_definitions(${CLIENT_TARGET} diff --git a/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/CMakeLists.txt b/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/CMakeLists.txt index a3a4ec5c..d8fc8cab 100644 --- a/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/CMakeLists.txt +++ b/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/CMakeLists.txt @@ -10,12 +10,14 @@ # Ali Eissa - 2026 version. # Server Executable Target (mimxrt1064_threadx) -add_executable(${PROJECT_NAME} +set(SERVER_TARGET "demo_netx_trng_server") +add_executable(${SERVER_TARGET} main.c ) +set_target_properties(${SERVER_TARGET} PROPERTIES OUTPUT_NAME "mimxrt1064_threadx") # Set compile definitions for server -target_compile_definitions(${PROJECT_NAME} +target_compile_definitions(${SERVER_TARGET} PRIVATE CPU_MIMXRT1064DVL6A XIP_EXTERNAL_FLASH=1 @@ -28,7 +30,7 @@ target_compile_definitions(${PROJECT_NAME} ) # Include paths for server -target_include_directories(${PROJECT_NAME} +target_include_directories(${SERVER_TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../.. @@ -44,7 +46,7 @@ target_include_directories(${PROJECT_NAME} ) # Link libraries for server -target_link_libraries(${PROJECT_NAME} +target_link_libraries(${SERVER_TARGET} PRIVATE board_bsp threadx @@ -54,14 +56,15 @@ target_link_libraries(${PROJECT_NAME} ) # Apply GCC linker script and post-build outputs for server -set_target_linker(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/MIMXRT1064xxxxx_flexspi_nor.ld") -post_build(${PROJECT_NAME}) +set_target_linker(${SERVER_TARGET} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/MIMXRT1064xxxxx_flexspi_nor.ld") +post_build(${SERVER_TARGET}) # Automated Verification Client Executable Target (mimxrt1064_client) -set(CLIENT_TARGET "mimxrt1064_client") +set(CLIENT_TARGET "demo_netx_trng_client") add_executable(${CLIENT_TARGET} client_main.c ) +set_target_properties(${CLIENT_TARGET} PROPERTIES OUTPUT_NAME "mimxrt1064_client") # Set compile definitions for client target_compile_definitions(${CLIENT_TARGET} diff --git a/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/nx_user.h b/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/nx_user.h deleted file mode 100644 index eccf436a..00000000 --- a/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/nx_user.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2026 Eclipse ThreadX contributors - * - * This program and the accompanying materials are made available - * under the terms of the MIT license which is available at - * https://opensource.org/license/mit. - * - * SPDX-License-Identifier: MIT - * - * Contributors: - * Ali Eissa - 2026 version. - */ - -#ifndef NX_USER_H -#define NX_USER_H - -#define NX_DISABLE_IPV6 -#define NX_PHYSICAL_HEADER 16 -#define NX_ENABLE_EXTENDED_NOTIFY_SUPPORT - -#endif /* NX_USER_H */ diff --git a/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/CMakeLists.txt b/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/CMakeLists.txt index 41f8f3bb..b8431811 100644 --- a/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/CMakeLists.txt +++ b/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/CMakeLists.txt @@ -9,12 +9,14 @@ # Contributors: # Ali Eissa - 2026 version. -add_executable(${PROJECT_NAME} +set(DEMO_TARGET "demo_threadx_basic") +add_executable(${DEMO_TARGET} main.c ) +set_target_properties(${DEMO_TARGET} PROPERTIES OUTPUT_NAME "mimxrt1064_threadx") # Set compile definitions for our executable -target_compile_definitions(${PROJECT_NAME} +target_compile_definitions(${DEMO_TARGET} PRIVATE CPU_MIMXRT1064DVL6A XIP_EXTERNAL_FLASH=1 @@ -27,7 +29,7 @@ target_compile_definitions(${PROJECT_NAME} ) # Include paths for the executable target -target_include_directories(${PROJECT_NAME} +target_include_directories(${DEMO_TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../.. @@ -41,7 +43,7 @@ target_include_directories(${PROJECT_NAME} ) # Link libraries -target_link_libraries(${PROJECT_NAME} +target_link_libraries(${DEMO_TARGET} PRIVATE board_bsp threadx @@ -49,7 +51,7 @@ target_link_libraries(${PROJECT_NAME} ) # Apply GCC linker script and print memory usage (utilities.cmake function) -set_target_linker(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/MIMXRT1064xxxxx_flexspi_nor.ld") +set_target_linker(${DEMO_TARGET} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/MIMXRT1064xxxxx_flexspi_nor.ld") # Post-build commands to generate raw .bin and .hex files -post_build(${PROJECT_NAME}) +post_build(${DEMO_TARGET}) diff --git a/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/main.c b/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/main.c index b313f404..6ff1132d 100644 --- a/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/main.c +++ b/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/main.c @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT * * Contributors: - * Ali Eissa - 2026 NXP i.MX RT1064 port. + * Ali Eissa - 2026 version. */ #include "board_init.h" diff --git a/NXP/MIMXRT1064-EVK/app/startup/MIMXRT1064xxxxx_flexspi_nor.ld b/NXP/MIMXRT1064-EVK/app/startup/MIMXRT1064xxxxx_flexspi_nor.ld index 8e79f28c..9fd0ae83 100644 --- a/NXP/MIMXRT1064-EVK/app/startup/MIMXRT1064xxxxx_flexspi_nor.ld +++ b/NXP/MIMXRT1064-EVK/app/startup/MIMXRT1064xxxxx_flexspi_nor.ld @@ -27,6 +27,10 @@ ** ################################################################### */ +/* +** Adapted memory sections for Eclipse ThreadX RTOS by Eclipse ThreadX contributors. +*/ + /* Entry Point */ ENTRY(Reset_Handler) diff --git a/NXP/MIMXRT1064-EVK/app/startup/tx_initialize_low_level.S b/NXP/MIMXRT1064-EVK/app/startup/tx_initialize_low_level.S index 40e3879d..d34654b5 100644 --- a/NXP/MIMXRT1064-EVK/app/startup/tx_initialize_low_level.S +++ b/NXP/MIMXRT1064-EVK/app/startup/tx_initialize_low_level.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT * * Contributors: - * Ali Eissa - 2026 NXP i.MX RT1064 port. + * Ali Eissa - 2026 version. **************************************************************************/ /**************************************************************************/ diff --git a/NXP/MIMXRT1064-EVK/cmake/utilities.cmake b/NXP/MIMXRT1064-EVK/cmake/utilities.cmake index d584424d..0cc921f9 100644 --- a/NXP/MIMXRT1064-EVK/cmake/utilities.cmake +++ b/NXP/MIMXRT1064-EVK/cmake/utilities.cmake @@ -14,14 +14,14 @@ function(post_build TARGET) if(CMAKE_C_COMPILER_ID STREQUAL "IAR") - add_custom_target(${TARGET}.bin ALL + add_custom_target(${TARGET}_bin ALL DEPENDS ${TARGET} COMMAND ${CMAKE_IAR_ELFTOOL} --bin ${TARGET}.elf ${TARGET}.bin) elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU") - add_custom_target(${TARGET}.bin ALL + add_custom_target(${TARGET}_bin ALL DEPENDS ${TARGET} - COMMAND ${CMAKE_OBJCOPY} -Obinary $ $/${TARGET}.bin - COMMAND ${CMAKE_OBJCOPY} -Oihex $ $/${TARGET}.hex) + COMMAND ${CMAKE_OBJCOPY} -Obinary $ $/$.bin + COMMAND ${CMAKE_OBJCOPY} -Oihex $ $/$.hex) else() message(FATAL_ERROR "Unknown CMAKE_C_COMPILER_ID ${CMAKE_C_COMPILER_ID}") endif() @@ -33,7 +33,7 @@ function(set_target_linker TARGET LINKER_SCRIPT) target_link_options(${TARGET} PRIVATE --map=${TARGET}.map) elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU") target_link_options(${TARGET} PRIVATE -T${LINKER_SCRIPT}) - target_link_options(${TARGET} PRIVATE -Wl,-Map=${TARGET}.map) + target_link_options(${TARGET} PRIVATE -Wl,-Map=$/$.map) set_target_properties(${TARGET} PROPERTIES SUFFIX ".elf") else() message(FATAL_ERROR "Unknown CMAKE_C_COMPILER_ID ${CMAKE_C_COMPILER_ID}") diff --git a/NXP/MIMXRT1064-EVK/app/demos/netx_echo/nx_user.h b/NXP/MIMXRT1064-EVK/lib/netxduo/nx_user.h similarity index 100% rename from NXP/MIMXRT1064-EVK/app/demos/netx_echo/nx_user.h rename to NXP/MIMXRT1064-EVK/lib/netxduo/nx_user.h diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc index 6ba323b0..ed38157e 100644 --- a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc @@ -1,3 +1,14 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. + :name: MIMXRT1064-EVK ThreadX Demo :description: This script runs the Eclipse ThreadX & NetX Duo demo on NXP i.MX RT1064-EVK. diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc new file mode 100644 index 00000000..4f695be6 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc @@ -0,0 +1,43 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. + +:name: MIMXRT1064-EVK Headless Multi-Node CI Test +:description: Headless two-node verification connecting server and client via virtual switch. + +# 1. Create Virtual Ethernet Switch +emulation CreateSwitch "switch" + +# 2. Server Machine (192.168.0.100) +mach create "server" +machine LoadPlatformDescription $ORIGIN/mimxrt1064-evk.repl +connector Connect sysbus.enet switch +sysbus.lpuart1 CreateFileBackend $ORIGIN/../build/server_uart.log true + +$bin_server?=$ORIGIN/../build/mimxrt1064_threadx.elf +cpu VectorTableOffset 0x70002000 +sysbus LoadELF $bin_server +cpu PC `sysbus ReadDoubleWord 0x70002004` +cpu SP `sysbus ReadDoubleWord 0x70002000` + +# 3. Client Machine (192.168.0.101) +mach create "client" +machine LoadPlatformDescription $ORIGIN/mimxrt1064-evk.repl +connector Connect sysbus.enet switch +sysbus.lpuart1 CreateFileBackend $ORIGIN/../build/client_uart.log true + +$bin_client?=$ORIGIN/../build/mimxrt1064_client.elf +cpu VectorTableOffset 0x70002000 +sysbus LoadELF $bin_client +cpu PC `sysbus ReadDoubleWord 0x70002004` +cpu SP `sysbus ReadDoubleWord 0x70002000` + +# 4. Start Simulation +start diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc new file mode 100644 index 00000000..7e4f74bd --- /dev/null +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc @@ -0,0 +1,26 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. + +:name: MIMXRT1064-EVK Headless Single-Node CI Test +:description: Headless single-node verification capturing LPUART1 output to log file. + +mach create "mimxrt1064-evk" +machine LoadPlatformDescription $ORIGIN/mimxrt1064-evk.repl + +sysbus.lpuart1 CreateFileBackend $ORIGIN/../build/server_uart.log true + +$bin?=$ORIGIN/../build/mimxrt1064_threadx.elf +cpu VectorTableOffset 0x70002000 +sysbus LoadELF $bin +cpu PC `sysbus ReadDoubleWord 0x70002004` +cpu SP `sysbus ReadDoubleWord 0x70002000` + +start diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-network-multinode.resc b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-network-multinode.resc index 88be9668..54343a1b 100644 --- a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-network-multinode.resc +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-network-multinode.resc @@ -1,3 +1,14 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. + :name: MIMXRT1064-EVK NetX Duo Two-Node Virtual Network Verification :description: This script creates two MIMXRT1064-EVK nodes connected via a virtual Ethernet switch: : - "server": Echo Server on 192.168.0.100 (ICMP Ping, UDP port 7, TCP port 7) diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-trng-console.resc b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-trng-console.resc index ca877e09..58f2465a 100644 --- a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-trng-console.resc +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-trng-console.resc @@ -1,3 +1,14 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. + :name: MIMXRT1064-EVK Hardware TRNG & Console Two-Node Verification :description: This script creates two MIMXRT1064-EVK nodes connected via a virtual Ethernet switch: : - "server": TRNG Console Server on 192.168.0.100 (TCP Port 23, ICMP Ping) diff --git a/NXP/MIMXRT1064-EVK/scripts/build.ps1 b/NXP/MIMXRT1064-EVK/scripts/build.ps1 index a0cd9c99..b785894f 100644 --- a/NXP/MIMXRT1064-EVK/scripts/build.ps1 +++ b/NXP/MIMXRT1064-EVK/scripts/build.ps1 @@ -12,7 +12,7 @@ param( [switch]$Clean, [switch]$Rebuild, - [string]$Demo = "netx_echo" + [string]$Demo = "all" ) $BoardDir = Resolve-Path "$PSScriptRoot/.." @@ -85,13 +85,29 @@ if ($LASTEXITCODE -ne 0) { Write-Host "" Write-Host "[SUCCESS] Build finished successfully!" -ForegroundColor Green -Write-Host "Server Firmware ELF: $(Join-Path $BUILD_DIR 'mimxrt1064_threadx.elf')" -Write-Host "Server Firmware BIN: $(Join-Path $BUILD_DIR 'mimxrt1064_threadx.bin')" -Write-Host "Server Firmware HEX: $(Join-Path $BUILD_DIR 'mimxrt1064_threadx.hex')" -if (Test-Path (Join-Path $BUILD_DIR 'mimxrt1064_client.elf')) { - Write-Host "Client Firmware ELF: $(Join-Path $BUILD_DIR 'mimxrt1064_client.elf')" - Write-Host "Client Firmware BIN: $(Join-Path $BUILD_DIR 'mimxrt1064_client.bin')" - Write-Host "Client Firmware HEX: $(Join-Path $BUILD_DIR 'mimxrt1064_client.hex')" + +$demosToReport = @() +if ($Demo -eq "all") { + $demosToReport = @("threadx_basic", "netx_echo", "netx_trng_console") +} else { + $demosToReport = @($Demo) +} + +foreach ($d in $demosToReport) { + $demoDir = Join-Path $BUILD_DIR "app/demos/$d" + if (Test-Path $demoDir) { + Write-Host "[$d] Output Binaries in $demoDir :" -ForegroundColor Cyan + $serverElf = Join-Path $demoDir "mimxrt1064_threadx.elf" + $clientElf = Join-Path $demoDir "mimxrt1064_client.elf" + if (Test-Path $serverElf) { + Write-Host " - Server ELF: $serverElf" + Write-Host " - Server BIN: $(Join-Path $demoDir 'mimxrt1064_threadx.bin')" + } + if (Test-Path $clientElf) { + Write-Host " - Client ELF: $clientElf" + Write-Host " - Client BIN: $(Join-Path $demoDir 'mimxrt1064_client.bin')" + } + } } Pop-Location diff --git a/NXP/MIMXRT1064-EVK/scripts/build.sh b/NXP/MIMXRT1064-EVK/scripts/build.sh index 48d5327e..101ac40f 100644 --- a/NXP/MIMXRT1064-EVK/scripts/build.sh +++ b/NXP/MIMXRT1064-EVK/scripts/build.sh @@ -19,14 +19,14 @@ NUM_JOBS=4 CLEAN=0 REBUILD=0 -DEMO="netx_echo" +DEMO="all" # Parse arguments while [[ "$#" -gt 0 ]]; do case $1 in --clean) CLEAN=1 ;; --rebuild) REBUILD=1 ;; - --demo) DEMO="$2"; shift ;; + -d|--demo) DEMO="$2"; shift ;; *) echo "Unknown parameter passed: $1"; exit 1 ;; esac shift @@ -84,11 +84,24 @@ ninja -j ${NUM_JOBS} echo "" echo "[SUCCESS] Build finished successfully!" -echo "Server Firmware ELF: ${BUILD_DIR}/mimxrt1064_threadx.elf" -echo "Server Firmware BIN: ${BUILD_DIR}/mimxrt1064_threadx.bin" -echo "Server Firmware HEX: ${BUILD_DIR}/mimxrt1064_threadx.hex" -if [ -f "${BUILD_DIR}/mimxrt1064_client.elf" ]; then - echo "Client Firmware ELF: ${BUILD_DIR}/mimxrt1064_client.elf" - echo "Client Firmware BIN: ${BUILD_DIR}/mimxrt1064_client.bin" - echo "Client Firmware HEX: ${BUILD_DIR}/mimxrt1064_client.hex" + +if [ "${DEMO}" = "all" ]; then + DEMOS_TO_REPORT=("threadx_basic" "netx_echo" "netx_trng_console") +else + DEMOS_TO_REPORT=("${DEMO}") fi + +for d in "${DEMOS_TO_REPORT[@]}"; do + DEMO_DIR="${BUILD_DIR}/app/demos/${d}" + if [ -d "${DEMO_DIR}" ]; then + echo "[${d}] Output Binaries in ${DEMO_DIR}:" + if [ -f "${DEMO_DIR}/mimxrt1064_threadx.elf" ]; then + echo " - Server ELF: ${DEMO_DIR}/mimxrt1064_threadx.elf" + echo " - Server BIN: ${DEMO_DIR}/mimxrt1064_threadx.bin" + fi + if [ -f "${DEMO_DIR}/mimxrt1064_client.elf" ]; then + echo " - Client ELF: ${DEMO_DIR}/mimxrt1064_client.elf" + echo " - Client BIN: ${DEMO_DIR}/mimxrt1064_client.bin" + fi + fi +done diff --git a/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 index 76d585a7..b99f9637 100644 --- a/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 +++ b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 @@ -186,7 +186,7 @@ try { # 3. Fetch CMSIS Core headers (standard ARM CMSIS-Core include files) Write-Host "[INFO] Cloning CMSIS Core headers (depth=1)..." $cmsisCloneDir = Join-Path $TempDir "cmsis_core_repo" - git clone --depth 1 https://github.com/STMicroelectronics/cmsis-core.git $cmsisCloneDir + git clone --depth 1 https://github.com/ARM-software/CMSIS_5.git $cmsisCloneDir if ($LASTEXITCODE -ne 0) { throw "Failed to clone CMSIS Core repository" } diff --git a/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh index c89fa6df..0f2e9b07 100644 --- a/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh +++ b/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh @@ -128,7 +128,7 @@ echo "" # 3. Fetch CMSIS Core headers echo "[INFO] Cloning CMSIS Core headers (depth=1)..." CMSIS_CLONE_DIR="${TEMP_DIR}/cmsis_core_repo" -git clone --depth 1 https://github.com/STMicroelectronics/cmsis-core.git "${CMSIS_CLONE_DIR}" +git clone --depth 1 https://github.com/ARM-software/CMSIS_5.git "${CMSIS_CLONE_DIR}" cp -r "${CMSIS_CLONE_DIR}/CMSIS/Core/Include/"* "${CMSIS_INCLUDE_DEST}/" echo "[OK] CMSIS Core headers copied" echo "" diff --git a/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 b/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 index 842c5de4..716f56db 100644 --- a/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 +++ b/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 @@ -10,47 +10,83 @@ # Ali Eissa - 2026 version. param( - [string]$Resc + [Alias("d")] + [string]$Demo, + [string]$Resc, + [Nullable[int]]$Seed ) $BoardDir = Resolve-Path "$PSScriptRoot/.." -$ServerElf = Join-Path $BoardDir "build/mimxrt1064_threadx.elf" -$ClientElf = Join-Path $BoardDir "build/mimxrt1064_client.elf" +$BuildDir = Join-Path $BoardDir "build" -if (-not (Test-Path $ServerElf)) { - Write-Error "Binary $ServerElf not found. Please build the project first using .\scripts\build.ps1" - exit 1 +# 1. Resolve which demo to simulate +$selectedDemo = $Demo +if (-not $selectedDemo) { + # Check CMakeCache.txt for ACTIVE_DEMO + $cacheFile = Join-Path $BuildDir "CMakeCache.txt" + if (Test-Path $cacheFile) { + $match = Select-String -Path $cacheFile -Pattern "^ACTIVE_DEMO:STRING=(.*)$" + if ($match) { + $cached = $match.Matches.Groups[1].Value.Trim() + if ($cached -and $cached -ne "all") { + $selectedDemo = $cached + } + } + } } -# Determine RESC script: custom argument, or auto-detect based on cached demo -$cachedDemo = "" -$cacheFile = Join-Path $BoardDir "build/CMakeCache.txt" -if (Test-Path $cacheFile) { - $match = Select-String -Path $cacheFile -Pattern "^ACTIVE_DEMO:STRING=(.*)$" - if ($match) { - $cachedDemo = $match.Matches.Groups[1].Value.Trim() +# If still undetermined, check existing built demo directories or default to threadx_basic +if (-not $selectedDemo) { + if (Test-Path (Join-Path $BuildDir "app/demos/threadx_basic/mimxrt1064_threadx.elf")) { + $selectedDemo = "threadx_basic" + } elseif (Test-Path (Join-Path $BuildDir "app/demos/netx_echo/mimxrt1064_threadx.elf")) { + $selectedDemo = "netx_echo" + } elseif (Test-Path (Join-Path $BuildDir "app/demos/netx_trng_console/mimxrt1064_threadx.elf")) { + $selectedDemo = "netx_trng_console" + } else { + $selectedDemo = "threadx_basic" } } +# 2. Locate firmware binaries for the selected demo +$serverElfRel = "build/app/demos/$selectedDemo/mimxrt1064_threadx.elf" +$clientElfRel = "build/app/demos/$selectedDemo/mimxrt1064_client.elf" + +# Fallback to root build dir if per-demo subfolder does not exist +if (-not (Test-Path (Join-Path $BoardDir $serverElfRel)) -and (Test-Path (Join-Path $BoardDir "build/mimxrt1064_threadx.elf"))) { + $serverElfRel = "build/mimxrt1064_threadx.elf" + $clientElfRel = "build/mimxrt1064_client.elf" +} + +$ServerElf = Join-Path $BoardDir $serverElfRel +$ClientElf = Join-Path $BoardDir $clientElfRel + +if (-not (Test-Path $ServerElf)) { + Write-Host "[ERROR] Firmware binary for demo '$selectedDemo' not found at:" -ForegroundColor Red + Write-Host " $ServerElf" -ForegroundColor Red + Write-Host "" + Write-Host "Please build the demo first using:" -ForegroundColor Yellow + Write-Host " .\scripts\build.ps1 -Demo $selectedDemo" -ForegroundColor Yellow + exit 1 +} + +# 3. Select Renode script and verification mode if ($Resc) { $RescRelPath = $Resc - $Mode = "Custom Script" -} elseif ($cachedDemo -eq "netx_trng_console") { + $Mode = "Custom Script ($Resc)" +} elseif ($selectedDemo -eq "netx_trng_console") { $RescRelPath = "renode/mimxrt1064-trng-console.resc" $Mode = "Hardware TRNG Console (Server: 192.168.0.100, Client: 192.168.0.101)" -} elseif ($cachedDemo -eq "netx_echo") { +} elseif ($selectedDemo -eq "netx_echo") { $RescRelPath = "renode/mimxrt1064-network-multinode.resc" - $Mode = "Multi-Node Network Echo Verification (Server: 192.168.0.100, Client: 192.168.0.101)" -} elseif (Test-Path $ClientElf) { - $RescRelPath = "renode/mimxrt1064-network-multinode.resc" - $Mode = "Multi-Node Network Verification (Server: 192.168.0.100, Client: 192.168.0.101)" + $Mode = "Multi-Node Network Echo (Server: 192.168.0.100, Client: 192.168.0.101)" } else { $RescRelPath = "renode/mimxrt1064-evk.resc" - $Mode = "Single-Node Demo" + $Mode = "ThreadX Core Basic Demo (Single-Node)" } $RescFullPath = Join-Path $BoardDir $RescRelPath -# Find Renode executable +# 4. Find Renode executable $RenodeExe = (Get-Command renode -ErrorAction SilentlyContinue).Source if (-not $RenodeExe -and (Test-Path "C:\Program Files\Renode\renode.exe")) { $RenodeExe = "C:\Program Files\Renode\renode.exe" @@ -64,12 +100,16 @@ if (-not $RenodeExe) { Write-Host "==========================================" Write-Host "Starting Renode Simulation" Write-Host "==========================================" -Write-Host "Renode: $RenodeExe" -Write-Host "Mode: $Mode" -Write-Host "Script: $RescFullPath" -Write-Host "Server ELF: $ServerElf" +Write-Host "Renode: $RenodeExe" +Write-Host "Demo: $selectedDemo" +Write-Host "Mode: $Mode" +Write-Host "Script: $RescFullPath" +if ($null -ne $Seed) { + Write-Host "Seed: $Seed (Deterministic)" +} +Write-Host "Server ELF: $ServerElf" if (Test-Path $ClientElf) { - Write-Host "Client ELF: $ClientElf" + Write-Host "Client ELF: $ClientElf" } Write-Host "" Write-Host "Opening Renode Monitor and LPUART1 terminal analyzer(s)..." @@ -78,5 +118,16 @@ Write-Host "==========================================" Set-Location $BoardDir +# 5. Build Renode execution command passing clean relative binary paths +$renodeCmd = "" +if ($null -ne $Seed) { + $renodeCmd += "emulation SetSeed $Seed; " +} +$renodeCmd += "`$bin = @`"$serverElfRel`"; `$bin_server = @`"$serverElfRel`"; " +if (Test-Path $ClientElf) { + $renodeCmd += "`$bin_client = @`"$clientElfRel`"; " +} +$renodeCmd += "include @`"$RescRelPath`"" + # Pass relative script path with quotes to avoid tokenization errors when workspace contains spaces -& $RenodeExe -e "include @`"$RescRelPath`"" +& $RenodeExe -e "$renodeCmd" diff --git a/NXP/MIMXRT1064-EVK/scripts/simulate.sh b/NXP/MIMXRT1064-EVK/scripts/simulate.sh index dcf574be..d3d3cdf1 100644 --- a/NXP/MIMXRT1064-EVK/scripts/simulate.sh +++ b/NXP/MIMXRT1064-EVK/scripts/simulate.sh @@ -14,36 +14,95 @@ set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" BOARD_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" -SERVER_ELF="${BOARD_DIR}/build/mimxrt1064_threadx.elf" -CLIENT_ELF="${BOARD_DIR}/build/mimxrt1064_client.elf" +BUILD_DIR="${BOARD_DIR}/build" -if [ ! -f "${SERVER_ELF}" ]; then - echo "[ERROR] Binary ${SERVER_ELF} not found. Please build first using ./scripts/build.sh" - exit 1 +DEMO_ARG="" +RESC_ARG="" +SEED_ARG="" + +while [[ $# -gt 0 ]]; do + case $1 in + -d|--demo) + DEMO_ARG="$2" + shift 2 + ;; + -s|--seed) + SEED_ARG="$2" + shift 2 + ;; + -r|--resc) + RESC_ARG="$2" + shift 2 + ;; + *) + if [ -z "${RESC_ARG}" ] && [[ "$1" == *.resc ]]; then + RESC_ARG="$1" + else + echo "Unknown parameter: $1" + exit 1 + fi + shift + ;; + esac +done + +# 1. Resolve which demo to simulate +SELECTED_DEMO="${DEMO_ARG}" +if [ -z "${SELECTED_DEMO}" ] && [ -f "${BUILD_DIR}/CMakeCache.txt" ]; then + CACHED_DEMO=$(grep -E "^ACTIVE_DEMO:STRING=" "${BUILD_DIR}/CMakeCache.txt" | cut -d'=' -f2 | tr -d ' \r\n') + if [ -n "${CACHED_DEMO}" ] && [ "${CACHED_DEMO}" != "all" ]; then + SELECTED_DEMO="${CACHED_DEMO}" + fi fi -CACHED_DEMO="" -if [ -f "${BOARD_DIR}/build/CMakeCache.txt" ]; then - CACHED_DEMO=$(grep -E "^ACTIVE_DEMO:STRING=" "${BOARD_DIR}/build/CMakeCache.txt" | cut -d'=' -f2 | tr -d ' \r\n') +if [ -z "${SELECTED_DEMO}" ]; then + if [ -f "${BUILD_DIR}/app/demos/threadx_basic/mimxrt1064_threadx.elf" ]; then + SELECTED_DEMO="threadx_basic" + elif [ -f "${BUILD_DIR}/app/demos/netx_echo/mimxrt1064_threadx.elf" ]; then + SELECTED_DEMO="netx_echo" + elif [ -f "${BUILD_DIR}/app/demos/netx_trng_console/mimxrt1064_threadx.elf" ]; then + SELECTED_DEMO="netx_trng_console" + else + SELECTED_DEMO="threadx_basic" + fi fi -if [ -n "$1" ]; then - RESC_REL_PATH="$1" - MODE="Custom Script" -elif [ "$CACHED_DEMO" = "netx_trng_console" ]; then +# 2. Locate firmware binaries for the selected demo +DEMO_DIR="${BUILD_DIR}/app/demos/${SELECTED_DEMO}" +SERVER_ELF="${DEMO_DIR}/mimxrt1064_threadx.elf" +CLIENT_ELF="${DEMO_DIR}/mimxrt1064_client.elf" + +# Fallback to root build dir if per-demo subfolder does not exist +if [ ! -f "${SERVER_ELF}" ] && [ -f "${BUILD_DIR}/mimxrt1064_threadx.elf" ]; then + SERVER_ELF="${BUILD_DIR}/mimxrt1064_threadx.elf" + CLIENT_ELF="${BUILD_DIR}/mimxrt1064_client.elf" +fi + +if [ ! -f "${SERVER_ELF}" ]; then + echo "[ERROR] Firmware binary for demo '${SELECTED_DEMO}' not found at:" + echo " ${SERVER_ELF}" + echo "" + echo "Please build the demo first using:" + echo " ./scripts/build.sh -d ${SELECTED_DEMO}" + exit 1 +fi + +# 3. Select Renode script and verification mode +if [ -n "${RESC_ARG}" ]; then + RESC_REL_PATH="${RESC_ARG}" + MODE="Custom Script (${RESC_ARG})" +elif [ "$SELECTED_DEMO" = "netx_trng_console" ]; then RESC_REL_PATH="renode/mimxrt1064-trng-console.resc" MODE="Hardware TRNG Console (Server: 192.168.0.100, Client: 192.168.0.101)" -elif [ "$CACHED_DEMO" = "netx_echo" ]; then +elif [ "$SELECTED_DEMO" = "netx_echo" ]; then RESC_REL_PATH="renode/mimxrt1064-network-multinode.resc" - MODE="Multi-Node Network Echo Verification (Server: 192.168.0.100, Client: 192.168.0.101)" -elif [ -f "${CLIENT_ELF}" ]; then - RESC_REL_PATH="renode/mimxrt1064-network-multinode.resc" - MODE="Multi-Node Network Verification (Server: 192.168.0.100, Client: 192.168.0.101)" + MODE="Multi-Node Network Echo (Server: 192.168.0.100, Client: 192.168.0.101)" else RESC_REL_PATH="renode/mimxrt1064-evk.resc" - MODE="Single-Node Demo" + MODE="ThreadX Core Basic Demo (Single-Node)" fi +# 4. Find Renode executable RENODE_CMD="renode" if ! command -v renode &> /dev/null; then if [ -f "/opt/renode/renode" ]; then @@ -57,13 +116,30 @@ fi echo "==========================================" echo "Starting Renode Simulation" echo "==========================================" -echo "Mode: ${MODE}" -echo "Script: ${BOARD_DIR}/${RESC_REL_PATH}" -echo "Server ELF: ${SERVER_ELF}" +echo "Renode: ${RENODE_CMD}" +echo "Demo: ${SELECTED_DEMO}" +echo "Mode: ${MODE}" +echo "Script: ${BOARD_DIR}/${RESC_REL_PATH}" +if [ -n "${SEED_ARG}" ]; then + echo "Seed: ${SEED_ARG} (Deterministic)" +fi +echo "Server ELF: ${SERVER_ELF}" if [ -f "${CLIENT_ELF}" ]; then - echo "Client ELF: ${CLIENT_ELF}" + echo "Client ELF: ${CLIENT_ELF}" fi echo "" cd "${BOARD_DIR}" -"${RENODE_CMD}" -e "include @\"${RESC_REL_PATH}\"" + +# 5. Build Renode execution command passing explicit binary paths +RENODE_EXEC_CMD="" +if [ -n "${SEED_ARG}" ]; then + RENODE_EXEC_CMD="emulation SetSeed ${SEED_ARG}; " +fi +RENODE_EXEC_CMD="${RENODE_EXEC_CMD}\$bin = @\"${SERVER_ELF}\"; \$bin_server = @\"${SERVER_ELF}\"; " +if [ -f "${CLIENT_ELF}" ]; then + RENODE_EXEC_CMD="${RENODE_EXEC_CMD}\$bin_client = @\"${CLIENT_ELF}\"; " +fi +RENODE_EXEC_CMD="${RENODE_EXEC_CMD}include @\"${RESC_REL_PATH}\"" + +"${RENODE_CMD}" -e "${RENODE_EXEC_CMD}" diff --git a/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 b/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 new file mode 100644 index 00000000..56fb3524 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 @@ -0,0 +1,153 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 NXP i.MX RT1064 port. + +param( + [string]$Demo, + [int]$TimeoutSeconds = 24, + [Nullable[int]]$Seed = 12345 +) + +$BoardDir = Resolve-Path "$PSScriptRoot/.." +$BuildDir = Join-Path $BoardDir "build" + +# Optional build if Demo parameter is supplied (incremental, no clean rebuild) +if ($Demo) { + Write-Host "[INFO] Ensuring demo '$Demo' is active and built..." + & "$PSScriptRoot/build.ps1" -Demo $Demo + if ($LASTEXITCODE -ne 0) { + Write-Error "[FAIL] Build failed for demo '$Demo'" + exit 1 + } +} + +# Determine active demo +if ($Demo) { + $cachedDemo = $Demo +} else { + $cachedDemo = "netx_trng_console" + $cacheFile = Join-Path $BuildDir "CMakeCache.txt" + if (Test-Path $cacheFile) { + $match = Select-String -Path $cacheFile -Pattern "^ACTIVE_DEMO:STRING=(.*)$" + if ($match) { + $val = $match.Matches.Groups[1].Value.Trim() + if ($val -and $val -ne "all") { + $cachedDemo = $val + } + } + } +} + +$serverElfRel = "build/app/demos/$cachedDemo/mimxrt1064_threadx.elf" +$clientElfRel = "build/app/demos/$cachedDemo/mimxrt1064_client.elf" + +if (-not (Test-Path (Join-Path $BoardDir $serverElfRel)) -and (Test-Path (Join-Path $BoardDir "build/mimxrt1064_threadx.elf"))) { + $serverElfRel = "build/mimxrt1064_threadx.elf" + $clientElfRel = "build/mimxrt1064_client.elf" +} + +$ServerElf = Join-Path $BoardDir $serverElfRel +$ClientElf = Join-Path $BoardDir $clientElfRel + +if (-not (Test-Path $ServerElf)) { + Write-Error "[FAIL] Binary $ServerElf not found. Please build first using .\scripts\build.ps1 -Demo $cachedDemo" + exit 1 +} + +# Configure test mode, script, and pass marker +if ($cachedDemo -eq "threadx_basic") { + $RescRelPath = "renode/mimxrt1064-headless-single.resc" + $TargetLog = Join-Path $BuildDir "server_uart.log" + $SuccessMarker = "Executing periodic task" + $TestDescription = "ThreadX Core Basic Demo (Task Scheduling & GPIO LED)" +} else { + $RescRelPath = "renode/mimxrt1064-headless-multinode.resc" + $TargetLog = Join-Path $BuildDir "client_uart.log" + $SuccessMarker = "VERIFICATION SUCCESS" + $TestDescription = "NetX Duo Multi-Node Networking Demo ($cachedDemo)" +} + +# Find Renode executable +$RenodeExe = (Get-Command renode -ErrorAction SilentlyContinue).Source +if (-not $RenodeExe -and (Test-Path "C:\Program Files\Renode\renode.exe")) { + $RenodeExe = "C:\Program Files\Renode\renode.exe" +} +if (-not $RenodeExe) { + Write-Error "[FAIL] Renode was not found in PATH or at 'C:\Program Files\Renode\renode.exe'." + exit 1 +} + +# Remove stale log files +Remove-Item (Join-Path $BuildDir "server_uart.log") -Force -ErrorAction SilentlyContinue +Remove-Item (Join-Path $BuildDir "client_uart.log") -Force -ErrorAction SilentlyContinue + +Write-Host "==========================================" +Write-Host "Renode Headless CI Automated Test Runner" +Write-Host "==========================================" +Write-Host "Active Demo: $cachedDemo" +Write-Host "Test Suite: $TestDescription" +Write-Host "Script: $RescRelPath" +if ($null -ne $Seed) { + Write-Host "Seed: $Seed (Deterministic)" +} +Write-Host "Timeout: ${TimeoutSeconds}s" +Write-Host "Log Target: $TargetLog" +Write-Host "" +Write-Host "[INFO] Launching Renode in headless mode..." + +# Build argument list for Renode: pass explicit binary paths, include script, sleep for duration, and quit +# Build argument list for Renode: pass clean relative paths, include script, sleep for duration, and quit +$initCmd = "" +if ($null -ne $Seed) { + $initCmd += "emulation SetSeed $Seed; " +} +$initCmd += "`$bin = @`"$serverElfRel`"; `$bin_server = @`"$serverElfRel`"; " +if (Test-Path $ClientElf) { + $initCmd += "`$bin_client = @`"$clientElfRel`"; " +} +$initCmd += "include @$RescRelPath; sleep $TimeoutSeconds; quit" + +Push-Location $BoardDir + +# Execute Renode directly with clean argument quoting +& $RenodeExe --plain --disable-xwt -e "$initCmd" + +Pop-Location + +# Verify success marker in target log +$pass = $false +if (Test-Path $TargetLog) { + $content = Get-Content $TargetLog -Raw -ErrorAction SilentlyContinue + if ($content -and $content.Contains($SuccessMarker)) { + $pass = $true + } +} + +Write-Host "" +Write-Host "==========================================" +if ($pass) { + Write-Host "[PASS] CI Automated Verification Succeeded!" -ForegroundColor Green + if (Test-Path $TargetLog) { + Write-Host "" + Write-Host "Captured UART Output:" + Get-Content $TargetLog | Select-Object -Last 20 | ForEach-Object { Write-Host " $_" } + } + Write-Host "==========================================" + exit 0 +} else { + Write-Host "[FAIL] CI Automated Verification Failed or Timed Out!" -ForegroundColor Red + if (Test-Path $TargetLog) { + Write-Host "" + Write-Host "Captured Log Output:" + Get-Content $TargetLog | ForEach-Object { Write-Host " $_" } + } + Write-Host "==========================================" + exit 1 +} diff --git a/NXP/MIMXRT1064-EVK/scripts/test_headless.sh b/NXP/MIMXRT1064-EVK/scripts/test_headless.sh new file mode 100644 index 00000000..67940c60 --- /dev/null +++ b/NXP/MIMXRT1064-EVK/scripts/test_headless.sh @@ -0,0 +1,150 @@ +#!/usr/bin/env bash +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/license/mit. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 NXP i.MX RT1064 port. + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +BOARD_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" +BUILD_DIR="${BOARD_DIR}/build" + +TIMEOUT_SECONDS=24 +SEED="12345" +DEMO="" + +while [[ $# -gt 0 ]]; do + case $1 in + -d|--demo) + DEMO="$2" + shift 2 + ;; + -t|--timeout) + TIMEOUT_SECONDS="$2" + shift 2 + ;; + -s|--seed) + SEED="$2" + shift 2 + ;; + *) + shift + ;; + esac +done + +if [ -n "${DEMO}" ]; then + echo "[INFO] Ensuring demo '${DEMO}' is active and built..." + "${SCRIPT_DIR}/build.sh" --demo "${DEMO}" +fi + +CACHED_DEMO="netx_trng_console" +if [ -n "${DEMO}" ]; then + CACHED_DEMO="${DEMO}" +elif [ -f "${BUILD_DIR}/CMakeCache.txt" ]; then + VAL=$(grep -E "^ACTIVE_DEMO:STRING=" "${BUILD_DIR}/CMakeCache.txt" | cut -d'=' -f2 | tr -d ' \r\n') + if [ -n "${VAL}" ] && [ "${VAL}" != "all" ]; then + CACHED_DEMO="${VAL}" + fi +fi + +DEMO_DIR="${BUILD_DIR}/app/demos/${CACHED_DEMO}" +SERVER_ELF="${DEMO_DIR}/mimxrt1064_threadx.elf" +CLIENT_ELF="${DEMO_DIR}/mimxrt1064_client.elf" + +if [ ! -f "${SERVER_ELF}" ] && [ -f "${BUILD_DIR}/mimxrt1064_threadx.elf" ]; then + SERVER_ELF="${BUILD_DIR}/mimxrt1064_threadx.elf" + CLIENT_ELF="${BUILD_DIR}/mimxrt1064_client.elf" +fi + +if [ ! -f "${SERVER_ELF}" ]; then + echo "[FAIL] Binary ${SERVER_ELF} not found. Please build first using ./scripts/build.sh -d ${CACHED_DEMO}" + exit 1 +fi + +if [ "${CACHED_DEMO}" = "threadx_basic" ]; then + RESC_REL_PATH="renode/mimxrt1064-headless-single.resc" + TARGET_LOG="${BUILD_DIR}/server_uart.log" + SUCCESS_MARKER="Executing periodic task" + TEST_DESC="ThreadX Core Basic Demo (Task Scheduling & GPIO LED)" +else + RESC_REL_PATH="renode/mimxrt1064-headless-multinode.resc" + TARGET_LOG="${BUILD_DIR}/client_uart.log" + SUCCESS_MARKER="VERIFICATION SUCCESS" + TEST_DESC="NetX Duo Multi-Node Networking Demo (${CACHED_DEMO})" +fi + +RENODE_CMD="renode" +if ! command -v renode &> /dev/null; then + if [ -f "/opt/renode/renode" ]; then + RENODE_CMD="/opt/renode/renode" + else + echo "[FAIL] Renode was not found in PATH." + exit 1 + fi +fi + +rm -f "${BUILD_DIR}/server_uart.log" "${BUILD_DIR}/client_uart.log" + +echo "==========================================" +echo "Renode Headless CI Automated Test Runner" +echo "==========================================" +echo "Active Demo: ${CACHED_DEMO}" +echo "Test Suite: ${TEST_DESC}" +echo "Script: ${RESC_REL_PATH}" +if [ -n "${SEED}" ]; then + echo "Seed: ${SEED} (Deterministic)" +fi +echo "Timeout: ${TIMEOUT_SECONDS}s" +echo "Log Target: ${TARGET_LOG}" +echo "" +echo "[INFO] Launching Renode in headless mode..." + +cd "${BOARD_DIR}" + +RENODE_EXEC_CMD="" +if [ -n "${SEED}" ]; then + RENODE_EXEC_CMD="emulation SetSeed ${SEED}; " +fi +RENODE_EXEC_CMD="${RENODE_EXEC_CMD}\$bin = @\"${SERVER_ELF}\"; \$bin_server = @\"${SERVER_ELF}\"; " +if [ -f "${CLIENT_ELF}" ]; then + RENODE_EXEC_CMD="${RENODE_EXEC_CMD}\$bin_client = @\"${CLIENT_ELF}\"; " +fi +RENODE_EXEC_CMD="${RENODE_EXEC_CMD}include @\"${RESC_REL_PATH}\"; sleep ${TIMEOUT_SECONDS}; quit" + +"${RENODE_CMD}" --plain --disable-xwt -e "${RENODE_EXEC_CMD}" || true + +PASS=0 +if [ -f "${TARGET_LOG}" ]; then + if grep -q "${SUCCESS_MARKER}" "${TARGET_LOG}" 2>/dev/null; then + PASS=1 + fi +fi + +echo "" +echo "==========================================" +if [ ${PASS} -eq 1 ]; then + echo "[PASS] CI Automated Verification Succeeded!" + echo "" + echo "Captured UART Output:" + tail -n 20 "${TARGET_LOG}" 2>/dev/null || true + echo "==========================================" + exit 0 +else + echo "[FAIL] CI Automated Verification Failed or Timed Out!" + if [ -f "${TARGET_LOG}" ]; then + echo "" + echo "Captured Log Output:" + cat "${TARGET_LOG}" + fi + echo "==========================================" + exit 1 +fi + From d462a7fa3a0ac6d80710fc01955e3789c20be40f Mon Sep 17 00:00:00 2001 From: Ali Eissa Date: Mon, 14 Sep 2026 06:15:29 +0400 Subject: [PATCH 09/13] ci: add NXP MIMXRT1064 build and Renode headless tests to pipeline --- .github/workflows/ci.yml | 126 ++++++++++++++++++++ NXP/MIMXRT1064-EVK/scripts/test_headless.sh | 4 - 2 files changed, 126 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f883765e..7cf59c35 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -262,3 +262,129 @@ jobs: - name: Run Deterministic Headless Renode Test run: | python3 targets/STMicroelectronics/NUCLEO_F401RE/scripts/test_renode.py + + build-arm-nxp: + name: Build NXP i.MX RT1064 (ARM Cortex-M7) + runs-on: ubuntu-24.04 + + env: + GCC_VERSION: 14.3.rel1 + GCC_TARGET: arm-none-eabi + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install CMake and Ninja + run: | + sudo apt-get update + sudo apt-get install -y cmake ninja-build + + - name: Cache the Arm GNU toolchain + id: cache-arm-gcc + uses: actions/cache@v4 + with: + path: toolchain + key: arm-gnu-toolchain-${{ env.GCC_VERSION }}-x86_64-${{ env.GCC_TARGET }} + + - name: Install the Arm GNU toolchain + if: steps.cache-arm-gcc.outputs.cache-hit != 'true' + run: | + set -eu + base="https://developer.arm.com/-/media/Files/downloads/gnu/${GCC_VERSION}/binrel" + archive="arm-gnu-toolchain-${GCC_VERSION}-x86_64-${GCC_TARGET}.tar.xz" + mkdir -p toolchain && cd toolchain + curl -fsSLO "$base/$archive" + curl -fsSLO "$base/$archive.sha256asc" + sha256sum -c "$archive.sha256asc" + tar xf "$archive" + rm -f "$archive" + + - name: Put the toolchain on PATH + run: | + set -eu + echo "$GITHUB_WORKSPACE/toolchain/arm-gnu-toolchain-${GCC_VERSION}-x86_64-${GCC_TARGET}/bin" >> "$GITHUB_PATH" + + - name: Report the toolchain version + run: ${{ env.GCC_TARGET }}-gcc --version + + - name: Fetch NXP SDK & CMSIS Dependencies + run: | + bash NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh + + - name: Build All NXP MIMXRT1064-EVK Demos + run: | + bash NXP/MIMXRT1064-EVK/scripts/build.sh --demo all --rebuild + + - name: Verify Built NXP ELFs + run: | + test -f NXP/MIMXRT1064-EVK/build/app/demos/threadx_basic/mimxrt1064_threadx.elf + test -f NXP/MIMXRT1064-EVK/build/app/demos/netx_echo/mimxrt1064_threadx.elf + test -f NXP/MIMXRT1064-EVK/build/app/demos/netx_echo/mimxrt1064_client.elf + test -f NXP/MIMXRT1064-EVK/build/app/demos/netx_trng_console/mimxrt1064_threadx.elf + test -f NXP/MIMXRT1064-EVK/build/app/demos/netx_trng_console/mimxrt1064_client.elf + echo "[OK] All NXP MIMXRT1064-EVK demo ELFs verified." + + - name: Archive Built NXP ELFs + uses: actions/upload-artifact@v4 + with: + name: nxp-mimxrt1064-demo-elfs + path: NXP/MIMXRT1064-EVK/build/app/demos/ + retention-days: 1 + + test-nxp-renode: + name: Headless Renode Emulation & Assertion Test (NXP i.MX RT1064) + needs: build-arm-nxp + runs-on: ubuntu-24.04 + timeout-minutes: 15 + env: + RENODE_VERSION: 1.16.1 + RENODE_SHA256: 1a532d4b5b82de0dd154970c401e0c7b0e498d17304b2cecc007e306c8f9617c + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Download Built NXP ELFs + uses: actions/download-artifact@v4 + with: + name: nxp-mimxrt1064-demo-elfs + path: NXP/MIMXRT1064-EVK/build/app/demos + + - name: Cache the portable Renode environment + id: cache-renode + uses: actions/cache@v4 + with: + path: ~/renode + key: renode-${{ env.RENODE_VERSION }}-linux-portable + + - name: Install Pinned Portable Renode Emulation Environment + if: steps.cache-renode.outputs.cache-hit != 'true' + run: | + set -euo pipefail + TARBALL="renode-${RENODE_VERSION}.linux-portable.tar.gz" + wget -q "https://github.com/renode/renode/releases/download/v${RENODE_VERSION}/${TARBALL}" + echo "${RENODE_SHA256} ${TARBALL}" | sha256sum --check --strict + mkdir -p $HOME/renode + tar -xzf "${TARBALL}" -C $HOME/renode --strip-components=1 + rm "${TARBALL}" + + - name: Put Renode on PATH + run: echo "$HOME/renode" >> $GITHUB_PATH + + - name: Run Deterministic Headless Renode Test (threadx_basic) + run: | + bash NXP/MIMXRT1064-EVK/scripts/test_headless.sh -d threadx_basic + + - name: Run Deterministic Headless Renode Test (netx_echo) + run: | + bash NXP/MIMXRT1064-EVK/scripts/test_headless.sh -d netx_echo + + - name: Run Deterministic Headless Renode Test (netx_trng_console) + run: | + bash NXP/MIMXRT1064-EVK/scripts/test_headless.sh -d netx_trng_console -s 12345 + diff --git a/NXP/MIMXRT1064-EVK/scripts/test_headless.sh b/NXP/MIMXRT1064-EVK/scripts/test_headless.sh index 67940c60..2164bc08 100644 --- a/NXP/MIMXRT1064-EVK/scripts/test_headless.sh +++ b/NXP/MIMXRT1064-EVK/scripts/test_headless.sh @@ -40,10 +40,6 @@ while [[ $# -gt 0 ]]; do esac done -if [ -n "${DEMO}" ]; then - echo "[INFO] Ensuring demo '${DEMO}' is active and built..." - "${SCRIPT_DIR}/build.sh" --demo "${DEMO}" -fi CACHED_DEMO="netx_trng_console" if [ -n "${DEMO}" ]; then From 751d6a312ae71e56ea3cd4f5d08e9e5472a67333 Mon Sep 17 00:00:00 2001 From: Ali Eissa Date: Mon, 14 Sep 2026 06:52:23 +0400 Subject: [PATCH 10/13] fix(ci/mimxrt1064-evk): resolve Renode headless test hang and make execution deterministic --- .../renode/mimxrt1064-headless-multinode.resc | 4 ++- .../renode/mimxrt1064-headless-single.resc | 3 +- NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 | 18 ++++++----- NXP/MIMXRT1064-EVK/scripts/test_headless.sh | 32 ++++++++++++++----- 4 files changed, 39 insertions(+), 18 deletions(-) diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc index 4f695be6..a2e4b70f 100644 --- a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc @@ -40,4 +40,6 @@ cpu PC `sysbus ReadDoubleWord 0x70002004` cpu SP `sysbus ReadDoubleWord 0x70002000` # 4. Start Simulation -start +emulation RunFor "3" + +quit diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc index 7e4f74bd..3ffe533f 100644 --- a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc @@ -22,5 +22,6 @@ cpu VectorTableOffset 0x70002000 sysbus LoadELF $bin cpu PC `sysbus ReadDoubleWord 0x70002004` cpu SP `sysbus ReadDoubleWord 0x70002000` +emulation RunFor "3" -start +quit diff --git a/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 b/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 index 56fb3524..bc737c27 100644 --- a/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 +++ b/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 @@ -102,22 +102,24 @@ Write-Host "Log Target: $TargetLog" Write-Host "" Write-Host "[INFO] Launching Renode in headless mode..." -# Build argument list for Renode: pass explicit binary paths, include script, sleep for duration, and quit -# Build argument list for Renode: pass clean relative paths, include script, sleep for duration, and quit -$initCmd = "" +# Generate clean ci_runner.resc +$ciRunner = Join-Path $BuildDir "ci_runner.resc" +$rescLines = @() if ($null -ne $Seed) { - $initCmd += "emulation SetSeed $Seed; " + $rescLines += "emulation SetSeed $Seed" } -$initCmd += "`$bin = @`"$serverElfRel`"; `$bin_server = @`"$serverElfRel`"; " +$rescLines += "`$bin = @$serverElfRel" +$rescLines += "`$bin_server = @$serverElfRel" if (Test-Path $ClientElf) { - $initCmd += "`$bin_client = @`"$clientElfRel`"; " + $rescLines += "`$bin_client = @$clientElfRel" } -$initCmd += "include @$RescRelPath; sleep $TimeoutSeconds; quit" +$rescLines += "include @$RescRelPath" +$rescLines | Set-Content -Path $ciRunner -Encoding ASCII Push-Location $BoardDir # Execute Renode directly with clean argument quoting -& $RenodeExe --plain --disable-xwt -e "$initCmd" +& $RenodeExe --plain --disable-gui --port -1 -e "include @build/ci_runner.resc" Pop-Location diff --git a/NXP/MIMXRT1064-EVK/scripts/test_headless.sh b/NXP/MIMXRT1064-EVK/scripts/test_headless.sh index 2164bc08..40676e8e 100644 --- a/NXP/MIMXRT1064-EVK/scripts/test_headless.sh +++ b/NXP/MIMXRT1064-EVK/scripts/test_headless.sh @@ -16,7 +16,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" BOARD_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" BUILD_DIR="${BOARD_DIR}/build" -TIMEOUT_SECONDS=24 +TIMEOUT_SECONDS=60 SEED="12345" DEMO="" @@ -105,17 +105,33 @@ echo "[INFO] Launching Renode in headless mode..." cd "${BOARD_DIR}" -RENODE_EXEC_CMD="" +SERVER_ELF_REL="build/app/demos/${CACHED_DEMO}/mimxrt1064_threadx.elf" +CLIENT_ELF_REL="build/app/demos/${CACHED_DEMO}/mimxrt1064_client.elf" +if [ ! -f "${BOARD_DIR}/${SERVER_ELF_REL}" ] && [ -f "${BUILD_DIR}/mimxrt1064_threadx.elf" ]; then + SERVER_ELF_REL="build/mimxrt1064_threadx.elf" + CLIENT_ELF_REL="build/mimxrt1064_client.elf" +fi + +CI_RUNNER="${BUILD_DIR}/ci_runner.resc" +mkdir -p "${BUILD_DIR}" +rm -f "${CI_RUNNER}" + if [ -n "${SEED}" ]; then - RENODE_EXEC_CMD="emulation SetSeed ${SEED}; " + echo "emulation SetSeed ${SEED}" >> "${CI_RUNNER}" fi -RENODE_EXEC_CMD="${RENODE_EXEC_CMD}\$bin = @\"${SERVER_ELF}\"; \$bin_server = @\"${SERVER_ELF}\"; " -if [ -f "${CLIENT_ELF}" ]; then - RENODE_EXEC_CMD="${RENODE_EXEC_CMD}\$bin_client = @\"${CLIENT_ELF}\"; " +echo "\$bin = @${SERVER_ELF_REL}" >> "${CI_RUNNER}" +echo "\$bin_server = @${SERVER_ELF_REL}" >> "${CI_RUNNER}" +if [ -f "${BOARD_DIR}/${CLIENT_ELF_REL}" ]; then + echo "\$bin_client = @${CLIENT_ELF_REL}" >> "${CI_RUNNER}" +fi +echo "include @${RESC_REL_PATH}" >> "${CI_RUNNER}" + +TIMEOUT_CMD=() +if command -v timeout &> /dev/null; then + TIMEOUT_CMD=(timeout "${TIMEOUT_SECONDS}s") fi -RENODE_EXEC_CMD="${RENODE_EXEC_CMD}include @\"${RESC_REL_PATH}\"; sleep ${TIMEOUT_SECONDS}; quit" -"${RENODE_CMD}" --plain --disable-xwt -e "${RENODE_EXEC_CMD}" || true +"${TIMEOUT_CMD[@]}" "${RENODE_CMD}" --plain --disable-gui --port -1 -e "include @build/ci_runner.resc" < /dev/null || true PASS=0 if [ -f "${TARGET_LOG}" ]; then From 3f04ac3dfbf0037de41575cee798af40ed6c9803 Mon Sep 17 00:00:00 2001 From: Ali Eissa Date: Mon, 14 Sep 2026 07:41:21 +0400 Subject: [PATCH 11/13] ci: add robust python-based renode test runner for nxp mimxrt1064 --- .github/workflows/ci.yml | 11 +- .../renode/mimxrt1064-headless-multinode.resc | 15 +- .../renode/mimxrt1064-headless-single.resc | 7 +- NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 | 148 ++--------- NXP/MIMXRT1064-EVK/scripts/test_headless.sh | 151 +----------- NXP/MIMXRT1064-EVK/scripts/test_renode.py | 230 ++++++++++++++++++ 6 files changed, 273 insertions(+), 289 deletions(-) create mode 100644 NXP/MIMXRT1064-EVK/scripts/test_renode.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7cf59c35..fa74c719 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -349,6 +349,11 @@ jobs: with: submodules: recursive + - name: Set Up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: Download Built NXP ELFs uses: actions/download-artifact@v4 with: @@ -378,13 +383,13 @@ jobs: - name: Run Deterministic Headless Renode Test (threadx_basic) run: | - bash NXP/MIMXRT1064-EVK/scripts/test_headless.sh -d threadx_basic + python3 NXP/MIMXRT1064-EVK/scripts/test_renode.py --demo threadx_basic - name: Run Deterministic Headless Renode Test (netx_echo) run: | - bash NXP/MIMXRT1064-EVK/scripts/test_headless.sh -d netx_echo + python3 NXP/MIMXRT1064-EVK/scripts/test_renode.py --demo netx_echo - name: Run Deterministic Headless Renode Test (netx_trng_console) run: | - bash NXP/MIMXRT1064-EVK/scripts/test_headless.sh -d netx_trng_console -s 12345 + python3 NXP/MIMXRT1064-EVK/scripts/test_renode.py --demo netx_trng_console --seed 12345 diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc index a2e4b70f..1d82a05e 100644 --- a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc @@ -12,16 +12,18 @@ :name: MIMXRT1064-EVK Headless Multi-Node CI Test :description: Headless two-node verification connecting server and client via virtual switch. +$platform?=$ORIGIN/mimxrt1064-evk.repl +$bin_server?=$ORIGIN/../build/app/demos/netx_echo/mimxrt1064_threadx.elf +$bin_client?=$ORIGIN/../build/app/demos/netx_echo/mimxrt1064_client.elf + # 1. Create Virtual Ethernet Switch emulation CreateSwitch "switch" # 2. Server Machine (192.168.0.100) mach create "server" -machine LoadPlatformDescription $ORIGIN/mimxrt1064-evk.repl +machine LoadPlatformDescription $platform connector Connect sysbus.enet switch -sysbus.lpuart1 CreateFileBackend $ORIGIN/../build/server_uart.log true -$bin_server?=$ORIGIN/../build/mimxrt1064_threadx.elf cpu VectorTableOffset 0x70002000 sysbus LoadELF $bin_server cpu PC `sysbus ReadDoubleWord 0x70002004` @@ -29,17 +31,16 @@ cpu SP `sysbus ReadDoubleWord 0x70002000` # 3. Client Machine (192.168.0.101) mach create "client" -machine LoadPlatformDescription $ORIGIN/mimxrt1064-evk.repl +machine LoadPlatformDescription $platform connector Connect sysbus.enet switch -sysbus.lpuart1 CreateFileBackend $ORIGIN/../build/client_uart.log true +showAnalyzer sysbus.lpuart1 -$bin_client?=$ORIGIN/../build/mimxrt1064_client.elf cpu VectorTableOffset 0x70002000 sysbus LoadELF $bin_client cpu PC `sysbus ReadDoubleWord 0x70002004` cpu SP `sysbus ReadDoubleWord 0x70002000` # 4. Start Simulation -emulation RunFor "3" +emulation RunFor "6" quit diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc index 3ffe533f..81a37c9e 100644 --- a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc @@ -13,11 +13,12 @@ :description: Headless single-node verification capturing LPUART1 output to log file. mach create "mimxrt1064-evk" -machine LoadPlatformDescription $ORIGIN/mimxrt1064-evk.repl +$platform?=$ORIGIN/mimxrt1064-evk.repl +machine LoadPlatformDescription $platform -sysbus.lpuart1 CreateFileBackend $ORIGIN/../build/server_uart.log true +showAnalyzer sysbus.lpuart1 -$bin?=$ORIGIN/../build/mimxrt1064_threadx.elf +$bin?=$ORIGIN/../build/app/demos/threadx_basic/mimxrt1064_threadx.elf cpu VectorTableOffset 0x70002000 sysbus LoadELF $bin cpu PC `sysbus ReadDoubleWord 0x70002004` diff --git a/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 b/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 index bc737c27..7cb98c30 100644 --- a/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 +++ b/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 @@ -10,146 +10,26 @@ # Ali Eissa - 2026 NXP i.MX RT1064 port. param( - [string]$Demo, - [int]$TimeoutSeconds = 24, - [Nullable[int]]$Seed = 12345 + [string]$Demo = "threadx_basic", + [int]$TimeoutSeconds = 120, + [Nullable[int]]$Seed ) -$BoardDir = Resolve-Path "$PSScriptRoot/.." -$BuildDir = Join-Path $BoardDir "build" +$scriptPath = Join-Path $PSScriptRoot "test_renode.py" -# Optional build if Demo parameter is supplied (incremental, no clean rebuild) -if ($Demo) { - Write-Host "[INFO] Ensuring demo '$Demo' is active and built..." - & "$PSScriptRoot/build.ps1" -Demo $Demo - if ($LASTEXITCODE -ne 0) { - Write-Error "[FAIL] Build failed for demo '$Demo'" - exit 1 - } -} - -# Determine active demo -if ($Demo) { - $cachedDemo = $Demo -} else { - $cachedDemo = "netx_trng_console" - $cacheFile = Join-Path $BuildDir "CMakeCache.txt" - if (Test-Path $cacheFile) { - $match = Select-String -Path $cacheFile -Pattern "^ACTIVE_DEMO:STRING=(.*)$" - if ($match) { - $val = $match.Matches.Groups[1].Value.Trim() - if ($val -and $val -ne "all") { - $cachedDemo = $val - } - } - } -} - -$serverElfRel = "build/app/demos/$cachedDemo/mimxrt1064_threadx.elf" -$clientElfRel = "build/app/demos/$cachedDemo/mimxrt1064_client.elf" - -if (-not (Test-Path (Join-Path $BoardDir $serverElfRel)) -and (Test-Path (Join-Path $BoardDir "build/mimxrt1064_threadx.elf"))) { - $serverElfRel = "build/mimxrt1064_threadx.elf" - $clientElfRel = "build/mimxrt1064_client.elf" -} - -$ServerElf = Join-Path $BoardDir $serverElfRel -$ClientElf = Join-Path $BoardDir $clientElfRel - -if (-not (Test-Path $ServerElf)) { - Write-Error "[FAIL] Binary $ServerElf not found. Please build first using .\scripts\build.ps1 -Demo $cachedDemo" - exit 1 -} - -# Configure test mode, script, and pass marker -if ($cachedDemo -eq "threadx_basic") { - $RescRelPath = "renode/mimxrt1064-headless-single.resc" - $TargetLog = Join-Path $BuildDir "server_uart.log" - $SuccessMarker = "Executing periodic task" - $TestDescription = "ThreadX Core Basic Demo (Task Scheduling & GPIO LED)" -} else { - $RescRelPath = "renode/mimxrt1064-headless-multinode.resc" - $TargetLog = Join-Path $BuildDir "client_uart.log" - $SuccessMarker = "VERIFICATION SUCCESS" - $TestDescription = "NetX Duo Multi-Node Networking Demo ($cachedDemo)" -} - -# Find Renode executable -$RenodeExe = (Get-Command renode -ErrorAction SilentlyContinue).Source -if (-not $RenodeExe -and (Test-Path "C:\Program Files\Renode\renode.exe")) { - $RenodeExe = "C:\Program Files\Renode\renode.exe" -} -if (-not $RenodeExe) { - Write-Error "[FAIL] Renode was not found in PATH or at 'C:\Program Files\Renode\renode.exe'." - exit 1 -} - -# Remove stale log files -Remove-Item (Join-Path $BuildDir "server_uart.log") -Force -ErrorAction SilentlyContinue -Remove-Item (Join-Path $BuildDir "client_uart.log") -Force -ErrorAction SilentlyContinue - -Write-Host "==========================================" -Write-Host "Renode Headless CI Automated Test Runner" -Write-Host "==========================================" -Write-Host "Active Demo: $cachedDemo" -Write-Host "Test Suite: $TestDescription" -Write-Host "Script: $RescRelPath" +$pythonArgs = @($scriptPath, "--demo", $Demo, "--timeout", $TimeoutSeconds) if ($null -ne $Seed) { - Write-Host "Seed: $Seed (Deterministic)" + $pythonArgs += @("--seed", $Seed) } -Write-Host "Timeout: ${TimeoutSeconds}s" -Write-Host "Log Target: $TargetLog" -Write-Host "" -Write-Host "[INFO] Launching Renode in headless mode..." -# Generate clean ci_runner.resc -$ciRunner = Join-Path $BuildDir "ci_runner.resc" -$rescLines = @() -if ($null -ne $Seed) { - $rescLines += "emulation SetSeed $Seed" -} -$rescLines += "`$bin = @$serverElfRel" -$rescLines += "`$bin_server = @$serverElfRel" -if (Test-Path $ClientElf) { - $rescLines += "`$bin_client = @$clientElfRel" +$pythonExe = (Get-Command python3 -ErrorAction SilentlyContinue).Source +if (-not $pythonExe) { + $pythonExe = (Get-Command python -ErrorAction SilentlyContinue).Source } -$rescLines += "include @$RescRelPath" -$rescLines | Set-Content -Path $ciRunner -Encoding ASCII - -Push-Location $BoardDir - -# Execute Renode directly with clean argument quoting -& $RenodeExe --plain --disable-gui --port -1 -e "include @build/ci_runner.resc" - -Pop-Location - -# Verify success marker in target log -$pass = $false -if (Test-Path $TargetLog) { - $content = Get-Content $TargetLog -Raw -ErrorAction SilentlyContinue - if ($content -and $content.Contains($SuccessMarker)) { - $pass = $true - } -} - -Write-Host "" -Write-Host "==========================================" -if ($pass) { - Write-Host "[PASS] CI Automated Verification Succeeded!" -ForegroundColor Green - if (Test-Path $TargetLog) { - Write-Host "" - Write-Host "Captured UART Output:" - Get-Content $TargetLog | Select-Object -Last 20 | ForEach-Object { Write-Host " $_" } - } - Write-Host "==========================================" - exit 0 -} else { - Write-Host "[FAIL] CI Automated Verification Failed or Timed Out!" -ForegroundColor Red - if (Test-Path $TargetLog) { - Write-Host "" - Write-Host "Captured Log Output:" - Get-Content $TargetLog | ForEach-Object { Write-Host " $_" } - } - Write-Host "==========================================" +if (-not $pythonExe) { + Write-Error "[FAIL] Python was not found in PATH." exit 1 } + +& $pythonExe @pythonArgs +exit $LASTEXITCODE diff --git a/NXP/MIMXRT1064-EVK/scripts/test_headless.sh b/NXP/MIMXRT1064-EVK/scripts/test_headless.sh index 40676e8e..24bbc030 100644 --- a/NXP/MIMXRT1064-EVK/scripts/test_headless.sh +++ b/NXP/MIMXRT1064-EVK/scripts/test_headless.sh @@ -13,150 +13,17 @@ set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -BOARD_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" -BUILD_DIR="${BOARD_DIR}/build" -TIMEOUT_SECONDS=60 -SEED="12345" -DEMO="" - -while [[ $# -gt 0 ]]; do - case $1 in - -d|--demo) - DEMO="$2" - shift 2 - ;; - -t|--timeout) - TIMEOUT_SECONDS="$2" - shift 2 - ;; - -s|--seed) - SEED="$2" - shift 2 - ;; - *) - shift - ;; - esac -done - - -CACHED_DEMO="netx_trng_console" -if [ -n "${DEMO}" ]; then - CACHED_DEMO="${DEMO}" -elif [ -f "${BUILD_DIR}/CMakeCache.txt" ]; then - VAL=$(grep -E "^ACTIVE_DEMO:STRING=" "${BUILD_DIR}/CMakeCache.txt" | cut -d'=' -f2 | tr -d ' \r\n') - if [ -n "${VAL}" ] && [ "${VAL}" != "all" ]; then - CACHED_DEMO="${VAL}" - fi -fi - -DEMO_DIR="${BUILD_DIR}/app/demos/${CACHED_DEMO}" -SERVER_ELF="${DEMO_DIR}/mimxrt1064_threadx.elf" -CLIENT_ELF="${DEMO_DIR}/mimxrt1064_client.elf" - -if [ ! -f "${SERVER_ELF}" ] && [ -f "${BUILD_DIR}/mimxrt1064_threadx.elf" ]; then - SERVER_ELF="${BUILD_DIR}/mimxrt1064_threadx.elf" - CLIENT_ELF="${BUILD_DIR}/mimxrt1064_client.elf" -fi - -if [ ! -f "${SERVER_ELF}" ]; then - echo "[FAIL] Binary ${SERVER_ELF} not found. Please build first using ./scripts/build.sh -d ${CACHED_DEMO}" - exit 1 -fi - -if [ "${CACHED_DEMO}" = "threadx_basic" ]; then - RESC_REL_PATH="renode/mimxrt1064-headless-single.resc" - TARGET_LOG="${BUILD_DIR}/server_uart.log" - SUCCESS_MARKER="Executing periodic task" - TEST_DESC="ThreadX Core Basic Demo (Task Scheduling & GPIO LED)" -else - RESC_REL_PATH="renode/mimxrt1064-headless-multinode.resc" - TARGET_LOG="${BUILD_DIR}/client_uart.log" - SUCCESS_MARKER="VERIFICATION SUCCESS" - TEST_DESC="NetX Duo Multi-Node Networking Demo (${CACHED_DEMO})" -fi - -RENODE_CMD="renode" -if ! command -v renode &> /dev/null; then - if [ -f "/opt/renode/renode" ]; then - RENODE_CMD="/opt/renode/renode" - else - echo "[FAIL] Renode was not found in PATH." - exit 1 - fi -fi - -rm -f "${BUILD_DIR}/server_uart.log" "${BUILD_DIR}/client_uart.log" - -echo "==========================================" -echo "Renode Headless CI Automated Test Runner" -echo "==========================================" -echo "Active Demo: ${CACHED_DEMO}" -echo "Test Suite: ${TEST_DESC}" -echo "Script: ${RESC_REL_PATH}" -if [ -n "${SEED}" ]; then - echo "Seed: ${SEED} (Deterministic)" -fi -echo "Timeout: ${TIMEOUT_SECONDS}s" -echo "Log Target: ${TARGET_LOG}" -echo "" -echo "[INFO] Launching Renode in headless mode..." - -cd "${BOARD_DIR}" - -SERVER_ELF_REL="build/app/demos/${CACHED_DEMO}/mimxrt1064_threadx.elf" -CLIENT_ELF_REL="build/app/demos/${CACHED_DEMO}/mimxrt1064_client.elf" -if [ ! -f "${BOARD_DIR}/${SERVER_ELF_REL}" ] && [ -f "${BUILD_DIR}/mimxrt1064_threadx.elf" ]; then - SERVER_ELF_REL="build/mimxrt1064_threadx.elf" - CLIENT_ELF_REL="build/mimxrt1064_client.elf" -fi - -CI_RUNNER="${BUILD_DIR}/ci_runner.resc" -mkdir -p "${BUILD_DIR}" -rm -f "${CI_RUNNER}" - -if [ -n "${SEED}" ]; then - echo "emulation SetSeed ${SEED}" >> "${CI_RUNNER}" -fi -echo "\$bin = @${SERVER_ELF_REL}" >> "${CI_RUNNER}" -echo "\$bin_server = @${SERVER_ELF_REL}" >> "${CI_RUNNER}" -if [ -f "${BOARD_DIR}/${CLIENT_ELF_REL}" ]; then - echo "\$bin_client = @${CLIENT_ELF_REL}" >> "${CI_RUNNER}" -fi -echo "include @${RESC_REL_PATH}" >> "${CI_RUNNER}" - -TIMEOUT_CMD=() -if command -v timeout &> /dev/null; then - TIMEOUT_CMD=(timeout "${TIMEOUT_SECONDS}s") -fi - -"${TIMEOUT_CMD[@]}" "${RENODE_CMD}" --plain --disable-gui --port -1 -e "include @build/ci_runner.resc" < /dev/null || true - -PASS=0 -if [ -f "${TARGET_LOG}" ]; then - if grep -q "${SUCCESS_MARKER}" "${TARGET_LOG}" 2>/dev/null; then - PASS=1 - fi -fi - -echo "" -echo "==========================================" -if [ ${PASS} -eq 1 ]; then - echo "[PASS] CI Automated Verification Succeeded!" - echo "" - echo "Captured UART Output:" - tail -n 20 "${TARGET_LOG}" 2>/dev/null || true - echo "==========================================" - exit 0 +PYTHON_BIN="" +if command -v python3 &>/dev/null && python3 --version &>/dev/null; then + PYTHON_BIN="python3" +elif command -v python &>/dev/null && python --version &>/dev/null; then + PYTHON_BIN="python" +elif command -v py &>/dev/null && py -3 --version &>/dev/null; then + PYTHON_BIN="py -3" else - echo "[FAIL] CI Automated Verification Failed or Timed Out!" - if [ -f "${TARGET_LOG}" ]; then - echo "" - echo "Captured Log Output:" - cat "${TARGET_LOG}" - fi - echo "==========================================" + echo "[FAIL] Python was not found in PATH." exit 1 fi +exec ${PYTHON_BIN} "${SCRIPT_DIR}/test_renode.py" "$@" diff --git a/NXP/MIMXRT1064-EVK/scripts/test_renode.py b/NXP/MIMXRT1064-EVK/scripts/test_renode.py new file mode 100644 index 00000000..0a59ebcf --- /dev/null +++ b/NXP/MIMXRT1064-EVK/scripts/test_renode.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/licenses/MIT. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 NXP i.MX RT1064 port. + +""" +Headless Renode Verification Test for NXP i.MX RT1064-EVK Demos. + +Runs deterministic virtual-time emulation in Antmicro Renode and asserts on +the streamed LPUART1 console output via showAnalyzer. +""" + +import argparse +import os +import queue +import shutil +import subprocess +import sys +import threading +import time + +DEMO_CONFIGS = { + "threadx_basic": { + "description": "ThreadX Core Basic Demo (Task Scheduling & GPIO LED)", + "resc": "mimxrt1064-headless-single.resc", + "multinode": False, + "marker": "Executing periodic task", + }, + "netx_echo": { + "description": "NetX Duo Multi-Node Echo Demo (ICMP, UDP, TCP)", + "resc": "mimxrt1064-headless-multinode.resc", + "multinode": True, + "marker": "[VERIFICATION SUCCESS] ALL NETWORK TESTS PASSED!", + }, + "netx_trng_console": { + "description": "NetX Duo Multi-Node Hardware TRNG & Console Demo", + "resc": "mimxrt1064-headless-multinode.resc", + "multinode": True, + "marker": "[VERIFICATION SUCCESS] ALL TRNG & CONSOLE TESTS PASSED!", + }, +} + + +def find_renode(): + renode_bin = shutil.which("renode") + if renode_bin: + return renode_bin + + candidates = [ + r"C:\Program Files\Renode\renode.exe", + os.path.expanduser(r"~\AppData\Local\Programs\Renode\renode.exe"), + os.path.expanduser(r"~/renode/renode"), + "/opt/renode/renode", + "/usr/bin/renode", + ] + for path in candidates: + if os.path.isfile(path): + return path + + return "renode" + + +def reader_thread_fn(pipe, q): + try: + for line in iter(pipe.readline, ""): + q.put(line) + except Exception: + pass + finally: + pipe.close() + + +def run_test(demo_name, seed=None, timeout_seconds=120): + if demo_name not in DEMO_CONFIGS: + print(f"[FAIL] Unknown demo: {demo_name}. Choices: {list(DEMO_CONFIGS.keys())}") + return 1 + + config = DEMO_CONFIGS[demo_name] + renode = find_renode() + + script_dir = os.path.dirname(os.path.abspath(__file__)) + board_dir = os.path.dirname(script_dir) + build_dir = os.path.join(board_dir, "build") + resc_rel = f"renode/{config['resc']}" + + # Check binary existence + demo_dir = os.path.join(build_dir, "app", "demos", demo_name) + server_elf = os.path.join(demo_dir, "mimxrt1064_threadx.elf") + if not os.path.isfile(server_elf): + fallback = os.path.join(build_dir, "mimxrt1064_threadx.elf") + if os.path.isfile(fallback): + server_elf = fallback + else: + print(f"[FAIL] Server ELF binary not found: {server_elf}") + return 1 + + if config["multinode"]: + client_elf = os.path.join(demo_dir, "mimxrt1064_client.elf") + if not os.path.isfile(client_elf): + fallback_c = os.path.join(build_dir, "mimxrt1064_client.elf") + if not os.path.isfile(fallback_c): + print(f"[FAIL] Client ELF binary not found: {client_elf}") + return 1 + + server_elf_rel = os.path.relpath(server_elf, board_dir).replace("\\", "/") + cmd_parts = [] + if seed is not None: + cmd_parts.append(f"emulation SetSeed {seed}") + + if config["multinode"]: + client_elf_rel = os.path.relpath(client_elf, board_dir).replace("\\", "/") + cmd_parts.append(f"$bin_server = @{server_elf_rel}") + cmd_parts.append(f"$bin_client = @{client_elf_rel}") + else: + cmd_parts.append(f"$bin = @{server_elf_rel}") + + cmd_parts.append(f"include @{resc_rel}") + renode_script_cmd = "; ".join(cmd_parts) + + cmd = [ + renode, + "--plain", + "--disable-gui", + "--port", "-1", + "-e", renode_script_cmd + ] + + print("==========================================") + print("Renode Headless CI Automated Test Runner") + print("==========================================") + print(f"Active Demo: {demo_name}") + print(f"Test Suite: {config['description']}") + print(f"Script: {config['resc']}") + if seed is not None: + print(f"Seed: {seed} (Deterministic)") + print(f"Timeout: {timeout_seconds}s") + print(f"Engine: {renode}") + print("") + print("[INFO] Launching Renode in headless mode...") + print("") + + proc = subprocess.Popen( + cmd, + cwd=board_dir, + stdin=subprocess.DEVNULL, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + bufsize=1, + ) + + output_q = queue.Queue() + reader_t = threading.Thread(target=reader_thread_fn, args=(proc.stdout, output_q), daemon=True) + reader_t.start() + + found_marker = False + start_time = time.time() + + try: + while time.time() - start_time < timeout_seconds: + try: + line = output_q.get(timeout=0.1) + sys.stdout.write(line) + sys.stdout.flush() + + if config["marker"] in line: + found_marker = True + break + except queue.Empty: + if proc.poll() is not None: + # Drain remaining output + while not output_q.empty(): + line = output_q.get_nowait() + sys.stdout.write(line) + sys.stdout.flush() + if config["marker"] in line: + found_marker = True + break + finally: + try: + proc.terminate() + proc.wait(timeout=3) + except Exception: + try: + proc.kill() + except Exception: + pass + + print("") + print("==========================================") + if found_marker: + print(f"[PASS] CI Automated Verification Succeeded for '{demo_name}'!") + print("==========================================") + return 0 + else: + print(f"[FAIL] CI Automated Verification Failed or Timed Out for '{demo_name}'!") + print(f" Expected assertion marker: '{config['marker']}'") + print("==========================================") + return 1 + + +def main(): + parser = argparse.ArgumentParser(description="NXP MIMXRT1064-EVK Headless Renode Test Runner") + parser.add_argument("-d", "--demo", default="threadx_basic", + choices=["threadx_basic", "netx_echo", "netx_trng_console"], + help="Demo application to verify") + parser.add_argument("-s", "--seed", type=int, default=None, + help="Deterministic simulation seed") + parser.add_argument("-t", "--timeout", type=int, default=120, + help="Timeout in seconds (default: 120)") + + args = parser.parse_args() + seed = args.seed + if args.demo == "netx_trng_console" and seed is None: + seed = 12345 + + ret = run_test(args.demo, seed=seed, timeout_seconds=args.timeout) + sys.exit(ret) + + +if __name__ == "__main__": + main() From 9e6117f345345b207d34a18658bfad3e8b234b09 Mon Sep 17 00:00:00 2001 From: Ali Eissa Date: Mon, 14 Sep 2026 08:16:52 +0400 Subject: [PATCH 12/13] fix(ci/nxp): resolve Renode freeze via macro reset and explicit platform binding --- .../renode/mimxrt1064-headless-multinode.resc | 24 ++++++++++++------- .../renode/mimxrt1064-headless-single.resc | 14 +++++++---- NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 | 2 +- NXP/MIMXRT1064-EVK/scripts/test_renode.py | 10 ++++---- 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc index 1d82a05e..3ce28a68 100644 --- a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc @@ -24,10 +24,14 @@ mach create "server" machine LoadPlatformDescription $platform connector Connect sysbus.enet switch -cpu VectorTableOffset 0x70002000 -sysbus LoadELF $bin_server -cpu PC `sysbus ReadDoubleWord 0x70002004` -cpu SP `sysbus ReadDoubleWord 0x70002000` +macro reset +""" + sysbus LoadELF $bin_server + cpu VectorTableOffset 0x70002000 + cpu PC `sysbus ReadDoubleWord 0x70002004` + cpu SP `sysbus ReadDoubleWord 0x70002000` +""" +runMacro $reset # 3. Client Machine (192.168.0.101) mach create "client" @@ -35,10 +39,14 @@ machine LoadPlatformDescription $platform connector Connect sysbus.enet switch showAnalyzer sysbus.lpuart1 -cpu VectorTableOffset 0x70002000 -sysbus LoadELF $bin_client -cpu PC `sysbus ReadDoubleWord 0x70002004` -cpu SP `sysbus ReadDoubleWord 0x70002000` +macro reset +""" + sysbus LoadELF $bin_client + cpu VectorTableOffset 0x70002000 + cpu PC `sysbus ReadDoubleWord 0x70002004` + cpu SP `sysbus ReadDoubleWord 0x70002000` +""" +runMacro $reset # 4. Start Simulation emulation RunFor "6" diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc index 81a37c9e..ca02102f 100644 --- a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc @@ -19,10 +19,16 @@ machine LoadPlatformDescription $platform showAnalyzer sysbus.lpuart1 $bin?=$ORIGIN/../build/app/demos/threadx_basic/mimxrt1064_threadx.elf -cpu VectorTableOffset 0x70002000 -sysbus LoadELF $bin -cpu PC `sysbus ReadDoubleWord 0x70002004` -cpu SP `sysbus ReadDoubleWord 0x70002000` + +macro reset +""" + sysbus LoadELF $bin + cpu VectorTableOffset 0x70002000 + cpu PC `sysbus ReadDoubleWord 0x70002004` + cpu SP `sysbus ReadDoubleWord 0x70002000` +""" +runMacro $reset + emulation RunFor "3" quit diff --git a/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 b/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 index 7cb98c30..e23e0f62 100644 --- a/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 +++ b/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 @@ -11,7 +11,7 @@ param( [string]$Demo = "threadx_basic", - [int]$TimeoutSeconds = 120, + [int]$TimeoutSeconds = 300, [Nullable[int]]$Seed ) diff --git a/NXP/MIMXRT1064-EVK/scripts/test_renode.py b/NXP/MIMXRT1064-EVK/scripts/test_renode.py index 0a59ebcf..2137c257 100644 --- a/NXP/MIMXRT1064-EVK/scripts/test_renode.py +++ b/NXP/MIMXRT1064-EVK/scripts/test_renode.py @@ -78,7 +78,7 @@ def reader_thread_fn(pipe, q): pipe.close() -def run_test(demo_name, seed=None, timeout_seconds=120): +def run_test(demo_name, seed=None, timeout_seconds=300): if demo_name not in DEMO_CONFIGS: print(f"[FAIL] Unknown demo: {demo_name}. Choices: {list(DEMO_CONFIGS.keys())}") return 1 @@ -115,6 +115,8 @@ def run_test(demo_name, seed=None, timeout_seconds=120): if seed is not None: cmd_parts.append(f"emulation SetSeed {seed}") + cmd_parts.append("$platform = @renode/mimxrt1064-evk.repl") + if config["multinode"]: client_elf_rel = os.path.relpath(client_elf, board_dir).replace("\\", "/") cmd_parts.append(f"$bin_server = @{server_elf_rel}") @@ -150,7 +152,7 @@ def run_test(demo_name, seed=None, timeout_seconds=120): proc = subprocess.Popen( cmd, cwd=board_dir, - stdin=subprocess.DEVNULL, + stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, @@ -214,8 +216,8 @@ def main(): help="Demo application to verify") parser.add_argument("-s", "--seed", type=int, default=None, help="Deterministic simulation seed") - parser.add_argument("-t", "--timeout", type=int, default=120, - help="Timeout in seconds (default: 120)") + parser.add_argument("-t", "--timeout", type=int, default=300, + help="Timeout in seconds (default: 300)") args = parser.parse_args() seed = args.seed From 570cd5c7d525434c03b31ef3fc7208a651e886e7 Mon Sep 17 00:00:00 2001 From: Ali Eissa Date: Mon, 14 Sep 2026 08:28:45 +0400 Subject: [PATCH 13/13] fix(ci/nxp) timing fix --- NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc | 2 +- NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc index 3ce28a68..95efb5f6 100644 --- a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc @@ -49,6 +49,6 @@ macro reset runMacro $reset # 4. Start Simulation -emulation RunFor "6" +emulation RunFor "200" quit diff --git a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc index ca02102f..56563a85 100644 --- a/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc +++ b/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc @@ -29,6 +29,6 @@ macro reset """ runMacro $reset -emulation RunFor "3" +emulation RunFor "30" quit