Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion .github/workflows/regression_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,23 @@ jobs:
cmake_path: ./test/smp/cmake
result_affix: SMP
skip_deploy: true
riscv:
permissions:
contents: read
issues: read
checks: write
pull-requests: write
pages: write
id-token: write
uses: ./.github/workflows/regression_template.yml
with:
install_script: ./scripts/install_riscv.sh
build_script: ./scripts/build_tx_riscv.sh
test_script: ./scripts/test_tx_riscv.sh
cmake_path: ./test/tx/cmake/riscv
result_affix: RISC-V
skip_deploy: true
skip_coverage: true
deploy:
permissions:
contents: read
Expand All @@ -49,7 +66,7 @@ jobs:
pull-requests: write
pages: write
id-token: write
needs: [tx, smp]
needs: [tx, smp, riscv]
uses: ./.github/workflows/regression_template.yml
with:
skip_test: true
Expand Down
4 changes: 2 additions & 2 deletions common/src/tx_trace_object_register.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ TX_TRACE_OBJECT_ENTRY *entry_ptr;
/* Trace buffer is enabled, proceed. */

/* Pickup the total entries. */
entries = _tx_trace_total_registry_entries;
entries = (UINT) _tx_trace_total_registry_entries;

/* Determine if there are available entries in the registry. */
if (_tx_trace_available_registry_entries != ((ULONG) 0))
Expand All @@ -98,7 +98,7 @@ TX_TRACE_OBJECT_ENTRY *entry_ptr;
loop_break = TX_FALSE;

/* Loop to find available entry. */
i = _tx_trace_registry_search_start;
i = (UINT) _tx_trace_registry_search_start;
do
{

Expand Down
2 changes: 1 addition & 1 deletion common/src/tx_trace_object_unregister.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ TX_TRACE_OBJECT_ENTRY *entry_ptr;
/* Registry is setup, proceed. */

/* Pickup the total entries. */
entries = _tx_trace_total_registry_entries;
entries = (UINT) _tx_trace_total_registry_entries;

/* Loop to find available entry. */
for (i = ((ULONG) 0); i < entries; i++)
Expand Down
21 changes: 20 additions & 1 deletion ports/risc-v32/gnu/example_build/qemu_virt/build_libthreadx.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
#!/bin/bash
printf "y\n" | rm -rf ../../../../../build/
rm -f kernel.elf

pushd ../../../../../
cmake -Bbuild -GNinja -DCMAKE_TOOLCHAIN_FILE=cmake/riscv32_gnu.cmake .
cmake --build ./build/
popd
popd

riscv32-unknown-elf-gcc \
-march=rv32gc -mabi=ilp32d \
-mcmodel=medany -O0 -g3 -Wall \
-ffunction-sections -fdata-sections \
-I../../../../../common/inc \
-I../../inc \
entry.s \
tx_initialize_low_level.S \
board.c uart.c hwtimer.c plic.c trap.c demo_threadx.c \
-L../../../../../build -lthreadx \
-T link.lds -nostartfiles \
-o kernel.elf


qemu-system-riscv32 -nographic -smp 1 -bios none -m 128M -machine virt -kernel kernel.elf
98 changes: 98 additions & 0 deletions ports/risc-v32/gnu/inc/tx_port.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,104 @@ UINT _tx_thread_interrupt_control(UIN
#define TX_SEMAPHORE_DISABLE TX_DISABLE


/* Define automated coverage test extensions for the ThreadX regression test. */

#ifndef __ASSEMBLER__

typedef unsigned int TEST_FLAG;
extern TEST_FLAG threadx_byte_allocate_loop_test;
extern TEST_FLAG threadx_byte_release_loop_test;
extern TEST_FLAG threadx_mutex_suspension_put_test;
extern TEST_FLAG threadx_mutex_suspension_priority_test;
#ifndef TX_TIMER_PROCESS_IN_ISR
extern TEST_FLAG threadx_delete_timer_thread;
#endif

extern void abort_and_resume_byte_allocating_thread(void);
extern void abort_all_threads_suspended_on_mutex(void);
extern void suspend_lowest_priority(void);
#ifndef TX_TIMER_PROCESS_IN_ISR
extern void delete_timer_thread(void);
#endif
extern TEST_FLAG test_stack_analyze_flag;
extern TEST_FLAG test_initialize_flag;
extern TEST_FLAG test_forced_mutex_timeout;


#ifdef TX_REGRESSION_TEST

#define TX_BYTE_ALLOCATE_EXTENSION if (threadx_byte_allocate_loop_test == ((TEST_FLAG) 1)) \
{ \
pool_ptr -> tx_byte_pool_owner = TX_NULL; \
threadx_byte_allocate_loop_test = ((TEST_FLAG) 0); \
}

#define TX_BYTE_RELEASE_EXTENSION if (threadx_byte_release_loop_test == ((TEST_FLAG) 1)) \
{ \
threadx_byte_release_loop_test = ((TEST_FLAG) 0); \
abort_and_resume_byte_allocating_thread(); \
}

#define TX_MUTEX_PUT_EXTENSION_1 if (threadx_mutex_suspension_put_test == ((TEST_FLAG) 1)) \
{ \
threadx_mutex_suspension_put_test = ((TEST_FLAG) 0); \
abort_all_threads_suspended_on_mutex(); \
}

#define TX_MUTEX_PUT_EXTENSION_2 if (test_forced_mutex_timeout == ((TEST_FLAG) 1)) \
{ \
test_forced_mutex_timeout = ((TEST_FLAG) 0); \
_tx_thread_wait_abort(mutex_ptr -> tx_mutex_suspension_list); \
}

#define TX_MUTEX_PRIORITY_CHANGE_EXTENSION if (threadx_mutex_suspension_priority_test == ((TEST_FLAG) 1)) \
{ \
threadx_mutex_suspension_priority_test = ((TEST_FLAG) 0); \
suspend_lowest_priority(); \
}

#ifndef TX_TIMER_PROCESS_IN_ISR

#define TX_TIMER_INITIALIZE_EXTENSION(a) if (threadx_delete_timer_thread == ((TEST_FLAG) 1)) \
{ \
threadx_delete_timer_thread = ((TEST_FLAG) 0); \
delete_timer_thread(); \
(a) = ((UINT) 1); \
}

#endif

#define TX_THREAD_STACK_ANALYZE_EXTENSION if (test_stack_analyze_flag == ((TEST_FLAG) 1)) \
{ \
thread_ptr -> tx_thread_id = ((TEST_FLAG) 0); \
test_stack_analyze_flag = ((TEST_FLAG) 0); \
} \
else if (test_stack_analyze_flag == ((TEST_FLAG) 2)) \
{ \
stack_ptr = thread_ptr -> tx_thread_stack_start; \
test_stack_analyze_flag = ((TEST_FLAG) 0); \
} \
else if (test_stack_analyze_flag == ((TEST_FLAG) 3)) \
{ \
*stack_ptr = TX_STACK_FILL; \
test_stack_analyze_flag = ((TEST_FLAG) 0); \
} \
else \
{ \
test_stack_analyze_flag = ((TEST_FLAG) 0); \
}

#define TX_INITIALIZE_KERNEL_ENTER_EXTENSION if (test_initialize_flag == ((TEST_FLAG) 1)) \
{ \
test_initialize_flag = ((TEST_FLAG) 0); \
return; \
}

#endif /* TX_REGRESSION_TEST */

#endif /* __ASSEMBLER__ */


/* Define the version ID of ThreadX. This may be utilized by the application. */

#ifndef __ASSEMBLER__
Expand Down
2 changes: 1 addition & 1 deletion ports/risc-v32/gnu/src/tx_thread_context_restore.S
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ _tx_thread_no_preempt_restore:

csrr t1, mstatus
li t2, 0x1888 // MPP(0x1800) | MPIE(0x80) | MIE(0x08)
li t3, 0x1800 // Set MPP to Machine mode
li t3, 0x1880 // Set MPP=Machine(0x1800) + MPIE(0x80) so mret re-enables MIE
li t4, ~0x1888 // Clear mask for MPP/MPIE/MIE
and t1, t1, t4
or t1, t1, t3
Expand Down
18 changes: 18 additions & 0 deletions ports/risc-v64/gnu/example_build/qemu_virt/build_libthreadx.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
#!/bin/bash
printf "y\n" | rm -rf ../../../../../build/
rm -f kernel.elf

pushd ../../../../../
cmake -Bbuild -GNinja -DCMAKE_TOOLCHAIN_FILE=cmake/riscv64_gnu.cmake .
cmake --build ./build/
popd

riscv64-unknown-elf-gcc \
-march=rv64gc -mabi=lp64d \
-mcmodel=medany -O0 -g3 -Wall \
-ffunction-sections -fdata-sections \
-I../../../../../common/inc \
-I../../inc \
entry.s \
tx_initialize_low_level.S \
board.c uart.c hwtimer.c plic.c trap.c demo_threadx.c \
-L../../../../../build -lthreadx \
-T link.lds -nostartfiles \
-o kernel.elf


qemu-system-riscv64 -nographic -smp 1 -bios none -m 128M -machine virt -kernel kernel.elf
98 changes: 98 additions & 0 deletions ports/risc-v64/gnu/inc/tx_port.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,104 @@ UINT _tx_thread_interrupt_control(UIN
#define TX_SEMAPHORE_DISABLE TX_DISABLE


/* Define automated coverage test extensions for the ThreadX regression test. */

#ifndef __ASSEMBLER__

typedef unsigned int TEST_FLAG;
extern TEST_FLAG threadx_byte_allocate_loop_test;
extern TEST_FLAG threadx_byte_release_loop_test;
extern TEST_FLAG threadx_mutex_suspension_put_test;
extern TEST_FLAG threadx_mutex_suspension_priority_test;
#ifndef TX_TIMER_PROCESS_IN_ISR
extern TEST_FLAG threadx_delete_timer_thread;
#endif

extern void abort_and_resume_byte_allocating_thread(void);
extern void abort_all_threads_suspended_on_mutex(void);
extern void suspend_lowest_priority(void);
#ifndef TX_TIMER_PROCESS_IN_ISR
extern void delete_timer_thread(void);
#endif
extern TEST_FLAG test_stack_analyze_flag;
extern TEST_FLAG test_initialize_flag;
extern TEST_FLAG test_forced_mutex_timeout;


#ifdef TX_REGRESSION_TEST

#define TX_BYTE_ALLOCATE_EXTENSION if (threadx_byte_allocate_loop_test == ((TEST_FLAG) 1)) \
{ \
pool_ptr -> tx_byte_pool_owner = TX_NULL; \
threadx_byte_allocate_loop_test = ((TEST_FLAG) 0); \
}

#define TX_BYTE_RELEASE_EXTENSION if (threadx_byte_release_loop_test == ((TEST_FLAG) 1)) \
{ \
threadx_byte_release_loop_test = ((TEST_FLAG) 0); \
abort_and_resume_byte_allocating_thread(); \
}

#define TX_MUTEX_PUT_EXTENSION_1 if (threadx_mutex_suspension_put_test == ((TEST_FLAG) 1)) \
{ \
threadx_mutex_suspension_put_test = ((TEST_FLAG) 0); \
abort_all_threads_suspended_on_mutex(); \
}

#define TX_MUTEX_PUT_EXTENSION_2 if (test_forced_mutex_timeout == ((TEST_FLAG) 1)) \
{ \
test_forced_mutex_timeout = ((TEST_FLAG) 0); \
_tx_thread_wait_abort(mutex_ptr -> tx_mutex_suspension_list); \
}

#define TX_MUTEX_PRIORITY_CHANGE_EXTENSION if (threadx_mutex_suspension_priority_test == ((TEST_FLAG) 1)) \
{ \
threadx_mutex_suspension_priority_test = ((TEST_FLAG) 0); \
suspend_lowest_priority(); \
}

#ifndef TX_TIMER_PROCESS_IN_ISR

#define TX_TIMER_INITIALIZE_EXTENSION(a) if (threadx_delete_timer_thread == ((TEST_FLAG) 1)) \
{ \
threadx_delete_timer_thread = ((TEST_FLAG) 0); \
delete_timer_thread(); \
(a) = ((UINT) 1); \
}

#endif

#define TX_THREAD_STACK_ANALYZE_EXTENSION if (test_stack_analyze_flag == ((TEST_FLAG) 1)) \
{ \
thread_ptr -> tx_thread_id = ((TEST_FLAG) 0); \
test_stack_analyze_flag = ((TEST_FLAG) 0); \
} \
else if (test_stack_analyze_flag == ((TEST_FLAG) 2)) \
{ \
stack_ptr = thread_ptr -> tx_thread_stack_start; \
test_stack_analyze_flag = ((TEST_FLAG) 0); \
} \
else if (test_stack_analyze_flag == ((TEST_FLAG) 3)) \
{ \
*stack_ptr = TX_STACK_FILL; \
test_stack_analyze_flag = ((TEST_FLAG) 0); \
} \
else \
{ \
test_stack_analyze_flag = ((TEST_FLAG) 0); \
}

#define TX_INITIALIZE_KERNEL_ENTER_EXTENSION if (test_initialize_flag == ((TEST_FLAG) 1)) \
{ \
test_initialize_flag = ((TEST_FLAG) 0); \
return; \
}

#endif /* TX_REGRESSION_TEST */

#endif /* __ASSEMBLER__ */


/* Define the version ID of ThreadX. This may be utilized by the application. */

#ifndef __ASSEMBLER__
Expand Down
2 changes: 1 addition & 1 deletion ports/risc-v64/gnu/src/tx_thread_context_restore.S
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ _tx_thread_no_preempt_restore:

csrr t1, mstatus
li t2, 0x1888 // MPP(0x1800) | MPIE(0x80) | MIE(0x08)
li t3, 0x1800 // Set MPP to Machine mode
li t3, 0x1880 // Set MPP=Machine(0x1800) + MPIE(0x80) so mret re-enables MIE
li t4, ~0x1888 // Clear mask for MPP/MPIE/MIE
and t1, t1, t4
or t1, t1, t3
Expand Down
15 changes: 15 additions & 0 deletions scripts/build_tx_riscv.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash
# Build RISC-V regression tests for both RV32 and RV64.
# Usage: build_tx_riscv.sh [all|<config>]

SCRIPT_DIR="$(dirname "$(realpath "$0")")"
RUN_SH="${SCRIPT_DIR}/../test/tx/cmake/riscv/run.sh"

ARGS="${@:-all}"

echo "=== Building RISC-V32 ==="
"$RUN_SH" riscv32 build $ARGS

echo ""
echo "=== Building RISC-V64 ==="
"$RUN_SH" riscv64 build $ARGS
32 changes: 32 additions & 0 deletions scripts/install_riscv.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/bash
# Install RISC-V bare-metal cross-compiler toolchain and QEMU for CI.
set -e

RELEASE_TAG="2026.04.26"
BASE_URL="https://github.com/riscv-collab/riscv-gnu-toolchain/releases/download/${RELEASE_TAG}"
# Use ubuntu-24.04 binaries to match ubuntu-latest runners.
RV32_TARBALL="riscv32-elf-ubuntu-24.04-gcc.tar.xz"
RV64_TARBALL="riscv64-elf-ubuntu-24.04-gcc.tar.xz"

echo "=== Installing QEMU and build tools ==="
sudo apt-get update -qq
sudo apt-get install -y -qq qemu-system-misc ninja-build cmake

echo "=== Downloading RISC-V GCC toolchain (${RELEASE_TAG}) ==="

# Both tarballs extract into riscv/ with non-overlapping prefixes
# (riscv32-unknown-elf-* and riscv64-unknown-elf-*).
for tarball in "$RV32_TARBALL" "$RV64_TARBALL"; do
echo "Downloading ${tarball} ..."
wget --no-verbose "${BASE_URL}/${tarball}" -O "/tmp/${tarball}"
sudo tar xJf "/tmp/${tarball}" -C /opt
rm "/tmp/${tarball}"
done

TOOLCHAIN_BIN=/opt/riscv/bin
echo "$TOOLCHAIN_BIN" >> "$GITHUB_PATH"

echo "=== Verifying installation ==="
"$TOOLCHAIN_BIN/riscv32-unknown-elf-gcc" --version | head -1
"$TOOLCHAIN_BIN/riscv64-unknown-elf-gcc" --version | head -1
qemu-system-riscv64 --version | head -1
Loading