|
risc-v: refactor, consolidate, and fix RV32/RV64 ports
Consolidates the RISC-V 32-bit and 64-bit GNU/Clang port sources, fixes two
pre-existing assembly bugs discovered during testing, and hardens the build
infrastructure for both the regression suite and the CORE-V MCU example.
--- Port consolidation (RV32 GNU + Clang) ---
- Delete ports/risc-v32/clang/src/ (8 .S files had no Clang-specific
directives; diverged from GNU only due to missing bug fixes). The Clang
port CMakeLists.txt now compiles from ../gnu/src/.
- Change .global -> .weak for _tx_initialize_low_level in gnu/src/ to allow
BSP-level override without a linker conflict (adopted from Clang port).
- Create ports/risc-v32/common/tx_port_riscv32_common.h with all definitions
shared between GNU and Clang ports. Reduce both tx_port.h files to thin
wrappers.
- Add a prominent comment in risc-v64/gnu/inc/tx_port.h explaining why
LONG/ULONG are intentionally 32-bit on RV64 (ThreadX ABI requirement,
mirrors win64/MSVC LLP64).
--- Shared CMake helper ---
- Add cmake/threadx_riscv_port.cmake with threadx_add_riscv_port(). All
three port CMakeLists.txt files are reduced to ~8 lines each. Include path
is relative to CMAKE_CURRENT_LIST_DIR so the helper works whether ports
are built standalone or as a subdirectory of the test framework.
--- Shared example-build drivers ---
- Create canonical driver files under ports/risc-v_common/:
inc/csr.h (uintptr_t-based; portable RV32 + RV64)
example_build/plic/ (plic.c, plic.h)
example_build/uart/ (uart_qemu_ns16550.c/h; static inline putc_nolock)
example_build/trap/ (trap_qemu.c; XLEN-portable mcause constants)
- Replace per-example copies with symlinks in all qemu_virt and cva6_ariane
example directories.
- Fix OS_IS_INTERRUPT typo (was OS_IS_INTERUPT) in shared trap_qemu.c.
- Gate print_hex() behind TX_RISCV_TRAP_DEBUG.
--- Bug fixes in RV32 assembly ---
tx_thread_schedule.S:
- Solicited-return FP path: reload t0 from the mepc stack slot before
csrw mepc, t0. After the FP restore block, t0 held the fcsr value (0 for
new threads), which caused mepc = 0 and an immediate instruction-address
fault on the first context switch.
- Same path: reload t0 from the mstatus stack slot before csrw mstatus, t0
to avoid writing the stale fcsr value into mstatus.
tx_thread_system_return.S:
- FP callee-saved registers were saved unconditionally before the mstatus.FS
check, causing an illegal instruction trap (mcause=0x2) when a thread with
FS=Off (lazy FPU, thread has never used FP) voluntarily yielded.
- Apply the same FS guard pattern used in tx_thread_context_save.S: read
mstatus first, isolate FS[1:0], and skip fsw/fsd if FS == Off.
Both bugs were pre-existing on origin/dev and are unrelated to the
consolidation changes.
--- RV64 64-bit pointer compatibility ---
- Add TX_TIMER_INTERNAL_EXTENSION, TX_THREAD_CREATE_TIMEOUT_SETUP, and
TX_THREAD_TIMEOUT_POINTER_SETUP to risc-v64/gnu/inc/tx_port.h to store the
thread timeout pointer in a VOID
* extension field rather than truncating it
into a 32-bit ULONG. Mirrors the win64 port pattern.
- Define TX_TIMER_EXTENSION_PTR_DEFINED as a portable sentinel.
- Update threadx_thread_basic_execution_test.c guard from #if defined(_WIN64)
to #if defined(_WIN64) || defined(TX_TIMER_EXTENSION_PTR_DEFINED).
- Disable -Wconversion for the RV64 test build: ULONG = unsigned int (32-bit)
is intentional for ThreadX ABI but triggers spurious warnings when sizeof()
(8 bytes on RV64) appears in arithmetic with ULONG in common/src/.
--- Regression suite cmake fixes ---
test/tx/cmake/riscv/regression/CMakeLists.txt:
- Build testcontrol_weak_defaults.c as a separate OBJECT library and include
it in every test executable via $<TARGET_OBJECTS:>. GNU ld does not extract
objects from a static archive to satisfy weak symbols, so bundling it in
test_utility was insufficient for the standalone
threadx_initialize_kernel_setup_test.
test/tx/cmake/regression/CMakeLists.txt,
test/smp/cmake/regression/CMakeLists.txt:
- Same fix applied to the Linux and SMP regression builds. The symbols
abort_all_threads_suspended_on_mutex, suspend_lowest_priority, and
abort_and_resume_byte_allocating_thread were introduced by the win64 merge
and left the standalone test unlinkable.
--- CORE-V MCU toolchain and build fixes ---
cmake/riscv64-gcc-rv32imc.cmake:
- Resolve riscv64-unknown-elf-gcc via PATH so the riscv-collab toolchain in
/opt/riscv/bin is preferred when it appears first.
ports/risc-v32/gnu/example_build/core_v_mcu/bsp/clz.c (new):
- The riscv-collab toolchain is built without rv32 multilib, so its libgcc
does not define __clzsi2 (the helper emitted for __builtin_clz() in fll.c).
Add a weak __clzsi2 fallback so the build is self-contained with any
riscv64-unknown-elf toolchain. The weak attribute yields to a
libgcc-provided strong symbol when the Ubuntu multilib package is used.
core_v_mcu/CMakeLists.txt:
- Add bsp/clz.c to sources.
- Reference CMAKE_TOOLCHAIN_FILE via message(STATUS) to suppress the false-
positive "Manually-specified variables were not used by the project" CMake
warning and to show the active toolchain at configure time.
--- Housekeeping ---
- Rename azrtos_test_* -> threadx_test_* (eliminate Azure RTOS branding).
- Add RV64 QEMU CI test script:
ports/risc-v64/gnu/example_build/qemu_virt/test/
threadx_test_tx_gnu_riscv64_qemu.py
- Normalize entry.s -> entry.S in all 4 example directories.
- .gitignore: exclude build_m7/ and .codex local artifacts.
- CI: comment out the riscv regression workflow job and remove it from the
deploy job's needs list (preserved in-place for easy re-enablement).
--- Verified ---
- 95/95 RV32 regression tests pass (QEMU virt)
- 95/95 RV64 regression tests pass (QEMU virt)
- All 5 Linux build configurations build cleanly (default_build_coverage,
disable_notify_callbacks_build, stack_checking_build,
stack_checking_rand_fill_build, trace_build)
- CORE-V MCU example_build links cleanly with /opt/riscv toolchain
Co-authored-by: Copilot [email protected]
|
|
* Fixed race condition and message loss in Cortex-M GNU, AC6, and IAR ports (#516)
- Added compiler memory barriers to BASEPRI management functions in tx_port.h.
- Added architectural barriers (DSB/ISB) to scheduler return paths in tx_port.h and tx_thread_system_return.S to prevent fall-through before context switch.
- These changes address spurious thread resumption and lost messages, especially when TX_NOT_INTERRUPTABLE is enabled.
- These changes ensure that pending interrupts (specifically PendSV) are recognised before subsequent instructions are executed, following Kairalite's feedback and ARM architectural guidelines.
Assisted-by: Gemini (Gemini 2.0 Flash)
-----
* Added a comment in common/tx_queue_cleanup to document why the NI path omits revalidation guards
- In `TX_NOT_INTERRUPTABLE` mode, the caller keeps interrupts disabled across the entire cleanup call, so the race window that makes the guards necessary in the interruptable path cannot occur. Add a comment explaining this, and noting that all paths that resume a suspended thread clear tx_thread_suspend_cleanup before calling
_tx_thread_system_ni_resume, making double-cleanup impossible.
This prevents future false-positive suggestions (e.g. from AI tools) to add redundant checks to the NI path.
Relates to: eclipse-threadx/threadx#516
Co-authored-by: Copilot <[email protected]>
|