summaryrefslogtreecommitdiff
path: root/test/tx/cmake
diff options
context:
space:
mode:
Diffstat (limited to 'test/tx/cmake')
-rw-r--r--test/tx/cmake/CMakeLists.txt94
-rwxr-xr-xtest/tx/cmake/coverage.sh11
-rw-r--r--test/tx/cmake/regression/CMakeLists.txt45
-rw-r--r--test/tx/cmake/regression/generate_test_file.cmake42
-rwxr-xr-xtest/tx/cmake/regression/generate_test_file.sh11
-rw-r--r--test/tx/cmake/riscv/CMakeLists.txt87
-rw-r--r--test/tx/cmake/riscv/bsp/CMakeLists.txt25
-rw-r--r--test/tx/cmake/riscv/bsp/board.c30
-rw-r--r--test/tx/cmake/riscv/bsp/csr.h84
-rw-r--r--test/tx/cmake/riscv/bsp/entry.S75
-rw-r--r--test/tx/cmake/riscv/bsp/hwtimer.c33
-rw-r--r--test/tx/cmake/riscv/bsp/hwtimer.h22
-rw-r--r--test/tx/cmake/riscv/bsp/link.lds60
-rw-r--r--test/tx/cmake/riscv/bsp/plic.c87
-rw-r--r--test/tx/cmake/riscv/bsp/plic.h46
-rw-r--r--test/tx/cmake/riscv/bsp/printf.c168
-rw-r--r--test/tx/cmake/riscv/bsp/syscalls.c128
-rw-r--r--test/tx/cmake/riscv/bsp/trap.c84
-rw-r--r--test/tx/cmake/riscv/bsp/tx_initialize_low_level.S100
-rw-r--r--test/tx/cmake/riscv/bsp/uart.c79
-rw-r--r--test/tx/cmake/riscv/bsp/uart.h22
-rw-r--r--test/tx/cmake/riscv/regression/CMakeLists.txt177
-rwxr-xr-xtest/tx/cmake/riscv/run.sh162
-rw-r--r--test/tx/cmake/samples/fake.c11
24 files changed, 1637 insertions, 46 deletions
diff --git a/test/tx/cmake/CMakeLists.txt b/test/tx/cmake/CMakeLists.txt
index 2dd16ade..97b3615b 100644
--- a/test/tx/cmake/CMakeLists.txt
+++ b/test/tx/cmake/CMakeLists.txt
@@ -2,8 +2,16 @@ cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
cmake_policy(SET CMP0054 NEW)
cmake_policy(SET CMP0057 NEW)
+if((DEFINED THREADX_ARCH) AND ((THREADX_ARCH STREQUAL "win32") OR (THREADX_ARCH STREQUAL "win64")))
+ set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+endif()
+
project(threadx_test LANGUAGES C)
+set(CMAKE_C_STANDARD 99)
+set(CMAKE_C_STANDARD_REQUIRED ON)
+set(CMAKE_C_EXTENSIONS OFF)
+
# Set build configurations
set(BUILD_CONFIGURATIONS default_build_coverage disable_notify_callbacks_build
stack_checking_build stack_checking_rand_fill_build trace_build)
@@ -22,24 +30,30 @@ endif()
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}.")
-set(default_build_coverage -DTX_QUEUE_MESSAGE_MAX_SIZE=32)
-set(disable_notify_callbacks_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_DISABLE_NOTIFY_CALLBACKS)
-set(stack_checking_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_ENABLE_STACK_CHECKING)
-set(stack_checking_rand_fill_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_ENABLE_STACK_CHECKING -DTX_ENABLE_RANDOM_NUMBER_STACK_FILLING)
-set(trace_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_ENABLE_EVENT_TRACE)
+set(default_build_coverage TX_QUEUE_MESSAGE_MAX_SIZE=32)
+set(disable_notify_callbacks_build TX_QUEUE_MESSAGE_MAX_SIZE=32 TX_DISABLE_NOTIFY_CALLBACKS)
+set(stack_checking_build TX_QUEUE_MESSAGE_MAX_SIZE=32 TX_ENABLE_STACK_CHECKING)
+set(stack_checking_rand_fill_build TX_QUEUE_MESSAGE_MAX_SIZE=32 TX_ENABLE_STACK_CHECKING TX_ENABLE_RANDOM_NUMBER_STACK_FILLING)
+set(trace_build TX_QUEUE_MESSAGE_MAX_SIZE=32 TX_ENABLE_EVENT_TRACE)
-add_compile_options(
- -m32
- -std=c99
- -ggdb
- -g3
- -gdwarf-2
- -fdiagnostics-color
- -Werror
- -DTX_REGRESSION_TEST
- -DTEST_STACK_SIZE_PRINTF=4096
+add_compile_definitions(
+ TX_REGRESSION_TEST
+ TEST_STACK_SIZE_PRINTF=4096
${${CMAKE_BUILD_TYPE}})
-add_link_options(-m32)
+
+if(MSVC)
+ add_compile_options(/W3 /Zi)
+ add_link_options(/DEBUG /INCREMENTAL:NO)
+else()
+ add_compile_options(
+ -m32
+ -ggdb
+ -g3
+ -gdwarf-2
+ -fdiagnostics-color
+ -Werror)
+ add_link_options(-m32)
+endif()
enable_testing()
@@ -49,26 +63,32 @@ add_subdirectory(samples)
# Coverage
if(CMAKE_BUILD_TYPE MATCHES ".*_coverage")
- target_compile_options(threadx PRIVATE -fprofile-arcs -ftest-coverage)
- target_link_options(threadx PRIVATE -fprofile-arcs -ftest-coverage)
+ if(NOT MSVC)
+ target_compile_options(threadx PRIVATE -fprofile-arcs -ftest-coverage)
+ target_link_options(threadx PRIVATE -fprofile-arcs -ftest-coverage)
+ endif()
endif()
-target_compile_options(
- threadx
- PRIVATE -Werror
- -Wall
- -Wextra
- -pedantic
- -fmessage-length=0
- -fsigned-char
- -ffunction-sections
- -fdata-sections
- -Wunused
- -Wuninitialized
- -Wmissing-declarations
- -Wconversion
- -Wpointer-arith
- # -Wshadow
- -Wlogical-op
- -Waggregate-return
- -Wfloat-equal)
+if(MSVC)
+ target_compile_options(threadx PRIVATE /W3)
+else()
+ target_compile_options(
+ threadx
+ PRIVATE -Werror
+ -Wall
+ -Wextra
+ -pedantic
+ -fmessage-length=0
+ -fsigned-char
+ -ffunction-sections
+ -fdata-sections
+ -Wunused
+ -Wuninitialized
+ -Wmissing-declarations
+ -Wconversion
+ -Wpointer-arith
+ # -Wshadow
+ -Wlogical-op
+ -Waggregate-return
+ -Wfloat-equal)
+endif()
diff --git a/test/tx/cmake/coverage.sh b/test/tx/cmake/coverage.sh
index ae2c7a4b..6dda78b3 100755
--- a/test/tx/cmake/coverage.sh
+++ b/test/tx/cmake/coverage.sh
@@ -1,4 +1,15 @@
#!/bin/bash
+##############################################################################
+# 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
+##############################################################################
+
set -e
diff --git a/test/tx/cmake/regression/CMakeLists.txt b/test/tx/cmake/regression/CMakeLists.txt
index d60743fa..34fba1b2 100644
--- a/test/tx/cmake/regression/CMakeLists.txt
+++ b/test/tx/cmake/regression/CMakeLists.txt
@@ -4,6 +4,14 @@ cmake_policy(SET CMP0057 NEW)
project(regression_test LANGUAGES C)
set(SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../regression)
+set(REPO_ROOT ${CMAKE_CURRENT_LIST_DIR}/../../../..)
+set(PORT_LOW_LEVEL_SOURCE ${REPO_ROOT}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/src/tx_initialize_low_level.c)
+set(GENERATED_LOW_LEVEL_SOURCE ${CMAKE_CURRENT_BINARY_DIR}/tx_initialize_low_level.c)
+set(TESTCONTROL_WEAK_DEFAULTS_SOURCE ${REPO_ROOT}/test/shared/regression/testcontrol_weak_defaults.c)
+
+if(NOT EXISTS ${PORT_LOW_LEVEL_SOURCE})
+ message(FATAL_ERROR "Unable to locate tx_initialize_low_level.c for ${THREADX_ARCH}/${THREADX_TOOLCHAIN}")
+endif()
set(regression_test_cases
${SOURCE_DIR}/threadx_block_memory_basic_test.c
@@ -104,19 +112,38 @@ set(regression_test_cases
${SOURCE_DIR}/threadx_initialize_kernel_setup_test.c)
add_custom_command(
- OUTPUT ${SOURCE_DIR}/tx_initialize_low_level.c
- COMMAND bash ${CMAKE_CURRENT_LIST_DIR}/generate_test_file.sh
+ OUTPUT ${GENERATED_LOW_LEVEL_SOURCE}
+ COMMAND ${CMAKE_COMMAND}
+ -DSOURCE_FILE=${PORT_LOW_LEVEL_SOURCE}
+ -DOUTPUT_FILE=${GENERATED_LOW_LEVEL_SOURCE}
+ -P ${CMAKE_CURRENT_LIST_DIR}/generate_test_file.cmake
+ DEPENDS ${PORT_LOW_LEVEL_SOURCE} ${CMAKE_CURRENT_LIST_DIR}/generate_test_file.cmake
COMMENT "Generating tx_initialize_low_level.c for test")
-add_library(test_utility ${SOURCE_DIR}/tx_initialize_low_level.c
- ${SOURCE_DIR}/testcontrol.c)
-target_link_libraries(test_utility PUBLIC azrtos::threadx)
-target_compile_definitions(test_utility PUBLIC CTEST BATCH_TEST
- TEST_STACK_SIZE_PRINTF=4096)
+add_library(test_weak_defaults OBJECT ${TESTCONTROL_WEAK_DEFAULTS_SOURCE})
+target_compile_definitions(test_weak_defaults PRIVATE CTEST BATCH_TEST
+ TEST_STACK_SIZE_PRINTF=4096)
+target_link_libraries(test_weak_defaults PRIVATE azrtos::threadx)
+
+add_library(test_utility OBJECT ${GENERATED_LOW_LEVEL_SOURCE}
+ ${SOURCE_DIR}/testcontrol.c)
+target_compile_definitions(test_utility PRIVATE CTEST BATCH_TEST
+ TEST_STACK_SIZE_PRINTF=4096)
+target_link_libraries(test_utility PRIVATE azrtos::threadx)
foreach(test_case ${regression_test_cases})
get_filename_component(test_name ${test_case} NAME_WE)
- add_executable(${test_name} ${test_case})
- target_link_libraries(${test_name} PRIVATE test_utility)
+
+ if(test_name STREQUAL "threadx_initialize_kernel_setup_test")
+ add_executable(${test_name} ${test_case} $<TARGET_OBJECTS:test_weak_defaults>)
+ else()
+ add_executable(${test_name} ${test_case}
+ $<TARGET_OBJECTS:test_utility>
+ $<TARGET_OBJECTS:test_weak_defaults>)
+ target_compile_definitions(${test_name} PRIVATE CTEST BATCH_TEST
+ TEST_STACK_SIZE_PRINTF=4096)
+ endif()
+
+ target_link_libraries(${test_name} PRIVATE azrtos::threadx)
add_test(${CMAKE_BUILD_TYPE}::${test_name} ${test_name})
endforeach()
diff --git a/test/tx/cmake/regression/generate_test_file.cmake b/test/tx/cmake/regression/generate_test_file.cmake
new file mode 100644
index 00000000..d37e744b
--- /dev/null
+++ b/test/tx/cmake/regression/generate_test_file.cmake
@@ -0,0 +1,42 @@
+if(NOT DEFINED SOURCE_FILE)
+ message(FATAL_ERROR "SOURCE_FILE is required")
+endif()
+
+if(NOT DEFINED OUTPUT_FILE)
+ message(FATAL_ERROR "OUTPUT_FILE is required")
+endif()
+
+file(STRINGS "${SOURCE_FILE}" FILE_LINES)
+
+set(UPDATED_FILE_CONTENTS "")
+set(DISPATCH_DECLARATION "VOID test_interrupt_dispatch(VOID);")
+set(DISPATCH_CALL "test_interrupt_dispatch();")
+set(DECLARATION_INSERTED FALSE)
+set(CALL_INSERTED FALSE)
+
+foreach(FILE_LINE IN LISTS FILE_LINES)
+ if((NOT DECLARATION_INSERTED) AND
+ ((FILE_LINE MATCHES "^void[ \t]+\\*_tx_linux_timer_interrupt\\(void \\*p\\);[ \t]*$")
+ OR
+ (FILE_LINE MATCHES "^VOID CALLBACK[ \t]+_tx_win32_timer_interrupt\\(UINT wTimerID, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2\\);[ \t]*$")))
+ string(APPEND UPDATED_FILE_CONTENTS "${FILE_LINE}\n${DISPATCH_DECLARATION}\n")
+ set(DECLARATION_INSERTED TRUE)
+ elseif((NOT CALL_INSERTED) AND (FILE_LINE MATCHES "^([ \t]*)_tx_timer_interrupt\\(\\);[ \t]*$"))
+ string(APPEND UPDATED_FILE_CONTENTS "${CMAKE_MATCH_1}${DISPATCH_CALL}\n${FILE_LINE}\n")
+ set(CALL_INSERTED TRUE)
+ else()
+ string(APPEND UPDATED_FILE_CONTENTS "${FILE_LINE}\n")
+ endif()
+endforeach()
+
+if(NOT CALL_INSERTED)
+ message(FATAL_ERROR "Unable to insert test interrupt dispatcher call into ${SOURCE_FILE}")
+endif()
+
+if(NOT DECLARATION_INSERTED)
+ message(FATAL_ERROR "Unable to insert test interrupt dispatcher declaration into ${SOURCE_FILE}")
+endif()
+
+get_filename_component(OUTPUT_DIRECTORY "${OUTPUT_FILE}" DIRECTORY)
+file(MAKE_DIRECTORY "${OUTPUT_DIRECTORY}")
+file(WRITE "${OUTPUT_FILE}" "${UPDATED_FILE_CONTENTS}")
diff --git a/test/tx/cmake/regression/generate_test_file.sh b/test/tx/cmake/regression/generate_test_file.sh
index ac0a70fa..67482c42 100755
--- a/test/tx/cmake/regression/generate_test_file.sh
+++ b/test/tx/cmake/regression/generate_test_file.sh
@@ -1,4 +1,15 @@
#!/bin/bash
+##############################################################################
+# 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
+##############################################################################
+
dst=$(dirname $0)/../../regression/tx_initialize_low_level.c
src=$(dirname $0)/../../../../ports/linux/gnu/src/tx_initialize_low_level.c
diff --git a/test/tx/cmake/riscv/CMakeLists.txt b/test/tx/cmake/riscv/CMakeLists.txt
new file mode 100644
index 00000000..a4f7e7e8
--- /dev/null
+++ b/test/tx/cmake/riscv/CMakeLists.txt
@@ -0,0 +1,87 @@
+cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
+cmake_policy(SET CMP0054 NEW)
+cmake_policy(SET CMP0057 NEW)
+
+project(threadx_riscv_test LANGUAGES C ASM)
+
+# Build configurations (same defines as Linux tests, minus coverage instrumentation)
+set(BUILD_CONFIGURATIONS default_build disable_notify_callbacks_build
+ stack_checking_build stack_checking_rand_fill_build trace_build)
+set(CMAKE_CONFIGURATION_TYPES
+ ${BUILD_CONFIGURATIONS}
+ CACHE STRING "list of supported configuration types" FORCE)
+set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
+ ${CMAKE_CONFIGURATION_TYPES})
+list(GET CMAKE_CONFIGURATION_TYPES 0 BUILD_TYPE)
+if((NOT CMAKE_BUILD_TYPE) OR (NOT ("${CMAKE_BUILD_TYPE}" IN_LIST
+ CMAKE_CONFIGURATION_TYPES)))
+ set(CMAKE_BUILD_TYPE
+ "${BUILD_TYPE}"
+ CACHE STRING "Build Type of the project" FORCE)
+endif()
+
+message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
+message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}.")
+message(STATUS "THREADX_ARCH: ${THREADX_ARCH}")
+
+# Per-configuration compile definitions
+set(default_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32)
+set(disable_notify_callbacks_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_DISABLE_NOTIFY_CALLBACKS)
+set(stack_checking_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_ENABLE_STACK_CHECKING)
+set(stack_checking_rand_fill_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_ENABLE_STACK_CHECKING -DTX_ENABLE_RANDOM_NUMBER_STACK_FILLING)
+set(trace_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_ENABLE_EVENT_TRACE)
+
+add_compile_options(
+ -std=c99
+ -O0
+ -g3
+ -fdiagnostics-color
+ -Werror
+ -ffunction-sections
+ -fdata-sections
+ -DTX_REGRESSION_TEST
+ -DTEST_STACK_SIZE_PRINTF=4096
+ -DEXTERNAL_EXIT
+ ${${CMAKE_BUILD_TYPE}}
+)
+
+enable_testing()
+
+# Add ThreadX library (uses the RISC-V toolchain set by CMAKE_TOOLCHAIN_FILE)
+add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../../../.. threadx)
+
+# Add BSP
+add_subdirectory(bsp)
+
+# Add regression tests
+add_subdirectory(regression)
+
+# Strict warning flags for the ThreadX library build
+target_compile_options(
+ threadx
+ PRIVATE -Werror
+ -Wall
+ -Wextra
+ -pedantic
+ -fmessage-length=0
+ -fsigned-char
+ -ffunction-sections
+ -fdata-sections
+ -Wunused
+ -Wuninitialized
+ -Wmissing-declarations
+ # -Wconversion is disabled for RV64 because ULONG is intentionally 32-bit
+ # (for ThreadX ABI compatibility across all ports) while sizeof(VOID*) and
+ # sizeof(ALIGN_TYPE) return size_t (64-bit on RV64). This design matches
+ # ARM Cortex-A72 and other 64-bit ports. The implicit conversions in
+ # common/src/ byte/block pool code trigger -Wconversion warnings. Since
+ # pool sizes are inherently limited to 32-bit (ULONG), the conversions
+ # are safe. No other 64-bit port with 32-bit ULONG has been tested with
+ # -Wconversion enabled, so we disable it here for RV64.
+ $<$<STREQUAL:${THREADX_ARCH},risc-v32>:-Wconversion>
+ -Wpointer-arith
+ -Wlogical-op
+ -Waggregate-return
+ -Wfloat-equal
+ $<$<COMPILE_LANGUAGE:C>:-include$<SEMICOLON>stdlib.h>
+)
diff --git a/test/tx/cmake/riscv/bsp/CMakeLists.txt b/test/tx/cmake/riscv/bsp/CMakeLists.txt
new file mode 100644
index 00000000..a6b8171a
--- /dev/null
+++ b/test/tx/cmake/riscv/bsp/CMakeLists.txt
@@ -0,0 +1,25 @@
+cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
+
+# BSP library for RISC-V QEMU virt regression tests.
+# Provides board init, UART, CLINT timer, PLIC, trap handler,
+# newlib syscall stubs, and low-level ThreadX initialization.
+
+project(riscv_bsp LANGUAGES C ASM)
+
+set(BSP_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_library(riscv_bsp
+ ${BSP_DIR}/entry.S
+ ${BSP_DIR}/tx_initialize_low_level.S
+ ${BSP_DIR}/board.c
+ ${BSP_DIR}/trap.c
+ ${BSP_DIR}/hwtimer.c
+ ${BSP_DIR}/plic.c
+ ${BSP_DIR}/uart.c
+ ${BSP_DIR}/syscalls.c
+ ${BSP_DIR}/printf.c
+)
+
+target_include_directories(riscv_bsp PUBLIC ${BSP_DIR})
+target_link_libraries(riscv_bsp PUBLIC azrtos::threadx)
+target_compile_definitions(riscv_bsp PUBLIC EXTERNAL_EXIT)
diff --git a/test/tx/cmake/riscv/bsp/board.c b/test/tx/cmake/riscv/bsp/board.c
new file mode 100644
index 00000000..0891200e
--- /dev/null
+++ b/test/tx/cmake/riscv/bsp/board.c
@@ -0,0 +1,30 @@
+/***************************************************************************
+ * Copyright (c) 2026 10xEngineers
+ *
+ * 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
+ **************************************************************************/
+
+#include "plic.h"
+#include "hwtimer.h"
+#include "uart.h"
+#include <stdint.h>
+#include <stddef.h>
+
+int board_init(void)
+{
+ int ret;
+ ret = plic_init();
+ if (ret)
+ return ret;
+ ret = uart_init();
+ if (ret)
+ return ret;
+ ret = hwtimer_init();
+ if (ret)
+ return ret;
+ return 0;
+}
diff --git a/test/tx/cmake/riscv/bsp/csr.h b/test/tx/cmake/riscv/bsp/csr.h
new file mode 100644
index 00000000..f3d15f82
--- /dev/null
+++ b/test/tx/cmake/riscv/bsp/csr.h
@@ -0,0 +1,84 @@
+/***************************************************************************
+ * Copyright (c) 2026 10xEngineers
+ *
+ * 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
+ **************************************************************************/
+
+#ifndef RISCV_CSR_H
+#define RISCV_CSR_H
+
+/* Machine Status Register, mstatus */
+#define MSTATUS_MPP_MASK (3L << 11)
+#define MSTATUS_MPP_M (3L << 11)
+#define MSTATUS_MPP_S (1L << 11)
+#define MSTATUS_MPP_U (0L << 11)
+#define MSTATUS_MIE (1L << 3)
+#define MSTATUS_MPIE (1L << 7)
+#define MSTATUS_FS (1L << 13)
+
+/* Machine-mode Interrupt Enable */
+#define MIE_MTIE (1L << 7)
+#define MIE_MSIE (1L << 3)
+#define MIE_MEIE (1L << 11)
+#define MIE_STIE (1L << 5)
+#define MIE_SSIE (1L << 1)
+#define MIE_SEIE (1L << 9)
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+static inline uintptr_t riscv_get_core(void)
+{
+ uintptr_t x;
+ __asm__ volatile("csrr %0, mhartid" : "=r" (x));
+ return x;
+}
+
+static inline uintptr_t riscv_get_mstatus(void)
+{
+ uintptr_t x;
+ __asm__ volatile("csrr %0, mstatus" : "=r" (x));
+ return x;
+}
+
+static inline void riscv_writ_mstatus(uintptr_t x)
+{
+ __asm__ volatile("csrw mstatus, %0" : : "r" (x));
+}
+
+static inline void riscv_mintr_on(void)
+{
+ uintptr_t mstatus = riscv_get_mstatus();
+ mstatus |= MSTATUS_MIE;
+ riscv_writ_mstatus(mstatus);
+}
+
+static inline void riscv_mintr_off(void)
+{
+ uintptr_t mstatus = riscv_get_mstatus();
+ mstatus &= (~MSTATUS_MIE);
+ riscv_writ_mstatus(mstatus);
+}
+
+static inline int riscv_mintr_get(void)
+{
+ uintptr_t x = riscv_get_mstatus();
+ return (x & MSTATUS_MIE) != 0;
+}
+
+static inline void riscv_mintr_restore(int x)
+{
+ if (x)
+ riscv_mintr_on();
+ else
+ riscv_mintr_off();
+}
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* RISCV_CSR_H */
diff --git a/test/tx/cmake/riscv/bsp/entry.S b/test/tx/cmake/riscv/bsp/entry.S
new file mode 100644
index 00000000..2f16c052
--- /dev/null
+++ b/test/tx/cmake/riscv/bsp/entry.S
@@ -0,0 +1,75 @@
+/***************************************************************************
+ * Copyright (c) 2026 10xEngineers
+ *
+ * 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
+ **************************************************************************/
+
+/* Boot code for RISC-V QEMU virt regression tests.
+ Works for both RV32 and RV64 (instructions are width-agnostic). */
+
+.section .text.init
+.align 4
+.global _start
+.extern main
+.extern _sysstack_end
+.extern _bss_start
+.extern _bss_end
+
+_start:
+ csrr t0, mhartid
+ bne t0, zero, _secondary_halt
+
+ /* Zero all general-purpose registers. */
+ li x1, 0
+ li x2, 0
+ li x3, 0
+ li x4, 0
+ li x5, 0
+ li x6, 0
+ li x7, 0
+ li x8, 0
+ li x9, 0
+ li x10, 0
+ li x11, 0
+ li x12, 0
+ li x13, 0
+ li x14, 0
+ li x15, 0
+ li x16, 0
+ li x17, 0
+ li x18, 0
+ li x19, 0
+ li x20, 0
+ li x21, 0
+ li x22, 0
+ li x23, 0
+ li x24, 0
+ li x25, 0
+ li x26, 0
+ li x27, 0
+ li x28, 0
+ li x29, 0
+ li x30, 0
+ li x31, 0
+
+ /* Set up stack pointer from linker symbol. */
+ la sp, _sysstack_end
+
+ /* Clear BSS. */
+ la t0, _bss_start
+ la t1, _bss_end
+_bss_clean:
+ bgeu t0, t1, _bss_done
+ sb zero, 0(t0)
+ addi t0, t0, 1
+ j _bss_clean
+_bss_done:
+ call main
+
+_secondary_halt:
+ wfi
+ j _secondary_halt
diff --git a/test/tx/cmake/riscv/bsp/hwtimer.c b/test/tx/cmake/riscv/bsp/hwtimer.c
new file mode 100644
index 00000000..99821f1e
--- /dev/null
+++ b/test/tx/cmake/riscv/bsp/hwtimer.c
@@ -0,0 +1,33 @@
+/***************************************************************************
+ * Copyright (c) 2026 10xEngineers
+ *
+ * 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
+ **************************************************************************/
+
+#include "csr.h"
+#include "hwtimer.h"
+#include <tx_port.h>
+
+#define CLINT (0x02000000L)
+#define CLINT_TIME (CLINT + 0xBFF8)
+#define CLINT_TIMECMP(id) (CLINT + 0x4000 + 8 * (id))
+
+int hwtimer_init(void)
+{
+ uintptr_t hart = riscv_get_core();
+ uint64_t time = *((volatile uint64_t *)CLINT_TIME);
+ *((volatile uint64_t *)CLINT_TIMECMP(hart)) = time + TICKNUM_PER_TIMER;
+ return 0;
+}
+
+int hwtimer_handler(void)
+{
+ uintptr_t hart = riscv_get_core();
+ uint64_t time = *((volatile uint64_t *)CLINT_TIME);
+ *((volatile uint64_t *)CLINT_TIMECMP(hart)) = time + TICKNUM_PER_TIMER;
+ return 0;
+}
diff --git a/test/tx/cmake/riscv/bsp/hwtimer.h b/test/tx/cmake/riscv/bsp/hwtimer.h
new file mode 100644
index 00000000..e6b9efa4
--- /dev/null
+++ b/test/tx/cmake/riscv/bsp/hwtimer.h
@@ -0,0 +1,22 @@
+/***************************************************************************
+ * Copyright (c) 2026 10xEngineers
+ *
+ * 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
+ **************************************************************************/
+
+#ifndef RISCV_HWTIMER_H
+#define RISCV_HWTIMER_H
+
+#include <stdint.h>
+
+#define TICKNUM_PER_SECOND 10000000
+#define TICKNUM_PER_TIMER (TICKNUM_PER_SECOND / 10)
+
+int hwtimer_init(void);
+int hwtimer_handler(void);
+
+#endif /* RISCV_HWTIMER_H */
diff --git a/test/tx/cmake/riscv/bsp/link.lds b/test/tx/cmake/riscv/bsp/link.lds
new file mode 100644
index 00000000..42f08fb6
--- /dev/null
+++ b/test/tx/cmake/riscv/bsp/link.lds
@@ -0,0 +1,60 @@
+/***************************************************************************
+ * Linker script for RISC-V QEMU virt regression tests.
+ * Provides 128 MB RAM starting at 0x80000000 (QEMU virt default).
+ * System stack is 16 KB to accommodate test framework overhead.
+ **************************************************************************/
+
+OUTPUT_ARCH( "riscv" )
+ENTRY( _start )
+
+MEMORY
+{
+ RAM (rwx) : ORIGIN = 0x80000000, LENGTH = 128M
+}
+
+SECTIONS
+{
+ . = 0x80000000;
+
+ .text : {
+ KEEP(*(.text.init))
+ *(.text .text.*)
+ . = ALIGN(0x1000);
+ PROVIDE(etext = .);
+ } > RAM
+
+ .rodata : {
+ . = ALIGN(16);
+ *(.srodata .srodata.*)
+ . = ALIGN(16);
+ *(.rodata .rodata.*)
+ } > RAM
+
+ .data : {
+ . = ALIGN(16);
+ *(.sdata .sdata.*)
+ . = ALIGN(16);
+ *(.data .data.*)
+ } > RAM
+
+ .bss : {
+ . = ALIGN(16);
+ _bss_start = .;
+ *(.sbss .sbss.*)
+ . = ALIGN(16);
+ *(.bss .bss.*)
+ *(COMMON)
+ _bss_end = .;
+ } > RAM
+
+ .stack : {
+ . = ALIGN(4096);
+ _sysstack_start = .;
+ . += 0x4000;
+ _sysstack_end = .;
+ } > RAM
+
+ PROVIDE(_end = .);
+
+ ASSERT(. <= ORIGIN(RAM) + LENGTH(RAM), "Image exceeds available RAM")
+}
diff --git a/test/tx/cmake/riscv/bsp/plic.c b/test/tx/cmake/riscv/bsp/plic.c
new file mode 100644
index 00000000..a2b44fec
--- /dev/null
+++ b/test/tx/cmake/riscv/bsp/plic.c
@@ -0,0 +1,87 @@
+/***************************************************************************
+ * Copyright (c) 2026 10xEngineers
+ *
+ * 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
+ **************************************************************************/
+
+#include "plic.h"
+#include <stddef.h>
+
+irq_callback callbacks[MAX_CALLBACK_NUM];
+
+void plic_irq_enable(int irqno)
+{
+ uintptr_t hart = riscv_get_core();
+ volatile uint32_t *reg = (volatile uint32_t *)(PLIC_MENABLE(hart) + (irqno / 32) * 4);
+ *reg = *reg | (1U << (irqno % 32));
+}
+
+void plic_irq_disable(int irqno)
+{
+ uintptr_t hart = riscv_get_core();
+ volatile uint32_t *reg = (volatile uint32_t *)(PLIC_MENABLE(hart) + (irqno / 32) * 4);
+ *reg = *reg & ~(1U << (irqno % 32));
+}
+
+void plic_prio_set(int irqno, int prio)
+{
+ PLIC_SET_PRIO(irqno, prio);
+}
+
+int plic_prio_get(int irqno)
+{
+ return (int)PLIC_GET_PRIO(irqno);
+}
+
+int plic_register_callback(int irqno, irq_callback callback)
+{
+ if (!(irqno >= 0 && irqno < MAX_CALLBACK_NUM))
+ return -1;
+ callbacks[irqno] = callback;
+ return 0;
+}
+
+int plic_unregister_callback(int irqno)
+{
+ return plic_register_callback(irqno, NULL);
+}
+
+int plic_init(void)
+{
+ for (int i = 0; i < MAX_CALLBACK_NUM; i++)
+ {
+ callbacks[i] = NULL;
+ }
+ return 0;
+}
+
+int plic_claim(void)
+{
+ uintptr_t hart = riscv_get_core();
+ return (int)(*(uint32_t *)PLIC_MCLAIM(hart));
+}
+
+void plic_complete(int irqno)
+{
+ uintptr_t hart = riscv_get_core();
+ *(uint32_t *)(PLIC_MCOMPLETE(hart)) = (uint32_t)irqno;
+}
+
+int plic_irq_intr(void)
+{
+ int ret = -1;
+ int irqno = plic_claim();
+ if (irqno <= 0 || irqno >= MAX_CALLBACK_NUM) {
+ plic_complete(irqno);
+ return 0; // spurious or out-of-range, not an error
+ }
+ if (callbacks[irqno] != NULL)
+ ret = (callbacks[irqno])(irqno);
+
+ plic_complete(irqno);
+ return ret;
+}
diff --git a/test/tx/cmake/riscv/bsp/plic.h b/test/tx/cmake/riscv/bsp/plic.h
new file mode 100644
index 00000000..e2734ea6
--- /dev/null
+++ b/test/tx/cmake/riscv/bsp/plic.h
@@ -0,0 +1,46 @@
+/***************************************************************************
+ * Copyright (c) 2026 10xEngineers
+ *
+ * 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
+ **************************************************************************/
+
+#ifndef RISCV_PLIC_H
+#define RISCV_PLIC_H
+
+#include "csr.h"
+#include <stdint.h>
+
+#define PLIC 0x0c000000L
+#define PLIC_PRIORITY (PLIC + 0x0)
+#define PLIC_PENDING (PLIC + 0x1000)
+#define PLIC_MENABLE(hart) (PLIC + 0x2000 + (hart) * 0x100)
+#define PLIC_SENABLE(hart) (PLIC + 0x2080 + (hart) * 0x100)
+#define PLIC_MPRIORITY(hart) (PLIC + 0x200000 + (hart) * 0x2000)
+#define PLIC_SPRIORITY(hart) (PLIC + 0x201000 + (hart) * 0x2000)
+#define PLIC_MCLAIM(hart) (PLIC + 0x200004 + (hart) * 0x2000)
+#define PLIC_SCLAIM(hart) (PLIC + 0x201004 + (hart) * 0x2000)
+#define PLIC_MCOMPLETE(hart) (PLIC + 0x200004 + (hart) * 0x2000)
+#define PLIC_SCOMPLETE(hart) (PLIC + 0x201004 + (hart) * 0x2000)
+
+#define PLIC_GET_PRIO(irqno) (*(uint32_t *)(PLIC_PRIORITY + (irqno) * 4))
+#define PLIC_SET_PRIO(irqno, prio) (*(uint32_t *)(PLIC_PRIORITY + (irqno) * 4) = (prio))
+
+#define MAX_CALLBACK_NUM 128
+typedef int (*irq_callback)(int irqno);
+
+void plic_irq_enable(int irqno);
+void plic_irq_disable(int irqno);
+int plic_prio_get(int irqno);
+void plic_prio_set(int irqno, int prio);
+int plic_register_callback(int irqno, irq_callback callback);
+int plic_unregister_callback(int irqno);
+int plic_init(void);
+int plic_claim(void);
+void plic_complete(int irqno);
+int plic_irq_intr(void);
+
+#endif /* RISCV_PLIC_H */
diff --git a/test/tx/cmake/riscv/bsp/printf.c b/test/tx/cmake/riscv/bsp/printf.c
new file mode 100644
index 00000000..4aa185cc
--- /dev/null
+++ b/test/tx/cmake/riscv/bsp/printf.c
@@ -0,0 +1,168 @@
+/***************************************************************************
+ * Copyright (c) 2026 10xEngineers
+ *
+ * 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
+ **************************************************************************/
+
+/* Minimal printf/puts for RISC-V QEMU virt regression tests.
+ Avoids linking newlib's stdio which is compiled with mcmodel=medlow
+ and causes relocation overflow on RV64 (DRAM at 0x80000000).
+ Only the format specifiers used by the test suite are supported:
+ %s, %d, %u, %lu, %ld, %%, and plain strings. */
+
+#include <stdarg.h>
+#include <stddef.h>
+
+extern int _write(int fd, const char *buf, int count);
+
+static void print_str(const char *s)
+{
+ const char *p = s;
+ while (*p)
+ p++;
+ _write(1, s, (int)(p - s));
+}
+
+static void print_unsigned(unsigned long val)
+{
+ char buf[21];
+ int i = 0;
+
+ if (val == 0)
+ {
+ _write(1, "0", 1);
+ return;
+ }
+
+ while (val > 0)
+ {
+ buf[i++] = (char)('0' + (int)(val % 10u));
+ val /= 10u;
+ }
+
+ /* Reverse. */
+ for (int j = i - 1; j >= 0; j--)
+ _write(1, &buf[j], 1);
+}
+
+static void print_hex(unsigned long val)
+{
+ static const char hex[] = "0123456789abcdef";
+ char buf[17];
+ int i = 0;
+
+ if (val == 0)
+ {
+ _write(1, "0", 1);
+ return;
+ }
+
+ while (val > 0)
+ {
+ buf[i++] = hex[val & 0xfu];
+ val >>= 4;
+ }
+
+ for (int j = i - 1; j >= 0; j--)
+ _write(1, &buf[j], 1);
+}
+
+static void print_signed(long val)
+{
+ if (val < 0)
+ {
+ _write(1, "-", 1);
+ print_unsigned((unsigned long)(-val));
+ }
+ else
+ {
+ print_unsigned((unsigned long)val);
+ }
+}
+
+int printf(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+
+ const char *p = fmt;
+ const char *seg = p;
+
+ while (*p)
+ {
+ if (*p == '%')
+ {
+ /* Flush preceding literal segment. */
+ if (p > seg)
+ _write(1, seg, (int)(p - seg));
+
+ p++;
+ /* Check for 'l' length modifier. */
+ int is_long = 0;
+ if (*p == 'l')
+ {
+ is_long = 1;
+ p++;
+ }
+
+ switch (*p)
+ {
+ case 's':
+ print_str(va_arg(ap, const char *));
+ break;
+ case 'd':
+ if (is_long)
+ print_signed(va_arg(ap, long));
+ else
+ print_signed((long)va_arg(ap, int));
+ break;
+ case 'u':
+ if (is_long)
+ print_unsigned(va_arg(ap, unsigned long));
+ else
+ print_unsigned((unsigned long)va_arg(ap, unsigned int));
+ break;
+ case 'x':
+ if (is_long)
+ print_hex(va_arg(ap, unsigned long));
+ else
+ print_hex((unsigned long)va_arg(ap, unsigned int));
+ break;
+ case '%':
+ _write(1, "%", 1);
+ break;
+ default:
+ /* Unknown specifier — print as-is. */
+ _write(1, "%", 1);
+ if (is_long)
+ _write(1, "l", 1);
+ _write(1, p, 1);
+ break;
+ }
+ p++;
+ seg = p;
+ }
+ else
+ {
+ p++;
+ }
+ }
+
+ /* Flush remaining literal segment. */
+ if (p > seg)
+ _write(1, seg, (int)(p - seg));
+
+ va_end(ap);
+ return 0;
+}
+
+int puts(const char *s)
+{
+ print_str(s);
+ _write(1, "\n", 1);
+ return 0;
+}
diff --git a/test/tx/cmake/riscv/bsp/syscalls.c b/test/tx/cmake/riscv/bsp/syscalls.c
new file mode 100644
index 00000000..802fe8af
--- /dev/null
+++ b/test/tx/cmake/riscv/bsp/syscalls.c
@@ -0,0 +1,128 @@
+/***************************************************************************
+ * Copyright (c) 2026 10xEngineers
+ *
+ * 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
+ **************************************************************************/
+
+/* Newlib system call stubs for RISC-V QEMU virt regression tests.
+ Provides _write (UART output for printf), _exit (QEMU test finisher),
+ and other minimal stubs needed by newlib. */
+
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdint.h>
+
+#define UART0_THR (*(volatile unsigned char *)0x10000000L)
+#define UART0_LSR (*(volatile unsigned char *)0x10000005L)
+#define LSR_TX_IDLE (1 << 5)
+
+/* QEMU virt sifive_test device for clean exit. */
+#define VIRT_TEST (*(volatile uint32_t *)0x100000L)
+#define VIRT_TEST_PASS 0x5555u
+#define VIRT_TEST_FAIL 0x3333u
+
+/* Called by testcontrol.c when EXTERNAL_EXIT is defined. */
+__attribute__((noreturn)) void external_exit(unsigned int code)
+{
+ if (code == 0)
+ VIRT_TEST = VIRT_TEST_PASS;
+ else
+ VIRT_TEST = (code << 16) | VIRT_TEST_FAIL;
+
+ /* Should not reach here, but halt if it does. */
+ while (1)
+ ;
+}
+
+int _write(int fd, const char *buf, int count)
+{
+ (void)fd;
+ for (int i = 0; i < count; i++)
+ {
+ while ((UART0_LSR & LSR_TX_IDLE) == 0)
+ ;
+ UART0_THR = (unsigned char)buf[i];
+ }
+ return count;
+}
+
+extern char _end[];
+static char *heap_ptr = 0;
+
+void *_sbrk(int incr)
+{
+ if (heap_ptr == 0)
+ heap_ptr = _end;
+
+ char *prev = heap_ptr;
+ heap_ptr += incr;
+ return prev;
+}
+
+int _close(int fd)
+{
+ (void)fd;
+ errno = EBADF;
+ return -1;
+}
+
+int _fstat(int fd, struct stat *st)
+{
+ (void)fd;
+ st->st_mode = S_IFCHR;
+ return 0;
+}
+
+int _isatty(int fd)
+{
+ (void)fd;
+ return 1;
+}
+
+int _lseek(int fd, int offset, int whence)
+{
+ (void)fd;
+ (void)offset;
+ (void)whence;
+ errno = ESPIPE;
+ return -1;
+}
+
+int _read(int fd, char *buf, int count)
+{
+ (void)fd;
+ (void)buf;
+ (void)count;
+ return 0;
+}
+
+__attribute__((noreturn)) void _exit(int code)
+{
+ external_exit((unsigned int)code);
+}
+
+/* Override newlib's exit() to avoid pulling in __call_exitprocs and
+ __stdio_exit_handler (compiled with mcmodel=medlow). */
+__attribute__((noreturn)) void exit(int code)
+{
+ external_exit((unsigned int)code);
+}
+
+/* Minimal rand/srand to avoid pulling newlib's version which uses
+ _impure_ptr (compiled with mcmodel=medlow, unreachable on RV64). */
+static unsigned long rand_seed = 1;
+
+int rand(void)
+{
+ rand_seed = rand_seed * 1103515245UL + 12345UL;
+ return (int)((rand_seed >> 16) & 0x7fff);
+}
+
+void srand(unsigned int seed)
+{
+ rand_seed = seed;
+}
diff --git a/test/tx/cmake/riscv/bsp/trap.c b/test/tx/cmake/riscv/bsp/trap.c
new file mode 100644
index 00000000..0ac7990a
--- /dev/null
+++ b/test/tx/cmake/riscv/bsp/trap.c
@@ -0,0 +1,84 @@
+/***************************************************************************
+ * Copyright (c) 2026 10xEngineers
+ *
+ * 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
+ **************************************************************************/
+
+/* Trap handler for RISC-V QEMU virt regression tests.
+ Calls test_interrupt_dispatch() BEFORE _tx_timer_interrupt() to match
+ the Linux port's behavior (generate_test_file.sh injection order). */
+
+#include "csr.h"
+#include <stdint.h>
+#include <stdio.h>
+#include "uart.h"
+#include "hwtimer.h"
+#include "plic.h"
+#include <tx_port.h>
+#include <tx_api.h>
+#include <tx_trace.h>
+
+/* Interrupt bit is the MSB of mcause */
+#define MCAUSE_INT_BIT ((uintptr_t)1 << (sizeof(uintptr_t) * 8 - 1))
+
+#define OS_IS_INTERUPT(mcause) ((mcause) & MCAUSE_INT_BIT)
+#define OS_IS_TICK_INT(mcause) ((mcause) == (MCAUSE_INT_BIT | 7u))
+#define OS_IS_SOFT_INT(mcause) ((mcause) == (MCAUSE_INT_BIT | 3u))
+#define OS_IS_EXT_INT(mcause) ((mcause) == (MCAUSE_INT_BIT | 11u))
+
+extern void _tx_timer_interrupt(void);
+extern void test_interrupt_dispatch(void) __attribute__((weak));
+extern void _exit(int code) __attribute__((noreturn));
+
+void trap_handler(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval)
+{
+ (void)mepc;
+ (void)mtval;
+
+ if (OS_IS_INTERUPT(mcause))
+ {
+ if (OS_IS_TICK_INT(mcause))
+ {
+ hwtimer_handler();
+
+ /* Trace ISR enter event (matches Linux port behavior). */
+ _tx_trace_isr_enter_insert(0);
+
+ /* Call test ISR dispatch BEFORE timer interrupt (matches Linux). */
+ if (test_interrupt_dispatch)
+ test_interrupt_dispatch();
+
+ _tx_timer_interrupt();
+
+ /* Trace ISR exit event. */
+ _tx_trace_isr_exit_insert(0);
+ }
+ else if (OS_IS_EXT_INT(mcause))
+ {
+ int ret = plic_irq_intr();
+ if (ret)
+ {
+ uart_puts("[INTERRUPT]: handler irq error!");
+ while (1)
+ ;
+ }
+ }
+ else
+ {
+ uart_puts("[INTERRUPT]: unhandled interrupt!");
+ while (1)
+ ;
+ }
+ }
+ else
+ {
+ uart_puts("[EXCEPTION]: unhandled exception!");
+ printf(" mcause=0x%lx mepc=0x%lx mtval=0x%lx\n",
+ (unsigned long)mcause, (unsigned long)mepc, (unsigned long)mtval);
+ _exit(1);
+ }
+}
diff --git a/test/tx/cmake/riscv/bsp/tx_initialize_low_level.S b/test/tx/cmake/riscv/bsp/tx_initialize_low_level.S
new file mode 100644
index 00000000..8d474d66
--- /dev/null
+++ b/test/tx/cmake/riscv/bsp/tx_initialize_low_level.S
@@ -0,0 +1,100 @@
+/***************************************************************************
+ * Copyright (c) 2026 10xEngineers
+ *
+ * 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
+ **************************************************************************/
+
+/* Trap entry and low-level init for RISC-V QEMU virt regression tests.
+ Supports both RV32 and RV64 via __riscv_xlen conditionals. */
+
+#include "csr.h"
+
+#if __riscv_xlen == 64
+#define STORE sd
+#define LOAD ld
+#define REGBYTES 8
+#else
+#define STORE sw
+#define LOAD lw
+#define REGBYTES 4
+#endif
+
+ .section .text
+ .align 4
+
+/**************************************************************************/
+/* trap_entry — saves context, calls C trap_handler, restores context. */
+/**************************************************************************/
+ .global trap_entry
+ .extern trap_handler
+ .extern _tx_thread_context_restore
+
+trap_entry:
+#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
+ addi sp, sp, -(65 * REGBYTES)
+#else
+ addi sp, sp, -(32 * REGBYTES)
+#endif
+
+ STORE x1, (28 * REGBYTES)(sp)
+
+ call _tx_thread_context_save
+
+ csrr a0, mcause
+ csrr a1, mepc
+ csrr a2, mtval
+ addi sp, sp, -REGBYTES
+ STORE ra, 0(sp)
+ call trap_handler
+ LOAD ra, 0(sp)
+ addi sp, sp, REGBYTES
+
+ call _tx_thread_context_restore
+
+_trap_err:
+ wfi
+ j _trap_err
+
+/**************************************************************************/
+/* _tx_initialize_low_level — hardware init for QEMU virt. */
+/**************************************************************************/
+ .section .text
+ .global _tx_initialize_low_level
+ .extern _end
+ .extern board_init
+
+_tx_initialize_low_level:
+
+ la t0, _tx_thread_system_stack_ptr
+ STORE sp, 0(t0)
+
+ la t0, _end
+ la t1, _tx_initialize_unused_memory
+ STORE t0, 0(t1)
+
+ li t0, MSTATUS_MIE
+ csrrc zero, mstatus, t0
+ li t0, (MSTATUS_MPP_M | MSTATUS_MPIE)
+ csrrs zero, mstatus, t0
+ li t0, (MIE_MTIE | MIE_MSIE | MIE_MEIE)
+ csrrs zero, mie, t0
+
+#ifdef __riscv_flen
+ li t0, MSTATUS_FS
+ csrrs zero, mstatus, t0
+ fscsr x0
+#endif
+
+ addi sp, sp, -REGBYTES
+ STORE ra, 0(sp)
+ call board_init
+ LOAD ra, 0(sp)
+ addi sp, sp, REGBYTES
+
+ la t0, trap_entry
+ csrw mtvec, t0
+ ret
diff --git a/test/tx/cmake/riscv/bsp/uart.c b/test/tx/cmake/riscv/bsp/uart.c
new file mode 100644
index 00000000..c1a6b64b
--- /dev/null
+++ b/test/tx/cmake/riscv/bsp/uart.c
@@ -0,0 +1,79 @@
+/***************************************************************************
+ * Copyright (c) 2026 10xEngineers
+ *
+ * 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
+ **************************************************************************/
+
+#include "uart.h"
+#include "csr.h"
+#include "plic.h"
+#include <stdint.h>
+
+#define Reg(reg) ((volatile unsigned char *)(UART0 + (reg)))
+
+#define RHR 0
+#define THR 0
+#define IER 1
+#define IER_RX_ENABLE (1<<0)
+#define IER_TX_ENABLE (1<<1)
+#define FCR 2
+#define FCR_FIFO_ENABLE (1<<0)
+#define FCR_FIFO_CLEAR (3<<1)
+#define LCR 3
+#define LCR_EIGHT_BITS (3<<0)
+#define LCR_BAUD_LATCH (1<<7)
+#define LSR 5
+#define LSR_RX_READY (1<<0)
+#define LSR_TX_IDLE (1<<5)
+
+#define ReadReg(reg) (*(Reg(reg)))
+#define WriteReg(reg, v) (*(Reg(reg)) = (v))
+
+int uart_init(void)
+{
+ WriteReg(IER, 0x00);
+ WriteReg(LCR, LCR_BAUD_LATCH);
+ WriteReg(0, 0x03);
+ WriteReg(1, 0x00);
+ WriteReg(LCR, LCR_EIGHT_BITS);
+ WriteReg(FCR, FCR_FIFO_ENABLE | FCR_FIFO_CLEAR);
+
+ plic_irq_enable(UART0_IRQ);
+ plic_prio_set(UART0_IRQ, 1);
+
+ return 0;
+}
+
+void uart_putc_nolock(int ch)
+{
+ while ((ReadReg(LSR) & LSR_TX_IDLE) == 0)
+ ;
+ WriteReg(THR, ch);
+}
+
+int uart_putc(int ch)
+{
+ int intr_enable = riscv_mintr_get();
+ riscv_mintr_off();
+ uart_putc_nolock(ch);
+ riscv_mintr_restore(intr_enable);
+ return 1;
+}
+
+int uart_puts(const char *str)
+{
+ int i;
+ int intr_enable = riscv_mintr_get();
+ riscv_mintr_off();
+ for (i = 0; str[i] != 0; i++)
+ {
+ uart_putc_nolock(str[i]);
+ }
+ uart_putc_nolock('\n');
+ riscv_mintr_restore(intr_enable);
+ return i;
+}
diff --git a/test/tx/cmake/riscv/bsp/uart.h b/test/tx/cmake/riscv/bsp/uart.h
new file mode 100644
index 00000000..765ec38f
--- /dev/null
+++ b/test/tx/cmake/riscv/bsp/uart.h
@@ -0,0 +1,22 @@
+/***************************************************************************
+ * Copyright (c) 2026 10xEngineers
+ *
+ * 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
+ **************************************************************************/
+
+#ifndef RISCV_UART_H
+#define RISCV_UART_H
+
+#define UART0 0x10000000L
+#define UART0_IRQ 10
+
+int uart_init(void);
+int uart_putc(int ch);
+void uart_putc_nolock(int ch);
+int uart_puts(const char *str);
+
+#endif /* RISCV_UART_H */
diff --git a/test/tx/cmake/riscv/regression/CMakeLists.txt b/test/tx/cmake/riscv/regression/CMakeLists.txt
new file mode 100644
index 00000000..80b6e3bd
--- /dev/null
+++ b/test/tx/cmake/riscv/regression/CMakeLists.txt
@@ -0,0 +1,177 @@
+cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
+cmake_policy(SET CMP0057 NEW)
+
+project(riscv_regression_test LANGUAGES C ASM)
+
+set(SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../regression)
+set(BSP_DIR ${CMAKE_CURRENT_LIST_DIR}/../bsp)
+
+# Determine QEMU arch from THREADX_ARCH
+if(THREADX_ARCH STREQUAL "risc-v64")
+ set(QEMU_SYSTEM "qemu-system-riscv64")
+ set(XLEN_TAG "rv64")
+else()
+ set(QEMU_SYSTEM "qemu-system-riscv32")
+ set(XLEN_TAG "rv32")
+endif()
+
+set(regression_test_cases
+ ${SOURCE_DIR}/threadx_block_memory_basic_test.c
+ ${SOURCE_DIR}/threadx_block_memory_error_detection_test.c
+ ${SOURCE_DIR}/threadx_block_memory_information_test.c
+ ${SOURCE_DIR}/threadx_block_memory_prioritize_test.c
+ ${SOURCE_DIR}/threadx_block_memory_suspension_test.c
+ ${SOURCE_DIR}/threadx_block_memory_suspension_timeout_test.c
+ ${SOURCE_DIR}/threadx_block_memory_thread_terminate_test.c
+ ${SOURCE_DIR}/threadx_byte_memory_basic_test.c
+ ${SOURCE_DIR}/threadx_byte_memory_information_test.c
+ ${SOURCE_DIR}/threadx_byte_memory_prioritize_test.c
+ ${SOURCE_DIR}/threadx_byte_memory_suspension_test.c
+ ${SOURCE_DIR}/threadx_byte_memory_suspension_timeout_test.c
+ ${SOURCE_DIR}/threadx_byte_memory_thread_contention_test.c
+ ${SOURCE_DIR}/threadx_byte_memory_thread_terminate_test.c
+ ${SOURCE_DIR}/threadx_event_flag_basic_test.c
+ ${SOURCE_DIR}/threadx_event_flag_information_test.c
+ ${SOURCE_DIR}/threadx_event_flag_isr_set_clear_test.c
+ ${SOURCE_DIR}/threadx_event_flag_isr_wait_abort_test.c
+ ${SOURCE_DIR}/threadx_event_flag_single_thread_terminate_test.c
+ ${SOURCE_DIR}/threadx_event_flag_suspension_consume_test.c
+ ${SOURCE_DIR}/threadx_event_flag_suspension_different_bits_consume_test.c
+ ${SOURCE_DIR}/threadx_event_flag_suspension_different_bits_test.c
+ ${SOURCE_DIR}/threadx_event_flag_suspension_test.c
+ ${SOURCE_DIR}/threadx_event_flag_suspension_timeout_test.c
+ ${SOURCE_DIR}/threadx_event_flag_thread_terminate_test.c
+ ${SOURCE_DIR}/threadx_interrupt_control_test.c
+ ${SOURCE_DIR}/threadx_mutex_basic_test.c
+ ${SOURCE_DIR}/threadx_mutex_delete_test.c
+ ${SOURCE_DIR}/threadx_mutex_information_test.c
+ ${SOURCE_DIR}/threadx_mutex_nested_priority_inheritance_test.c
+ ${SOURCE_DIR}/threadx_mutex_no_preemption_test.c
+ ${SOURCE_DIR}/threadx_mutex_preemption_test.c
+ ${SOURCE_DIR}/threadx_mutex_priority_inheritance_test.c
+ ${SOURCE_DIR}/threadx_mutex_proritize_test.c
+ ${SOURCE_DIR}/threadx_mutex_suspension_timeout_test.c
+ ${SOURCE_DIR}/threadx_mutex_thread_terminate_test.c
+ ${SOURCE_DIR}/threadx_queue_basic_eight_word_test.c
+ ${SOURCE_DIR}/threadx_queue_basic_four_word_test.c
+ ${SOURCE_DIR}/threadx_queue_basic_one_word_test.c
+ ${SOURCE_DIR}/threadx_queue_basic_sixteen_word_test.c
+ ${SOURCE_DIR}/threadx_queue_basic_two_word_test.c
+ ${SOURCE_DIR}/threadx_queue_basic_max_message_size_test.c
+ ${SOURCE_DIR}/threadx_queue_empty_suspension_test.c
+ ${SOURCE_DIR}/threadx_queue_flush_no_suspension_test.c
+ ${SOURCE_DIR}/threadx_queue_flush_test.c
+ ${SOURCE_DIR}/threadx_queue_front_send_test.c
+ ${SOURCE_DIR}/threadx_queue_full_suspension_test.c
+ ${SOURCE_DIR}/threadx_queue_information_test.c
+ ${SOURCE_DIR}/threadx_queue_prioritize.c
+ ${SOURCE_DIR}/threadx_queue_suspension_timeout_test.c
+ ${SOURCE_DIR}/threadx_queue_thread_terminate_test.c
+ ${SOURCE_DIR}/threadx_semaphore_basic_test.c
+ ${SOURCE_DIR}/threadx_semaphore_ceiling_put_test.c
+ ${SOURCE_DIR}/threadx_semaphore_delete_test.c
+ ${SOURCE_DIR}/threadx_semaphore_information_test.c
+ ${SOURCE_DIR}/threadx_semaphore_non_preemption_test.c
+ ${SOURCE_DIR}/threadx_semaphore_preemption_test.c
+ ${SOURCE_DIR}/threadx_semaphore_prioritize.c
+ ${SOURCE_DIR}/threadx_semaphore_thread_terminate_test.c
+ ${SOURCE_DIR}/threadx_semaphore_timeout_test.c
+ ${SOURCE_DIR}/threadx_thread_basic_execution_test.c
+ ${SOURCE_DIR}/threadx_thread_basic_time_slice_test.c
+ ${SOURCE_DIR}/threadx_thread_completed_test.c
+ ${SOURCE_DIR}/threadx_thread_create_preemption_threshold_test.c
+ ${SOURCE_DIR}/threadx_thread_delayed_suspension_test.c
+ ${SOURCE_DIR}/threadx_thread_information_test.c
+ ${SOURCE_DIR}/threadx_thread_multi_level_preemption_threshold_test.c
+ ${SOURCE_DIR}/threadx_thread_multiple_non_current_test.c
+ ${SOURCE_DIR}/threadx_thread_multiple_sleep_test.c
+ ${SOURCE_DIR}/threadx_thread_multiple_suspension_test.c
+ ${SOURCE_DIR}/threadx_thread_multiple_time_slice_test.c
+ ${SOURCE_DIR}/threadx_thread_preemptable_suspension_test.c
+ ${SOURCE_DIR}/threadx_thread_preemption_change_test.c
+ ${SOURCE_DIR}/threadx_thread_priority_change.c
+ ${SOURCE_DIR}/threadx_thread_relinquish_test.c
+ ${SOURCE_DIR}/threadx_thread_reset_test.c
+ ${SOURCE_DIR}/threadx_thread_simple_sleep_non_clear_test.c
+ ${SOURCE_DIR}/threadx_thread_simple_sleep_test.c
+ ${SOURCE_DIR}/threadx_thread_simple_suspend_test.c
+ ${SOURCE_DIR}/threadx_thread_sleep_for_100ticks_test.c
+ ${SOURCE_DIR}/threadx_thread_sleep_terminate_test.c
+ ${SOURCE_DIR}/threadx_thread_stack_checking_test.c
+ ${SOURCE_DIR}/threadx_thread_terminate_delete_test.c
+ ${SOURCE_DIR}/threadx_thread_time_slice_change_test.c
+ ${SOURCE_DIR}/threadx_thread_wait_abort_and_isr_test.c
+ ${SOURCE_DIR}/threadx_thread_wait_abort_test.c
+ ${SOURCE_DIR}/threadx_time_get_set_test.c
+ ${SOURCE_DIR}/threadx_timer_activate_deactivate_test.c
+ ${SOURCE_DIR}/threadx_timer_deactivate_accuracy_test.c
+ ${SOURCE_DIR}/threadx_timer_information_test.c
+ ${SOURCE_DIR}/threadx_timer_large_timer_accuracy_test.c
+ ${SOURCE_DIR}/threadx_timer_multiple_accuracy_test.c
+ ${SOURCE_DIR}/threadx_timer_multiple_test.c
+ ${SOURCE_DIR}/threadx_timer_simple_test.c
+ # threadx_trace_basic_test.c excluded: references tx_saved_posture
+ # (the Linux port's interrupt save variable) which is named
+ # interrupt_save on RISC-V.
+)
+
+# Tests that provide their own main() and must NOT link with testcontrol.
+set(standalone_test_cases
+ ${SOURCE_DIR}/threadx_initialize_kernel_setup_test.c
+)
+
+set(WEAK_DEFAULTS_SOURCE ${CMAKE_CURRENT_LIST_DIR}/../../../../shared/regression/testcontrol_weak_defaults.c)
+
+# Weak defaults must be an OBJECT library so all objects are always linked
+# into each test executable, even though they only provide weak symbols.
+# A STATIC library would have the linker skip them (weak defs don't satisfy
+# undefined strong references during archive scanning).
+add_library(riscv_test_weak_defaults OBJECT ${WEAK_DEFAULTS_SOURCE})
+target_compile_definitions(riscv_test_weak_defaults PRIVATE
+ CTEST BATCH_TEST EXTERNAL_EXIT TEST_STACK_SIZE_PRINTF=4096)
+target_compile_options(riscv_test_weak_defaults PRIVATE -include stdlib.h)
+target_link_libraries(riscv_test_weak_defaults PRIVATE azrtos::threadx)
+
+# Build testcontrol.c as a static library (no patched tx_initialize_low_level
+# needed — the BSP provides it directly with test_interrupt_dispatch hook).
+add_library(riscv_test_utility ${SOURCE_DIR}/testcontrol.c)
+target_link_libraries(riscv_test_utility PUBLIC riscv_bsp azrtos::threadx)
+target_compile_definitions(riscv_test_utility PUBLIC
+ CTEST BATCH_TEST EXTERNAL_EXIT TEST_STACK_SIZE_PRINTF=4096)
+# Bare-metal newlib needs explicit stdlib.h for rand() used in some tests.
+target_compile_options(riscv_test_utility PUBLIC -include stdlib.h)
+
+# Helper function to register a test executable with QEMU + CTest.
+function(register_riscv_test test_name)
+ target_link_options(${test_name} PRIVATE
+ -T ${BSP_DIR}/link.lds -nostartfiles
+ -Wl,--gc-sections)
+ add_test(
+ NAME ${CMAKE_BUILD_TYPE}::${XLEN_TAG}::${test_name}
+ COMMAND ${QEMU_SYSTEM} -nographic -smp 1 -bios none -m 128M
+ -machine virt -kernel $<TARGET_FILE:${test_name}>
+ )
+ set_tests_properties(${CMAKE_BUILD_TYPE}::${XLEN_TAG}::${test_name}
+ PROPERTIES TIMEOUT 120)
+endfunction()
+
+# Regular tests (linked with testcontrol).
+foreach(test_case ${regression_test_cases})
+ get_filename_component(test_name ${test_case} NAME_WE)
+ add_executable(${test_name} ${test_case} $<TARGET_OBJECTS:riscv_test_weak_defaults>)
+ target_link_libraries(${test_name} PRIVATE
+ -Wl,--whole-archive riscv_bsp -Wl,--no-whole-archive
+ riscv_test_utility)
+ register_riscv_test(${test_name})
+endforeach()
+
+# Standalone tests (provide their own main, no testcontrol).
+foreach(test_case ${standalone_test_cases})
+ get_filename_component(test_name ${test_case} NAME_WE)
+ add_executable(${test_name} ${test_case} $<TARGET_OBJECTS:riscv_test_weak_defaults>)
+ target_link_libraries(${test_name} PRIVATE
+ -Wl,--whole-archive riscv_bsp -Wl,--no-whole-archive
+ azrtos::threadx)
+ target_compile_options(${test_name} PRIVATE -include stdlib.h)
+ register_riscv_test(${test_name})
+endforeach()
diff --git a/test/tx/cmake/riscv/run.sh b/test/tx/cmake/riscv/run.sh
new file mode 100755
index 00000000..3b0905e7
--- /dev/null
+++ b/test/tx/cmake/riscv/run.sh
@@ -0,0 +1,162 @@
+#!/bin/bash
+##############################################################################
+# 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
+##############################################################################
+
+
+set -e
+
+# RISC-V regression test build/test runner.
+# Usage: run.sh <arch> <build|test> [all|<config> ...]
+# arch: riscv32 or riscv64
+
+function help() {
+ echo "Usage: $0 <arch> <command> [all|<build_configuration> ...]"
+ echo ""
+ echo " arch: riscv32 | riscv64"
+ echo " command: build | test"
+ echo ""
+ echo "Available build configurations:"
+ for build in ${build_configurations[*]}; do
+ echo " $build"
+ done
+ exit 1
+}
+
+function validate() {
+ for build in ${build_configurations[*]}; do
+ if [ "$1" == "$build" ]; then
+ return
+ fi
+ done
+ help
+}
+
+function generate() {
+ local arch=$1
+ local build=$2
+ local toolchain_file
+ local build_dir
+
+ if [ "$arch" == "riscv32" ]; then
+ toolchain_file="${REPO_ROOT}/cmake/riscv32_gnu.cmake"
+ else
+ toolchain_file="${REPO_ROOT}/cmake/riscv64_gnu.cmake"
+ fi
+
+ build_dir="build/${arch}_${build}"
+ cmake -B"$build_dir" -GNinja \
+ -DCMAKE_TOOLCHAIN_FILE="$toolchain_file" \
+ -DCMAKE_BUILD_TYPE="$build" \
+ .
+}
+
+function build() {
+ local arch=$1
+ local build=$2
+ cmake --build "build/${arch}_${build}"
+}
+
+function run_test() {
+ local arch=$1
+ local build=$2
+ local parallel_jobs=$3
+
+ pushd "build/${arch}_${build}"
+ [ -z "${CTEST_PARALLEL_LEVEL}" ] && parallel="-j${parallel_jobs}"
+ if [ -z "${CTEST_REPEAT_FAIL}" ]; then
+ repeat_fail=2
+ else
+ repeat_fail=${CTEST_REPEAT_FAIL}
+ fi
+ ctest $parallel --timeout 1000 \
+ -O "${arch}_${build}.txt" \
+ -T test --no-compress-output \
+ --test-output-size-passed 4194304 \
+ --test-output-size-failed 4194304 \
+ --output-on-failure \
+ --repeat until-pass:${repeat_fail} \
+ --output-junit "${arch}_${build}.xml"
+ popd
+}
+
+# Determine repo root and script directory
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+REPO_ROOT="$(cd "${SCRIPT_DIR}/../../../.." && pwd)"
+cd "$SCRIPT_DIR"
+
+# Parse build configurations from CMakeLists.txt
+result=$(sed -n "/(BUILD_CONFIGURATIONS/,/)/p" CMakeLists.txt | sed ':label;N;s/\n/ /;b label' | grep -Pzo "[a-zA-Z0-9_]*build[a-zA-Z0-9_]*\s*" | tr -d '\0')
+IFS=' '
+read -ra build_configurations <<< "$result"
+
+if [ $# -lt 2 ]; then
+ help
+fi
+
+arch=$1
+shift
+
+if [ "$arch" != "riscv32" ] && [ "$arch" != "riscv64" ]; then
+ echo "Error: arch must be 'riscv32' or 'riscv64'"
+ help
+fi
+
+command=$1
+shift
+
+if [ "$#" == "0" ]; then
+ builds=${build_configurations[0]}
+elif [ "$*" == "all" ]; then
+ builds=${build_configurations[@]}
+else
+ for item in $*; do
+ validate "$item"
+ done
+ builds=$*
+fi
+
+if [ "$command" == "build" ]; then
+ for item in $builds; do
+ generate "$arch" "$item"
+ echo ""
+ done
+
+ for item in $builds; do
+ echo "Building ${arch} ${item}"
+ build "$arch" "$item"
+ echo ""
+ done
+elif [ "$command" == "test" ]; then
+ cores=$(nproc)
+ if [ -z "${CTEST_PARALLEL_LEVEL}" ]; then
+ build_counts=$(echo $builds | wc -w)
+ parallel_jobs=$(($cores / $build_counts))
+ parallel_jobs=$(($parallel_jobs + 2))
+ pids=""
+ for item in $builds; do
+ echo "Testing ${arch} ${item}"
+ run_test "$arch" "$item" "$parallel_jobs" &
+ pids+=" $!"
+ done
+ exit_code=0
+ for p in $pids; do
+ wait $p || exit_code=$?
+ done
+ exit $exit_code
+ else
+ for item in $builds; do
+ echo "Testing ${arch} ${item}"
+ run_test "$arch" "$item" "$parallel_jobs"
+ done
+ fi
+else
+ help
+fi
diff --git a/test/tx/cmake/samples/fake.c b/test/tx/cmake/samples/fake.c
index 199f257e..138117b5 100644
--- a/test/tx/cmake/samples/fake.c
+++ b/test/tx/cmake/samples/fake.c
@@ -1,3 +1,14 @@
+/***************************************************************************/
+/* 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 */
+/***************************************************************************/
+
#include "tx_api.h"
typedef unsigned int TEST_FLAG;