diff --git a/ports/risc-v64/gnu/CMakeLists.txt b/ports/risc-v64/gnu/CMakeLists.txt index b217065d2..9357c6970 100644 --- a/ports/risc-v64/gnu/CMakeLists.txt +++ b/ports/risc-v64/gnu/CMakeLists.txt @@ -9,7 +9,7 @@ target_sources(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S - ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S # {{END_TARGET_SOURCES}} ) diff --git a/ports/risc-v64/gnu/inc/tx_port.h b/ports/risc-v64/gnu/inc/tx_port.h index 855ecf82a..346083e53 100644 --- a/ports/risc-v64/gnu/inc/tx_port.h +++ b/ports/risc-v64/gnu/inc/tx_port.h @@ -53,26 +53,6 @@ #ifndef TX_PORT_H #define TX_PORT_H -#ifdef __ASSEMBLER__ - - -#if __riscv_xlen == 64 -# define SLL32 sllw -# define STORE sd -# define LOAD ld -# define LWU lwu -# define LOG_REGBYTES 3 -#else -# define SLL32 sll -# define STORE sw -# define LOAD lw -# define LWU lw -# define LOG_REGBYTES 2 -#endif -#define REGBYTES (1 << LOG_REGBYTES) - -#else /*not __ASSEMBLER__ */ - /* Include for memset. */ #include @@ -86,10 +66,7 @@ alternately be defined on the command line. */ #include "tx_user.h" -#endif - - -/* Define compiler library include files. */ +#endif /* TX_INCLUDE_USER_DEFINE_FILE */ /* Define ThreadX basic types for this port. */ @@ -105,8 +82,6 @@ typedef unsigned long long ULONG64; typedef short SHORT; typedef unsigned short USHORT; #define ULONG64_DEFINED -#define ALIGN_TYPE_DEFINED -#define ALIGN_TYPE ULONG64 @@ -253,25 +228,25 @@ typedef unsigned short USHORT; is used to define a local function save area for the disable and restore macros. */ -#ifdef TX_DISABLE_INLINE +/* Expose helper used to perform an atomic read/modify/write of mstatus. + The helper composes and returns the posture per ThreadX contract. */ +UINT _tx_thread_interrupt_control(UINT new_posture); -ULONG64 _tx_thread_interrupt_control(unsigned int new_posture); +#ifdef TX_DISABLE_INLINE -#define TX_INTERRUPT_SAVE_AREA register ULONG64 interrupt_save; +#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save; #define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE); #define TX_RESTORE _tx_thread_interrupt_control(interrupt_save); #else -#define TX_INTERRUPT_SAVE_AREA ULONG64 interrupt_save; -/* Atomically read mstatus into interrupt_save and clear bit 3 of mstatus. */ -#define TX_DISABLE {__asm__ ("csrrci %0, mstatus, 0x08" : "=r" (interrupt_save) : );}; -/* We only care about mstatus.mie (bit 3), so mask interrupt_save and write to mstatus. */ -#define TX_RESTORE {register ULONG64 __tempmask = interrupt_save & 0x08; \ - __asm__ ("csrrs x0, mstatus, %0 \n\t" : : "r" (__tempmask) : );}; +#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save; -#endif +#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE); +#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save); + +#endif /* TX_DISABLE_INLINE */ /* Define the interrupt lockout macros for each ThreadX object. */ @@ -291,7 +266,6 @@ CHAR _tx_version_id[] = "Copyright (c) 2024 Microsoft Corporation. * ThreadX RISC-V64/GNU Version 6.4.2 *"; #else extern CHAR _tx_version_id[]; -#endif +#endif /* TX_THREAD_INIT */ -#endif /*not __ASSEMBLER__ */ -#endif +#endif /* TX_PORT_H */ diff --git a/ports/risc-v64/gnu/readme_threadx.txt b/ports/risc-v64/gnu/readme_threadx.txt new file mode 100644 index 000000000..60854ecd5 --- /dev/null +++ b/ports/risc-v64/gnu/readme_threadx.txt @@ -0,0 +1,430 @@ + Eclipse Foundation's RTOS, ThreadX for RISC-V64 + + Using the GNU Tools + + +1. Building the ThreadX run-time Library + +Prerequisites +- Install a RISC-V64 bare-metal GNU toolchain with riscv64-unknown-elf prefix +- Common source: https://github.com/riscv-collab/riscv-gnu-toolchain + +Verify the toolchain: + riscv64-unknown-elf-gcc --version + riscv64-unknown-elf-objdump --version + +CMake-based build (recommended) + +From the ThreadX top-level directory: + + cmake -Bbuild -GNinja -DCMAKE_TOOLCHAIN_FILE=cmake/riscv64_gnu.cmake . + cmake --build ./build/ + +This uses cmake/riscv64_gnu.cmake and ports/risc-v64/gnu/CMakeLists.txt to +configure the cross-compiler flags and produce the ThreadX run-time library +and example binaries. + +Example build script + +The example demonstration contains a build script. See: + + ports/risc-v64/gnu/example_build/qemu_virt/build_libthreadx.sh + +This script builds the library and the demo application kernel.elf. + + +2. Demonstration System (QEMU) + +The provided example is targeted at QEMU's virt platform. After building the +example, the produced kernel.elf can be executed in QEMU: + + qemu-system-riscv64 -nographic -smp 1 -bios none -m 128M -machine virt -kernel kernel.elf + +Typical QEMU features used: +- Single-core CPU +- UART serial console +- PLIC (Platform-Level Interrupt Controller) +- CLINT (Core-Local Interruptor) for timer + + +3. System Initialization + +Entry Point + +The example startup code begins at the _start label in entry.s. This startup +code performs hardware initialization including: +- Check hart ID (only hart 0 continues; others enter WFI loop) +- Zero general-purpose registers +- Set up initial stack pointer +- Clear BSS section +- Jump to main() + +Low-Level Port Initialization (tx_initialize_low_level.S) + +The _tx_initialize_low_level function: +- Saves the system stack pointer to _tx_thread_system_stack_ptr +- Records first free RAM address from __tx_free_memory_start symbol +- Initializes floating-point control/status register (FCSR) if floating point enabled + +Board Initialization (board.c) + +After tx_initialize_low_level returns, main() calls board_init() to: +- Initialize PLIC (Platform-Level Interrupt Controller) +- Initialize UART +- Initialize hardware timer (CLINT) +- Set trap vector (mtvec) to point to trap handler + + +4. Register Usage and Stack Frames + +The RISC-V64 ABI defines t0-t6 and a0-a7 as caller-saved (scratch) registers. +All other registers used by a function must be preserved by the function. + +ThreadX takes advantage of this: when a context switch happens during a +function call, only the non-scratch registers need to be saved. + +Stack Frame Types + +Two types of stack frames exist: + +A. Interrupt Frame (stack type = 1) + Created when an interrupt occurs during thread execution. + Saves all registers including caller-saved registers. + Size: 65*8 = 520 bytes (with FP), or 32*8 = 256 bytes (without FP) + +B. Solicited Frame (stack type = 0) + Created when a thread voluntarily yields via ThreadX service calls. + Saves only callee-saved registers (s0-s11) and mstatus. + Size: 29*8 = 232 bytes (with FP), or 16*8 = 128 bytes (without FP) + + +Stack Layout for Interrupt Frame (with FP enabled): + + Index Offset Register Description + ───────────────────────────────────────────────── + 0 0x00 -- Stack type (1 = interrupt) + 1 0x08 s11 Preserved register + 2 0x10 s10 Preserved register + 3 0x18 s9 Preserved register + 4 0x20 s8 Preserved register + 5 0x28 s7 Preserved register + 6 0x30 s6 Preserved register + 7 0x38 s5 Preserved register + 8 0x40 s4 Preserved register + 9 0x48 s3 Preserved register + 10 0x50 s2 Preserved register + 11 0x58 s1 Preserved register + 12 0x60 s0 Preserved register + 13 0x68 t6 Scratch register + 14 0x70 t5 Scratch register + 15 0x78 t4 Scratch register + 16 0x80 t3 Scratch register + 17 0x88 t2 Scratch register + 18 0x90 t1 Scratch register + 19 0x98 t0 Scratch register + 20 0xA0 a7 Argument register + 21 0xA8 a6 Argument register + 22 0xB0 a5 Argument register + 23 0xB8 a4 Argument register + 24 0xC0 a3 Argument register + 25 0xC8 a2 Argument register + 26 0xD0 a1 Argument register + 27 0xD8 a0 Argument register + 28 0xE0 ra Return address + 29 0xE8 -- Reserved + 30 0xF0 mepc Machine exception PC + 31-46 0xF8-0x168 fs0-fs7 Preserved FP registers + 47-62 0x170-0x210 ft0-ft11 Scratch FP registers + 63 0x218 fcsr FP control/status register + ───────────────────────────────────────────────── + + +5. Interrupt Handling + +Machine Mode Operation + +ThreadX operates in machine mode (M-mode), the highest privilege level. +All interrupts and exceptions trap to machine mode. + +Interrupt Sources + +1. Machine Timer Interrupt (MTI): + - Triggered by CLINT when mtime >= mtimecmp + - Handled by _tx_timer_interrupt (src/tx_timer_interrupt.S) + - Called from trap handler in trap.c + +2. External Interrupts (MEI): + - Routed through PLIC + - Handler in trap.c calls registered ISR callbacks + +3. Software Interrupts (MSI): + - Supported but not actively used in this port + +Interrupt Flow + +1. Hardware trap entry (automatic): + - mepc <- PC (address of interrupted instruction) + - mcause <- exception/interrupt code + - mstatus.MPIE <- mstatus.MIE (save interrupt-enable state) + - mstatus.MIE <- 0 (disable interrupts) + - mstatus.MPP <- Machine mode + - PC <- mtvec (points to trap_entry in entry.s) + +2. Trap entry (entry.s): + - Allocates interrupt stack frame (32*8 or 65*8 bytes depending on FP) + - Saves RA (x1) on stack + - Calls _tx_thread_context_save + +3. Context save (_tx_thread_context_save.S): + - Increments _tx_thread_system_state (nested interrupt counter) + - If nested interrupt: saves remaining registers and returns to ISR + - If first interrupt: saves full context, switches to system stack + +4. Trap handler (trap.c): + - Examines mcause to determine interrupt type + - Dispatches to appropriate handler (_tx_timer_interrupt or PLIC handler) + - Returns to context restore + +5. Context restore (_tx_thread_context_restore.S): + - Decrements _tx_thread_system_state + - Checks if preemption needed + - Restores thread context or switches to next ready thread via scheduler + - Returns to interrupted thread or executes new thread + + +Interrupt Control Macros + +TX_DISABLE and TX_RESTORE macros atomically manage the MIE bit in mstatus: + + TX_DISABLE: Saves and clears MIE bit via csrrci (CSR read-clear immediate) + TX_RESTORE: Restores only MIE bit via csrrs (CSR read-set) + Other mstatus bits remain unchanged + +These are defined in ports/risc-v64/gnu/inc/tx_port.h and use the +_tx_thread_interrupt_control() function. + + +6. Thread Scheduling and Context Switching + +Thread Scheduler (src/tx_thread_schedule.S) + +The scheduler: +1. Enables interrupts while waiting for next thread +2. Spins until _tx_thread_execute_ptr becomes non-NULL +3. Disables interrupts (critical section) +4. Sets _tx_thread_current_ptr = _tx_thread_execute_ptr +5. Increments thread's run count +6. Switches to thread's stack +7. Determines stack frame type and restores context: + - Interrupt frame: full context restored, returns via mret + - Solicited frame: minimal context restored, returns via ret + +Initial Thread Stack Frame (src/tx_thread_stack_build.S) + +New threads start with a fake interrupt frame containing: +- All registers initialized to 0 +- ra (x1) = 0 +- mepc = entry function pointer +- Stack type = 1 (interrupt frame) +- Floating-point registers initialized based on ABI + + +7. Port Configuration and Macros + +Default Configurations (in ports/risc-v64/gnu/inc/tx_port.h): + + TX_MINIMUM_STACK 1024 /* Minimum thread stack size */ + TX_TIMER_THREAD_STACK_SIZE 1024 /* Timer thread stack size */ + TX_TIMER_THREAD_PRIORITY 0 /* Timer thread priority */ + TX_MAX_PRIORITIES 32 /* Must be multiple of 32 */ + +These can be overridden in tx_user.h or on the compiler command line. + + +8. Build Configuration + +CMake Toolchain File: cmake/riscv64_gnu.cmake + +Compiler Flags: + -march=rv64gc RV64 with IMAFD+C extensions + -mabi=lp64d 64-bit integers/pointers, double-precision FP in registers + -mcmodel=medany ±2GB addressability + -D__ASSEMBLER__ For assembly files + +ABI Selection + +The port uses lp64d ABI which includes: +- 64-bit integers and pointers +- Double-precision floating-point arguments in registers +- Floating-point registers f0-f31 + +When building with floating-point ABI: +- FP registers and FCSR are saved/restored in context switches +- Stack frames expand from 32*REGBYTES to 65*REGBYTES +- Conditional compilation uses __riscv_float_abi_double + + +9. File Organization + +Port-specific files (ports/risc-v64/gnu/): + +Core assembly files (src/): + - tx_initialize_low_level.S Initial setup and system state + - tx_thread_context_save.S Save context on interrupt entry + - tx_thread_context_restore.S Restore context on interrupt exit + - tx_thread_schedule.S Thread scheduler + - tx_thread_system_return.S Solicited context save for voluntary yield + - tx_thread_stack_build.S Build initial stack frame for new thread + - tx_thread_interrupt_control.S Interrupt enable/disable control + - tx_timer_interrupt.S Timer interrupt handler + +Header file (inc/): + - tx_port.h Port-specific defines and macros + +Example files (example_build/qemu_virt/): + - entry.s Startup code, trap entry point + - board.c, uart.c, hwtimer.c Platform-specific initialization + - plic.c PLIC interrupt controller driver + - trap.c Trap/exception dispatcher + - link.lds Linker script for QEMU virt + - build_libthreadx.sh Build script + + +10. Linker Script Requirements + +The linker script must provide: + +1. Entry point: + ENTRY(_start) + +2. Memory layout: + - .text section (code) + - .rodata section (read-only data) + - .data section (initialized data) + - .bss section (uninitialized data) + +3. Symbols: + - _end: First free memory address (used by ThreadX allocation) + - _bss_start, _bss_end: For zero initialization + - Initial stack space (example: 4KB) + +4. Alignment: + - 16-byte alignment throughout (RISC-V64 requirement) + +Example from QEMU virt build: + + SECTIONS + { + . = 0x80000000; /* QEMU virt base address */ + + .text : { *(.text .text.*) } + .rodata : { *(.rodata .rodata.*) } + .data : { *(.data .data.*) } + .bss : { *(.bss .bss.*) } + + .stack : { + . = ALIGN(4096); + _sysstack_start = .; + . += 0x1000; /* 4KB initial stack */ + _sysstack_end = .; + } + + PROVIDE(_end = .); + } + + +11. Floating-Point Support + +When building with lp64d ABI and FP enabled: + +- FP registers f0-f31 and FCSR are saved/restored during context switches +- Stack frames increase from 32*REGBYTES to 65*REGBYTES (256 to 520 bytes) +- MSTATUS.FS (floating-point state) field is set to indicate dirty FP state + +Stack frame differences: +- Without FP: 32*8 = 256 bytes (interrupt), 16*8 = 128 bytes (solicited) +- With FP: 65*8 = 520 bytes (interrupt), 29*8 = 232 bytes (solicited) + + +12. Performance and Debugging + +Performance Optimization + +Build optimizations: +- Use -O2 or -O3 for production (example uses -O0 for debugging) +- Enable -Wl,--gc-sections to remove unused code +- Define TX_DISABLE_ERROR_CHECKING to remove parameter checks +- Consider -flto for link-time optimization + +Debugging with QEMU and GDB + +Start QEMU in debug mode: + qemu-system-riscv64 -nographic -smp 1 -bios none -m 128M \ + -machine virt -kernel kernel.elf -s -S + + -s: Enable GDB server on TCP port 1234 + -S: Pause at startup waiting for GDB + +Connect GDB: + riscv64-unknown-elf-gdb kernel.elf + (gdb) target remote :1234 + (gdb) break main + (gdb) continue + +Useful GDB commands: + (gdb) info registers # View general registers + (gdb) info all-registers # Include CSR and FP registers + (gdb) p/x $mstatus # View machine status register + (gdb) x/32gx $sp # Examine stack memory + (gdb) p *_tx_thread_current_ptr # View current thread control block + + +13. Platform-Specific Notes (QEMU virt) + +PLIC Configuration + +The PLIC (Platform-Level Interrupt Controller) is memory-mapped at 0x0C000000: + +- Enables up to 1024 interrupt sources +- Supports priority levels 0-7 (0 = disabled) +- Requires per-hart priority threshold and enable register configuration + +Example PLIC usage (from plic.c): + plic_irq_enable(irq_number); # Enable specific interrupt + plic_prio_set(irq_number, priority);# Set priority level + +CLINT Configuration + +The CLINT (Core-Local Interruptor) is memory-mapped at 0x02000000: + +- CLINT_MSIP(hartid): 0x0000 + 4*hartid (software interrupt) +- CLINT_MTIMECMP(hartid): 0x4000 + 8*hartid (timer compare) +- CLINT_MTIME: 0xBFF8 (timer value, read-only) + +Timer frequency is platform-dependent (example uses 10MHz). + +Multi-Core Considerations + +The current port is single-core focused: +- Only hart 0 continues from reset; others enter WFI loop +- _tx_thread_system_state is a global variable +- No per-hart data structures + + +14. Revision History + +For generic code revision information, refer to readme_threadx_generic.txt. + +The following details the revision history for this RISC-V64 GNU port: + +01-26-2026 Akif Ejaz Comprehensive rewrite with accurate + technical details matching implementation, + register naming per RISC-V ABI, and + complete interrupt flow documentation + +03-08-2023 Scott Larson Initial Version 6.2.1 + + +Copyright (c) 1996-2026 Microsoft Corporation + +https://azure.com/rtos diff --git a/ports/risc-v64/gnu/src/tx_initialize_low_level.S b/ports/risc-v64/gnu/src/tx_initialize_low_level.S index ccafd5e22..68150c187 100644 --- a/ports/risc-v64/gnu/src/tx_initialize_low_level.S +++ b/ports/risc-v64/gnu/src/tx_initialize_low_level.S @@ -71,41 +71,45 @@ __tx_free_memory_start: .global _tx_initialize_low_level .weak _tx_initialize_low_level _tx_initialize_low_level: - sd sp, _tx_thread_system_stack_ptr, t0 // Save system stack pointer + /* Save the system stack pointer. */ + /* _tx_thread_system_stack_ptr = sp; */ + la t0, _tx_thread_system_stack_ptr + sd sp, 0(t0) /* Save system stack pointer */ - la t0, __tx_free_memory_start // Pickup first free address - sd t0, _tx_initialize_unused_memory, t1 // Save unused memory address + /* Pickup first free address. */ + /* _tx_initialize_unused_memory(__tx_free_memory_start); */ + la t0, __tx_free_memory_start /* Pickup first free address */ + la t1, _tx_initialize_unused_memory + sd t0, 0(t1) /* Save unused memory address */ + /* Initialize floating point control/status register if floating point is enabled. */ #ifdef __riscv_flen - fscsr x0 + li t0, 0 + csrw fcsr, t0 /* Clear FP control/status register */ #endif ret - - /* Define the actual timer interrupt/exception handler. */ - - .global timer1_plic_IRQHandler - //.global __minterrupt_000007 - //EXTWEAK __require_minterrupt_vector_table -timer1_plic_IRQHandler: -//__minterrupt_000007: - //REQUIRE __require_minterrupt_vector_table - - - /* Before calling _tx_thread_context_save, we have to allocate an interrupt - stack frame and save the current value of x1 (ra). */ -//#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) -// addi sp, sp, -520 // Allocate space for all registers - with floating point enabled -//#else -// addi sp, sp, -256 // Allocate space for all registers - without floating point enabled -//#endif -// sd x1, 224(sp) // Store RA -// call _tx_thread_context_save // Call ThreadX context save - - /* Call the ThreadX timer routine. */ - call _tx_timer_interrupt // Call timer interrupt handler - call timer1_interrupt - ret - /* Timer interrupt processing is done, jump to ThreadX context restore. */ -// j _tx_thread_context_restore // Jump to ThreadX context restore function. Note: this does not return! +/* Timer Interrupt Handler Note: + Platform-specific implementations must provide their own timer ISR. + The timer interrupt handler should follow this execution flow: + + 1. Disable interrupts (if not done by hardware exception entry) + 2. Allocate interrupt stack frame (65*8 bytes with FP, 32*8 bytes without) + 3. Save RA (x1) on the stack at offset 28*8 + 4. Call _tx_thread_context_save to save thread context + 5. Call _tx_timer_interrupt to process the timer tick + 6. Call _tx_thread_context_restore to resume execution (does not return) + + Example (for CLINT timer): + + _tx_timer_interrupt_handler: + addi sp, sp, -32*8 + sd ra, 28*8(sp) + call _tx_thread_context_save + call _tx_timer_interrupt + j _tx_thread_context_restore + + The port assumes Machine mode (M-mode) execution. + For Supervisor mode (S-mode), use sstatus and SIE/SPIE instead of mstatus. + See the RISC-V Privileged Specification for more details. */ diff --git a/ports/risc-v64/gnu/src/tx_thread_context_restore.S b/ports/risc-v64/gnu/src/tx_thread_context_restore.S index d805a59c8..edacb8b6d 100644 --- a/ports/risc-v64/gnu/src/tx_thread_context_restore.S +++ b/ports/risc-v64/gnu/src/tx_thread_context_restore.S @@ -19,7 +19,6 @@ /**************************************************************************/ /**************************************************************************/ -#include "tx_port.h" .section .text /**************************************************************************/ @@ -69,21 +68,21 @@ _tx_thread_context_restore: /* Lockout interrupts. */ - csrci mstatus, 0x08 // Disable interrupts + csrci mstatus, 0x08 /* Disable interrupts (MIE bit 3) */ #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY - call _tx_execution_isr_exit // Call the ISR execution exit function + call _tx_execution_isr_exit /* Call the ISR execution exit function */ #endif /* Determine if interrupts are nested. */ /* if (--_tx_thread_system_state) { */ - la t0, _tx_thread_system_state // Pickup addr of nested interrupt count - LOAD t1, 0(t0) // Pickup nested interrupt count - addi t1, t1, -1 // Decrement the nested interrupt counter - STORE t1, 0(t0) // Store new nested count - beqz t1, _tx_thread_not_nested_restore // If 0, not nested restore + la t0, _tx_thread_system_state /* Pickup addr of nested interrupt count */ + ld t1, 0(t0) /* Pickup nested interrupt count */ + addi t1, t1, -1 /* Decrement the nested interrupt counter */ + sd t1, 0(t0) /* Store new nested count */ + beqz t1, _tx_thread_not_nested_restore /* If 0, not nested restore */ /* Interrupts are nested. */ @@ -92,51 +91,51 @@ _tx_thread_context_restore: /* Recover floating point registers. */ #if defined(__riscv_float_abi_single) - flw f0, 31*REGBYTES(sp) // Recover ft0 - flw f1, 32*REGBYTES(sp) // Recover ft1 - flw f2, 33*REGBYTES(sp) // Recover ft2 - flw f3, 34*REGBYTES(sp) // Recover ft3 - flw f4, 35*REGBYTES(sp) // Recover ft4 - flw f5, 36*REGBYTES(sp) // Recover ft5 - flw f6, 37*REGBYTES(sp) // Recover ft6 - flw f7, 38*REGBYTES(sp) // Recover ft7 - flw f10,41*REGBYTES(sp) // Recover fa0 - flw f11,42*REGBYTES(sp) // Recover fa1 - flw f12,43*REGBYTES(sp) // Recover fa2 - flw f13,44*REGBYTES(sp) // Recover fa3 - flw f14,45*REGBYTES(sp) // Recover fa4 - flw f15,46*REGBYTES(sp) // Recover fa5 - flw f16,47*REGBYTES(sp) // Recover fa6 - flw f17,48*REGBYTES(sp) // Recover fa7 - flw f28,59*REGBYTES(sp) // Recover ft8 - flw f29,60*REGBYTES(sp) // Recover ft9 - flw f30,61*REGBYTES(sp) // Recover ft10 - flw f31,62*REGBYTES(sp) // Recover ft11 - lw t0, 63*REGBYTES(sp) // Recover fcsr - csrw fcsr, t0 // + flw f0, 31*8(sp) /* Recover ft0 */ + flw f1, 32*8(sp) /* Recover ft1 */ + flw f2, 33*8(sp) /* Recover ft2 */ + flw f3, 34*8(sp) /* Recover ft3 */ + flw f4, 35*8(sp) /* Recover ft4 */ + flw f5, 36*8(sp) /* Recover ft5 */ + flw f6, 37*8(sp) /* Recover ft6 */ + flw f7, 38*8(sp) /* Recover ft7 */ + flw f10,41*8(sp) /* Recover fa0 */ + flw f11,42*8(sp) /* Recover fa1 */ + flw f12,43*8(sp) /* Recover fa2 */ + flw f13,44*8(sp) /* Recover fa3 */ + flw f14,45*8(sp) /* Recover fa4 */ + flw f15,46*8(sp) /* Recover fa5 */ + flw f16,47*8(sp) /* Recover fa6 */ + flw f17,48*8(sp) /* Recover fa7 */ + flw f28,59*8(sp) /* Recover ft8 */ + flw f29,60*8(sp) /* Recover ft9 */ + flw f30,61*8(sp) /* Recover ft10 */ + flw f31,62*8(sp) /* Recover ft11 */ + ld t0, 63*8(sp) /* Recover fcsr */ + csrw fcsr, t0 /* Restore fcsr */ #elif defined(__riscv_float_abi_double) - fld f0, 31*REGBYTES(sp) // Recover ft0 - fld f1, 32*REGBYTES(sp) // Recover ft1 - fld f2, 33*REGBYTES(sp) // Recover ft2 - fld f3, 34*REGBYTES(sp) // Recover ft3 - fld f4, 35*REGBYTES(sp) // Recover ft4 - fld f5, 36*REGBYTES(sp) // Recover ft5 - fld f6, 37*REGBYTES(sp) // Recover ft6 - fld f7, 38*REGBYTES(sp) // Recover ft7 - fld f10,41*REGBYTES(sp) // Recover fa0 - fld f11,42*REGBYTES(sp) // Recover fa1 - fld f12,43*REGBYTES(sp) // Recover fa2 - fld f13,44*REGBYTES(sp) // Recover fa3 - fld f14,45*REGBYTES(sp) // Recover fa4 - fld f15,46*REGBYTES(sp) // Recover fa5 - fld f16,47*REGBYTES(sp) // Recover fa6 - fld f17,48*REGBYTES(sp) // Recover fa7 - fld f28,59*REGBYTES(sp) // Recover ft8 - fld f29,60*REGBYTES(sp) // Recover ft9 - fld f30,61*REGBYTES(sp) // Recover ft10 - fld f31,62*REGBYTES(sp) // Recover ft11 - LOAD t0, 63*REGBYTES(sp) // Recover fcsr - csrw fcsr, t0 // + fld f0, 31*8(sp) /* Recover ft0 */ + fld f1, 32*8(sp) /* Recover ft1 */ + fld f2, 33*8(sp) /* Recover ft2 */ + fld f3, 34*8(sp) /* Recover ft3 */ + fld f4, 35*8(sp) /* Recover ft4 */ + fld f5, 36*8(sp) /* Recover ft5 */ + fld f6, 37*8(sp) /* Recover ft6 */ + fld f7, 38*8(sp) /* Recover ft7 */ + fld f10,41*8(sp) /* Recover fa0 */ + fld f11,42*8(sp) /* Recover fa1 */ + fld f12,43*8(sp) /* Recover fa2 */ + fld f13,44*8(sp) /* Recover fa3 */ + fld f14,45*8(sp) /* Recover fa4 */ + fld f15,46*8(sp) /* Recover fa5 */ + fld f16,47*8(sp) /* Recover fa6 */ + fld f17,48*8(sp) /* Recover fa7 */ + fld f28,59*8(sp) /* Recover ft8 */ + fld f29,60*8(sp) /* Recover ft9 */ + fld f30,61*8(sp) /* Recover ft10 */ + fld f31,62*8(sp) /* Recover ft11 */ + ld t0, 63*8(sp) /* Recover fcsr */ + csrw fcsr, t0 #endif /* Recover standard registers. */ @@ -146,39 +145,56 @@ _tx_thread_context_restore: Also skip the saved registers since they have been restored by any function we called, except s0 since we use it ourselves. */ - LOAD t0, 30*REGBYTES(sp) // Recover mepc - csrw mepc, t0 // Setup mepc - li t0, 0x1880 // Prepare MPIP + ld t0, 30*8(sp) /* Recover mepc */ + csrw mepc, t0 /* Setup mepc */ + + /* Compose mstatus via read/modify/write to avoid clobbering unrelated bits. + Set MPIE and restore MPP to Machine, preserve other fields. */ + + csrr t1, mstatus + + /* Clear MPP/MPIE/MIE bits in t1 then set desired values. */ + + li t2, 0x1888 /* MPP(0x1800) | MPIE(0x80) | MIE(0x08) */ + li t3, 0x1800 /* Set MPP to Machine mode (bits 12:11) */ + + /* Construct new mstatus in t1: clear mask bits, set MPP/MPIE and optionally FP bit, + preserve everything except the bits we will modify. */ + + li t4, ~0x1888 /* Clear mask for MPP/MPIE/MIE */ + and t1, t1, t4 + or t1, t1, t3 + #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - li t1, 1<<13 - or t0, t1, t0 + li t0, 0x2000 /* Set FS bits (bits 14:13 to 01) for FP state */ + or t1, t1, t0 #endif - csrw mstatus, t0 // Enable MPIP - - LOAD x1, 28*REGBYTES(sp) // Recover RA - LOAD x5, 19*REGBYTES(sp) // Recover t0 - LOAD x6, 18*REGBYTES(sp) // Recover t1 - LOAD x7, 17*REGBYTES(sp) // Recover t2 - LOAD x8, 12*REGBYTES(sp) // Recover s0 - LOAD x10, 27*REGBYTES(sp) // Recover a0 - LOAD x11, 26*REGBYTES(sp) // Recover a1 - LOAD x12, 25*REGBYTES(sp) // Recover a2 - LOAD x13, 24*REGBYTES(sp) // Recover a3 - LOAD x14, 23*REGBYTES(sp) // Recover a4 - LOAD x15, 22*REGBYTES(sp) // Recover a5 - LOAD x16, 21*REGBYTES(sp) // Recover a6 - LOAD x17, 20*REGBYTES(sp) // Recover a7 - LOAD x28, 16*REGBYTES(sp) // Recover t3 - LOAD x29, 15*REGBYTES(sp) // Recover t4 - LOAD x30, 14*REGBYTES(sp) // Recover t5 - LOAD x31, 13*REGBYTES(sp) // Recover t6 + csrw mstatus, t1 /* Update mstatus safely */ + + ld ra, 28*8(sp) /* Recover return address */ + ld t0, 19*8(sp) /* Recover t0 */ + ld t1, 18*8(sp) /* Recover t1 */ + ld t2, 17*8(sp) /* Recover t2 */ + ld s0, 12*8(sp) /* Recover s0 */ + ld a0, 27*8(sp) /* Recover a0 */ + ld a1, 26*8(sp) /* Recover a1 */ + ld a2, 25*8(sp) /* Recover a2 */ + ld a3, 24*8(sp) /* Recover a3 */ + ld a4, 23*8(sp) /* Recover a4 */ + ld a5, 22*8(sp) /* Recover a5 */ + ld a6, 21*8(sp) /* Recover a6 */ + ld a7, 20*8(sp) /* Recover a7 */ + ld t3, 16*8(sp) /* Recover t3 */ + ld t4, 15*8(sp) /* Recover t4 */ + ld t5, 14*8(sp) /* Recover t5 */ + ld t6, 13*8(sp) /* Recover t6 */ #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 65*REGBYTES // Recover stack frame - with floating point enabled + addi sp, sp, 65*8 /* Recover stack frame - with floating point enabled */ #else - addi sp, sp, 32*REGBYTES // Recover stack frame - without floating point enabled + addi sp, sp, 32*8 /* Recover stack frame - without floating point enabled */ #endif - mret // Return to point of interrupt + mret /* Return to point of interrupt */ /* } */ _tx_thread_not_nested_restore: @@ -187,71 +203,74 @@ _tx_thread_not_nested_restore: || (_tx_thread_preempt_disable)) { */ - LOAD t1, _tx_thread_current_ptr // Pickup current thread pointer - beqz t1, _tx_thread_idle_system_restore // If NULL, idle system restore + la t0, _tx_thread_current_ptr /* Pickup current thread pointer address */ + ld t1, 0(t0) /* Pickup current thread pointer */ + beqz t1, _tx_thread_idle_system_restore /* If NULL, idle system restore */ - LOAD t2, _tx_thread_preempt_disable // Pickup preempt disable flag - bgtz t2, _tx_thread_no_preempt_restore // If set, restore interrupted thread + la t0, _tx_thread_preempt_disable /* Pickup preempt disable flag address */ + lw t2, 0(t0) /* Pickup preempt disable flag (UINT) */ + bgtz t2, _tx_thread_no_preempt_restore /* If set, restore interrupted thread */ - LOAD t2, _tx_thread_execute_ptr // Pickup thread execute pointer - bne t1, t2, _tx_thread_preempt_restore // If higher-priority thread is ready, preempt + la t0, _tx_thread_execute_ptr /* Pickup thread execute pointer address */ + ld t2, 0(t0) /* Pickup thread execute pointer */ + bne t1, t2, _tx_thread_preempt_restore /* If higher-priority thread is ready, preempt */ _tx_thread_no_preempt_restore: /* Restore interrupted thread or ISR. */ /* Pickup the saved stack pointer. */ - /* SP = _tx_thread_current_ptr -> tx_thread_stack_ptr; */ + /* sp = _tx_thread_current_ptr -> tx_thread_stack_ptr; */ - LOAD sp, 2*REGBYTES(t1) // Switch back to thread's stack + ld sp, 16(t1) /* Switch back to thread's stack */ /* Recover floating point registers. */ #if defined(__riscv_float_abi_single) - flw f0, 31*REGBYTES(sp) // Recover ft0 - flw f1, 32*REGBYTES(sp) // Recover ft1 - flw f2, 33*REGBYTES(sp) // Recover ft2 - flw f3, 34*REGBYTES(sp) // Recover ft3 - flw f4, 35*REGBYTES(sp) // Recover ft4 - flw f5, 36*REGBYTES(sp) // Recover ft5 - flw f6, 37*REGBYTES(sp) // Recover ft6 - flw f7, 38*REGBYTES(sp) // Recover ft7 - flw f10,41*REGBYTES(sp) // Recover fa0 - flw f11,42*REGBYTES(sp) // Recover fa1 - flw f12,43*REGBYTES(sp) // Recover fa2 - flw f13,44*REGBYTES(sp) // Recover fa3 - flw f14,45*REGBYTES(sp) // Recover fa4 - flw f15,46*REGBYTES(sp) // Recover fa5 - flw f16,47*REGBYTES(sp) // Recover fa6 - flw f17,48*REGBYTES(sp) // Recover fa7 - flw f28,59*REGBYTES(sp) // Recover ft8 - flw f29,60*REGBYTES(sp) // Recover ft9 - flw f30,61*REGBYTES(sp) // Recover ft10 - flw f31,62*REGBYTES(sp) // Recover ft11 - lw t0, 63*REGBYTES(sp) // Recover fcsr - csrw fcsr, t0 // + flw f0, 31*8(sp) /* Recover ft0 */ + flw f1, 32*8(sp) /* Recover ft1 */ + flw f2, 33*8(sp) /* Recover ft2 */ + flw f3, 34*8(sp) /* Recover ft3 */ + flw f4, 35*8(sp) /* Recover ft4 */ + flw f5, 36*8(sp) /* Recover ft5 */ + flw f6, 37*8(sp) /* Recover ft6 */ + flw f7, 38*8(sp) /* Recover ft7 */ + flw f10,41*8(sp) /* Recover fa0 */ + flw f11,42*8(sp) /* Recover fa1 */ + flw f12,43*8(sp) /* Recover fa2 */ + flw f13,44*8(sp) /* Recover fa3 */ + flw f14,45*8(sp) /* Recover fa4 */ + flw f15,46*8(sp) /* Recover fa5 */ + flw f16,47*8(sp) /* Recover fa6 */ + flw f17,48*8(sp) /* Recover fa7 */ + flw f28,59*8(sp) /* Recover ft8 */ + flw f29,60*8(sp) /* Recover ft9 */ + flw f30,61*8(sp) /* Recover ft10 */ + flw f31,62*8(sp) /* Recover ft11 */ + ld t0, 63*8(sp) /* Recover fcsr */ + csrw fcsr, t0 /* Restore fcsr */ #elif defined(__riscv_float_abi_double) - fld f0, 31*REGBYTES(sp) // Recover ft0 - fld f1, 32*REGBYTES(sp) // Recover ft1 - fld f2, 33*REGBYTES(sp) // Recover ft2 - fld f3, 34*REGBYTES(sp) // Recover ft3 - fld f4, 35*REGBYTES(sp) // Recover ft4 - fld f5, 36*REGBYTES(sp) // Recover ft5 - fld f6, 37*REGBYTES(sp) // Recover ft6 - fld f7, 38*REGBYTES(sp) // Recover ft7 - fld f10,41*REGBYTES(sp) // Recover fa0 - fld f11,42*REGBYTES(sp) // Recover fa1 - fld f12,43*REGBYTES(sp) // Recover fa2 - fld f13,44*REGBYTES(sp) // Recover fa3 - fld f14,45*REGBYTES(sp) // Recover fa4 - fld f15,46*REGBYTES(sp) // Recover fa5 - fld f16,47*REGBYTES(sp) // Recover fa6 - fld f17,48*REGBYTES(sp) // Recover fa7 - fld f28,59*REGBYTES(sp) // Recover ft8 - fld f29,60*REGBYTES(sp) // Recover ft9 - fld f30,61*REGBYTES(sp) // Recover ft10 - fld f31,62*REGBYTES(sp) // Recover ft11 - LOAD t0, 63*REGBYTES(sp) // Recover fcsr - csrw fcsr, t0 // + fld f0, 31*8(sp) /* Recover ft0 */ + fld f1, 32*8(sp) /* Recover ft1 */ + fld f2, 33*8(sp) /* Recover ft2 */ + fld f3, 34*8(sp) /* Recover ft3 */ + fld f4, 35*8(sp) /* Recover ft4 */ + fld f5, 36*8(sp) /* Recover ft5 */ + fld f6, 37*8(sp) /* Recover ft6 */ + fld f7, 38*8(sp) /* Recover ft7 */ + fld f10,41*8(sp) /* Recover fa0 */ + fld f11,42*8(sp) /* Recover fa1 */ + fld f12,43*8(sp) /* Recover fa2 */ + fld f13,44*8(sp) /* Recover fa3 */ + fld f14,45*8(sp) /* Recover fa4 */ + fld f15,46*8(sp) /* Recover fa5 */ + fld f16,47*8(sp) /* Recover fa6 */ + fld f17,48*8(sp) /* Recover fa7 */ + fld f28,59*8(sp) /* Recover ft8 */ + fld f29,60*8(sp) /* Recover ft9 */ + fld f30,61*8(sp) /* Recover ft10 */ + fld f31,62*8(sp) /* Recover ft11 */ + ld t0, 63*8(sp) /* Recover fcsr */ + csrw fcsr, t0 /* Restore fcsr */ #endif /* Recover the saved context and return to the point of interrupt. */ @@ -260,39 +279,48 @@ _tx_thread_no_preempt_restore: /* Restore registers, Skip global pointer because that does not change */ - LOAD t0, 240(sp) // Recover mepc - csrw mepc, t0 // Setup mepc - li t0, 0x1880 // Prepare MPIP + ld t0, 30*8(sp) /* Recover mepc */ + csrw mepc, t0 /* Setup mepc */ + + /* Compose mstatus via read/modify/write to avoid clobbering unrelated bits. */ + + csrr t1, mstatus + li t2, 0x1888 /* MPP(0x1800) | MPIE(0x80) | MIE(0x08) */ + li t3, 0x1800 /* Set MPP to Machine mode */ + li t4, ~0x1888 /* Clear mask for MPP/MPIE/MIE */ + and t1, t1, t4 + or t1, t1, t3 + #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - li t1, 1<<13 - or t0, t1, t0 + li t0, 0x2000 /* Set FS bits for FP state */ + or t1, t1, t0 #endif - csrw mstatus, t0 // Enable MPIP - - LOAD x1, 28*REGBYTES(sp) // Recover RA - LOAD x5, 19*REGBYTES(sp) // Recover t0 - LOAD x6, 18*REGBYTES(sp) // Recover t1 - LOAD x7, 17*REGBYTES(sp) // Recover t2 - LOAD x8, 12*REGBYTES(sp) // Recover s0 - LOAD x10, 27*REGBYTES(sp) // Recover a0 - LOAD x11, 26*REGBYTES(sp) // Recover a1 - LOAD x12, 25*REGBYTES(sp) // Recover a2 - LOAD x13, 24*REGBYTES(sp) // Recover a3 - LOAD x14, 23*REGBYTES(sp) // Recover a4 - LOAD x15, 22*REGBYTES(sp) // Recover a5 - LOAD x16, 21*REGBYTES(sp) // Recover a6 - LOAD x17, 20*REGBYTES(sp) // Recover a7 - LOAD x28, 16*REGBYTES(sp) // Recover t3 - LOAD x29, 15*REGBYTES(sp) // Recover t4 - LOAD x30, 14*REGBYTES(sp) // Recover t5 - LOAD x31, 13*REGBYTES(sp) // Recover t6 + csrw mstatus, t1 /* Update mstatus safely */ + + ld ra, 28*8(sp) /* Recover return address */ + ld t0, 19*8(sp) /* Recover t0 */ + ld t1, 18*8(sp) /* Recover t1 */ + ld t2, 17*8(sp) /* Recover t2 */ + ld s0, 12*8(sp) /* Recover s0 */ + ld a0, 27*8(sp) /* Recover a0 */ + ld a1, 26*8(sp) /* Recover a1 */ + ld a2, 25*8(sp) /* Recover a2 */ + ld a3, 24*8(sp) /* Recover a3 */ + ld a4, 23*8(sp) /* Recover a4 */ + ld a5, 22*8(sp) /* Recover a5 */ + ld a6, 21*8(sp) /* Recover a6 */ + ld a7, 20*8(sp) /* Recover a7 */ + ld t3, 16*8(sp) /* Recover t3 */ + ld t4, 15*8(sp) /* Recover t4 */ + ld t5, 14*8(sp) /* Recover t5 */ + ld t6, 13*8(sp) /* Recover t6 */ #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 65*REGBYTES // Recover stack frame - with floating point enabled + addi sp, sp, 65*8 /* Recover stack frame - with floating point enabled */ #else - addi sp, sp, 32*REGBYTES // Recover stack frame - without floating point enabled + addi sp, sp, 32*8 /* Recover stack frame - without floating point enabled */ #endif - mret // Return to point of interrupt + mret /* Return to point of interrupt */ /* } else @@ -301,52 +329,52 @@ _tx_thread_preempt_restore: /* Instead of directly activating the thread again, ensure we save the entire stack frame by saving the remaining registers. */ - LOAD t0, 2*REGBYTES(t1) // Pickup thread's stack pointer - ori t3, x0, 1 // Build interrupt stack type - STORE t3, 0(t0) // Store stack type + ld t0, 16(t1) /* Pickup thread's stack pointer */ + ori t3, zero, 1 /* Build interrupt stack type */ + sd t3, 0(t0) /* Store stack type */ /* Store floating point preserved registers. */ #ifdef __riscv_float_abi_single - fsw f8, 39*REGBYTES(t0) // Store fs0 - fsw f9, 40*REGBYTES(t0) // Store fs1 - fsw f18, 49*REGBYTES(t0) // Store fs2 - fsw f19, 50*REGBYTES(t0) // Store fs3 - fsw f20, 51*REGBYTES(t0) // Store fs4 - fsw f21, 52*REGBYTES(t0) // Store fs5 - fsw f22, 53*REGBYTES(t0) // Store fs6 - fsw f23, 54*REGBYTES(t0) // Store fs7 - fsw f24, 55*REGBYTES(t0) // Store fs8 - fsw f25, 56*REGBYTES(t0) // Store fs9 - fsw f26, 57*REGBYTES(t0) // Store fs10 - fsw f27, 58*REGBYTES(t0) // Store fs11 + fsw f8, 39*8(t0) /* Store fs0 */ + fsw f9, 40*8(t0) /* Store fs1 */ + fsw f18, 49*8(t0) /* Store fs2 */ + fsw f19, 50*8(t0) // Store fs3 + fsw f20, 51*8(t0) // Store fs4 + fsw f21, 52*8(t0) // Store fs5 + fsw f22, 53*8(t0) // Store fs6 + fsw f23, 54*8(t0) // Store fs7 + fsw f24, 55*8(t0) // Store fs8 + fsw f25, 56*8(t0) // Store fs9 + fsw f26, 57*8(t0) // Store fs10 + fsw f27, 58*8(t0) // Store fs11 #elif defined(__riscv_float_abi_double) - fsd f8, 39*REGBYTES(t0) // Store fs0 - fsd f9, 40*REGBYTES(t0) // Store fs1 - fsd f18, 49*REGBYTES(t0) // Store fs2 - fsd f19, 50*REGBYTES(t0) // Store fs3 - fsd f20, 51*REGBYTES(t0) // Store fs4 - fsd f21, 52*REGBYTES(t0) // Store fs5 - fsd f22, 53*REGBYTES(t0) // Store fs6 - fsd f23, 54*REGBYTES(t0) // Store fs7 - fsd f24, 55*REGBYTES(t0) // Store fs8 - fsd f25, 56*REGBYTES(t0) // Store fs9 - fsd f26, 57*REGBYTES(t0) // Store fs10 - fsd f27, 58*REGBYTES(t0) // Store fs11 + fsd f8, 39*8(t0) // Store fs0 + fsd f9, 40*8(t0) // Store fs1 + fsd f18, 49*8(t0) // Store fs2 + fsd f19, 50*8(t0) // Store fs3 + fsd f20, 51*8(t0) // Store fs4 + fsd f21, 52*8(t0) // Store fs5 + fsd f22, 53*8(t0) // Store fs6 + fsd f23, 54*8(t0) // Store fs7 + fsd f24, 55*8(t0) // Store fs8 + fsd f25, 56*8(t0) // Store fs9 + fsd f26, 57*8(t0) // Store fs10 + fsd f27, 58*8(t0) // Store fs11 #endif /* Store standard preserved registers. */ - STORE x9, 11*REGBYTES(t0) // Store s1 - STORE x18, 10*REGBYTES(t0) // Store s2 - STORE x19, 9*REGBYTES(t0) // Store s3 - STORE x20, 8*REGBYTES(t0) // Store s4 - STORE x21, 7*REGBYTES(t0) // Store s5 - STORE x22, 6*REGBYTES(t0) // Store s6 - STORE x23, 5*REGBYTES(t0) // Store s7 - STORE x24, 4*REGBYTES(t0) // Store s8 - STORE x25, 3*REGBYTES(t0) // Store s9 - STORE x26, 2*REGBYTES(t0) // Store s10 - STORE x27, 1*REGBYTES(t0) // Store s11 + sd x9, 11*8(t0) // Store s1 + sd x18, 10*8(t0) // Store s2 + sd x19, 9*8(t0) // Store s3 + sd x20, 8*8(t0) // Store s4 + sd x21, 7*8(t0) // Store s5 + sd x22, 6*8(t0) // Store s6 + sd x23, 5*8(t0) // Store s7 + sd x24, 4*8(t0) // Store s8 + sd x25, 3*8(t0) // Store s9 + sd x26, 2*8(t0) // Store s10 + sd x27, 1*8(t0) // Store s11 // Note: s0 is already stored! /* Save the remaining time-slice and disable it. */ @@ -354,14 +382,14 @@ _tx_thread_preempt_restore: { */ la t0, _tx_timer_time_slice // Pickup time slice variable address - LOAD t2, 0(t0) // Pickup time slice + ld t2, 0(t0) // Pickup time slice beqz t2, _tx_thread_dont_save_ts // If 0, skip time slice processing /* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice _tx_timer_time_slice = 0; */ - STORE t2, 6*REGBYTES(t1) // Save current time slice - STORE x0, 0(t0) // Clear global time slice + sd t2, 48(t1) // Save current time slice + sd x0, 0(t0) // Clear global time slice /* } */ @@ -372,7 +400,8 @@ _tx_thread_dont_save_ts: /* Return to the scheduler. */ /* _tx_thread_schedule(); */ - STORE x0, _tx_thread_current_ptr, t0 // Clear current thread pointer*/ + la t0, _tx_thread_current_ptr // Pickup current thread pointer address + sd x0, 0(t0) // Clear current thread pointer*/ /* } */ _tx_thread_idle_system_restore: diff --git a/ports/risc-v64/gnu/src/tx_thread_context_save.S b/ports/risc-v64/gnu/src/tx_thread_context_save.S index a1f2a9b64..13281d7f3 100644 --- a/ports/risc-v64/gnu/src/tx_thread_context_save.S +++ b/ports/risc-v64/gnu/src/tx_thread_context_save.S @@ -19,8 +19,6 @@ /**************************************************************************/ /**************************************************************************/ -#include "tx_port.h" - .section .text /**************************************************************************/ /* */ @@ -67,97 +65,97 @@ _tx_thread_context_save: /* Upon entry to this routine, it is assumed that interrupts are locked - out and the interrupt stack fame has been allocated and x1 (ra) has + out and the interrupt stack frame has been allocated and ra has been saved on the stack. */ - STORE x5, 19*REGBYTES(sp) // First store t0 and t1 - STORE x6, 18*REGBYTES(sp) + sd t0, 19*8(sp) /* First store t0 and t1 */ + sd t1, 18*8(sp) - la x5, _tx_thread_system_state // Pickup address of system state - LOAD x6, 0(x5) // Pickup system state + la t0, _tx_thread_system_state /* Pickup address of system state */ + ld t1, 0(t0) /* Pickup system state */ /* Check for a nested interrupt condition. */ /* if (_tx_thread_system_state++) { */ - beqz x6, _tx_thread_not_nested_save // If 0, first interrupt condition - addi x6, x6, 1 // Increment the interrupt counter - STORE x6, 0(x5) // Store the interrupt counter + beqz t1, _tx_thread_not_nested_save /* If 0, first interrupt condition */ + addi t1, t1, 1 /* Increment the interrupt counter */ + sd t1, 0(t0) /* Store the interrupt counter */ /* Nested interrupt condition. - Save the reset of the scratch registers on the stack and return to the + Save the rest of the scratch registers on the stack and return to the calling ISR. */ - STORE x7, 17*REGBYTES(sp) // Store t2 - STORE x8, 12*REGBYTES(sp) // Store s0 - STORE x10, 27*REGBYTES(sp) // Store a0 - STORE x11, 26*REGBYTES(sp) // Store a1 - STORE x12, 25*REGBYTES(sp) // Store a2 - STORE x13, 24*REGBYTES(sp) // Store a3 - STORE x14, 23*REGBYTES(sp) // Store a4 - STORE x15, 22*REGBYTES(sp) // Store a5 - STORE x16, 21*REGBYTES(sp) // Store a6 - STORE x17, 20*REGBYTES(sp) // Store a7 - STORE x28, 16*REGBYTES(sp) // Store t3 - STORE x29, 15*REGBYTES(sp) // Store t4 - STORE x30, 14*REGBYTES(sp) // Store t5 - STORE x31, 13*REGBYTES(sp) // Store t6 - csrr t0, mepc // Load exception program counter - STORE t0, 30*REGBYTES(sp) // Save it on the stack - - /* Save floating point scratch registers. */ -#if defined(__riscv_float_abi_single) - fsw f0, 31*REGBYTES(sp) // Store ft0 - fsw f1, 32*REGBYTES(sp) // Store ft1 - fsw f2, 33*REGBYTES(sp) // Store ft2 - fsw f3, 34*REGBYTES(sp) // Store ft3 - fsw f4, 35*REGBYTES(sp) // Store ft4 - fsw f5, 36*REGBYTES(sp) // Store ft5 - fsw f6, 37*REGBYTES(sp) // Store ft6 - fsw f7, 38*REGBYTES(sp) // Store ft7 - fsw f10,41*REGBYTES(sp) // Store fa0 - fsw f11,42*REGBYTES(sp) // Store fa1 - fsw f12,43*REGBYTES(sp) // Store fa2 - fsw f13,44*REGBYTES(sp) // Store fa3 - fsw f14,45*REGBYTES(sp) // Store fa4 - fsw f15,46*REGBYTES(sp) // Store fa5 - fsw f16,47*REGBYTES(sp) // Store fa6 - fsw f17,48*REGBYTES(sp) // Store fa7 - fsw f28,59*REGBYTES(sp) // Store ft8 - fsw f29,60*REGBYTES(sp) // Store ft9 - fsw f30,61*REGBYTES(sp) // Store ft10 - fsw f31,62*REGBYTES(sp) // Store ft11 + sd t2, 17*8(sp) /* Store t2 */ + sd s0, 12*8(sp) /* Store s0 */ + sd a0, 27*8(sp) /* Store a0 */ + sd a1, 26*8(sp) /* Store a1 */ + sd a2, 25*8(sp) /* Store a2 */ + sd a3, 24*8(sp) /* Store a3 */ + sd a4, 23*8(sp) /* Store a4 */ + sd a5, 22*8(sp) /* Store a5 */ + sd a6, 21*8(sp) /* Store a6 */ + sd a7, 20*8(sp) /* Store a7 */ + sd t3, 16*8(sp) /* Store t3 */ + sd t4, 15*8(sp) /* Store t4 */ + sd t5, 14*8(sp) /* Store t5 */ + sd t6, 13*8(sp) /* Store t6 */ + csrr t0, mepc /* Load exception program counter */ + sd t0, 30*8(sp) /* Save it on the stack */ + + /* Save floating point scratch registers if floating point is enabled. */ +#ifdef __riscv_float_abi_single + fsw f0, 31*8(sp) /* Store ft0 */ + fsw f1, 32*8(sp) /* Store ft1 */ + fsw f2, 33*8(sp) /* Store ft2 */ + fsw f3, 34*8(sp) /* Store ft3 */ + fsw f4, 35*8(sp) /* Store ft4 */ + fsw f5, 36*8(sp) /* Store ft5 */ + fsw f6, 37*8(sp) /* Store ft6 */ + fsw f7, 38*8(sp) /* Store ft7 */ + fsw f10,41*8(sp) /* Store fa0 */ + fsw f11,42*8(sp) /* Store fa1 */ + fsw f12,43*8(sp) /* Store fa2 */ + fsw f13,44*8(sp) /* Store fa3 */ + fsw f14,45*8(sp) /* Store fa4 */ + fsw f15,46*8(sp) /* Store fa5 */ + fsw f16,47*8(sp) /* Store fa6 */ + fsw f17,48*8(sp) /* Store fa7 */ + fsw f28,59*8(sp) /* Store ft8 */ + fsw f29,60*8(sp) /* Store ft9 */ + fsw f30,61*8(sp) /* Store ft10 */ + fsw f31,62*8(sp) /* Store ft11 */ csrr t0, fcsr - STORE t0, 63*REGBYTES(sp) // Store fcsr + sd t0, 63*8(sp) /* Store fcsr */ #elif defined(__riscv_float_abi_double) - fsd f0, 31*REGBYTES(sp) // Store ft0 - fsd f1, 32*REGBYTES(sp) // Store ft1 - fsd f2, 33*REGBYTES(sp) // Store ft2 - fsd f3, 34*REGBYTES(sp) // Store ft3 - fsd f4, 35*REGBYTES(sp) // Store ft4 - fsd f5, 36*REGBYTES(sp) // Store ft5 - fsd f6, 37*REGBYTES(sp) // Store ft6 - fsd f7, 38*REGBYTES(sp) // Store ft7 - fsd f10,41*REGBYTES(sp) // Store fa0 - fsd f11,42*REGBYTES(sp) // Store fa1 - fsd f12,43*REGBYTES(sp) // Store fa2 - fsd f13,44*REGBYTES(sp) // Store fa3 - fsd f14,45*REGBYTES(sp) // Store fa4 - fsd f15,46*REGBYTES(sp) // Store fa5 - fsd f16,47*REGBYTES(sp) // Store fa6 - fsd f17,48*REGBYTES(sp) // Store fa7 - fsd f28,59*REGBYTES(sp) // Store ft8 - fsd f29,60*REGBYTES(sp) // Store ft9 - fsd f30,61*REGBYTES(sp) // Store ft10 - fsd f31,62*REGBYTES(sp) // Store ft11 + fsd f0, 31*8(sp) /* Store ft0 */ + fsd f1, 32*8(sp) /* Store ft1 */ + fsd f2, 33*8(sp) /* Store ft2 */ + fsd f3, 34*8(sp) /* Store ft3 */ + fsd f4, 35*8(sp) /* Store ft4 */ + fsd f5, 36*8(sp) /* Store ft5 */ + fsd f6, 37*8(sp) /* Store ft6 */ + fsd f7, 38*8(sp) /* Store ft7 */ + fsd f10,41*8(sp) /* Store fa0 */ + fsd f11,42*8(sp) /* Store fa1 */ + fsd f12,43*8(sp) /* Store fa2 */ + fsd f13,44*8(sp) /* Store fa3 */ + fsd f14,45*8(sp) /* Store fa4 */ + fsd f15,46*8(sp) /* Store fa5 */ + fsd f16,47*8(sp) /* Store fa6 */ + fsd f17,48*8(sp) /* Store fa7 */ + fsd f28,59*8(sp) /* Store ft8 */ + fsd f29,60*8(sp) /* Store ft9 */ + fsd f30,61*8(sp) /* Store ft10 */ + fsd f31,62*8(sp) /* Store ft11 */ csrr t0, fcsr - STORE t0, 63*REGBYTES(sp) // Store fcsr + sd t0, 63*8(sp) /* Store fcsr */ #endif #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY - call _tx_execution_isr_enter // Call the ISR execution enter function + call _tx_execution_isr_enter /* Call the ISR execution enter function */ #endif - ret // Return to calling ISR + ret /* Return to calling ISR */ _tx_thread_not_nested_save: /* } */ @@ -165,81 +163,159 @@ _tx_thread_not_nested_save: /* Otherwise, not nested, check to see if a thread was running. */ /* else if (_tx_thread_current_ptr) { */ - addi x6, x6, 1 // Increment the interrupt counter - STORE x6, 0(x5) // Store the interrupt counter + addi t1, t1, 1 /* Increment the interrupt counter */ + sd t1, 0(t0) /* Store the interrupt counter */ /* Not nested: Find the user thread that was running and load our SP */ - LOAD x5, _tx_thread_current_ptr // Pickup current thread pointer - beqz x5, _tx_thread_idle_system_save // If NULL, idle system was interrupted + la t0, _tx_thread_current_ptr /* Pickup current thread pointer address */ + ld t0, 0(t0) /* Pickup current thread pointer */ + beqz t0, _tx_thread_idle_system_save /* If NULL, idle system was interrupted */ /* Save the standard scratch registers. */ - STORE x7, 17*REGBYTES(sp) // Store t2 - STORE x8, 12*REGBYTES(sp) // Store s0 - STORE x10, 27*REGBYTES(sp) // Store a0 - STORE x11, 26*REGBYTES(sp) // Store a1 - STORE x12, 25*REGBYTES(sp) // Store a2 - STORE x13, 24*REGBYTES(sp) // Store a3 - STORE x14, 23*REGBYTES(sp) // Store a4 - STORE x15, 22*REGBYTES(sp) // Store a5 - STORE x16, 21*REGBYTES(sp) // Store a6 - STORE x17, 20*REGBYTES(sp) // Store a7 - STORE x28, 16*REGBYTES(sp) // Store t3 - STORE x29, 15*REGBYTES(sp) // Store t4 - STORE x30, 14*REGBYTES(sp) // Store t5 - STORE x31, 13*REGBYTES(sp) // Store t6 + sd t2, 17*8(sp) /* Store t2 */ + sd s0, 12*8(sp) /* Store s0 */ + sd a0, 27*8(sp) /* Store a0 */ + sd a1, 26*8(sp) /* Store a1 */ + sd a2, 25*8(sp) /* Store a2 */ + sd a3, 24*8(sp) /* Store a3 */ + sd a4, 23*8(sp) /* Store a4 */ + sd a5, 22*8(sp) /* Store a5 */ + sd a6, 21*8(sp) /* Store a6 */ + sd a7, 20*8(sp) /* Store a7 */ + sd t3, 16*8(sp) /* Store t3 */ + sd t4, 15*8(sp) /* Store t4 */ + sd t5, 14*8(sp) /* Store t5 */ + sd t6, 13*8(sp) /* Store t6 */ + + csrr t1, mepc /* Load exception program counter */ + sd t1, 30*8(sp) /* Save it on the stack */ + + /* Save floating point scratch registers if floating point is enabled. */ +#ifdef __riscv_float_abi_single + fsw f0, 31*8(sp) /* Store ft0 */ + fsw f1, 32*8(sp) /* Store ft1 */ + fsw f2, 33*8(sp) /* Store ft2 */ + fsw f3, 34*8(sp) /* Store ft3 */ + fsw f4, 35*8(sp) /* Store ft4 */ + fsw f5, 36*8(sp) /* Store ft5 */ + fsw f6, 37*8(sp) /* Store ft6 */ + fsw f7, 38*8(sp) /* Store ft7 */ + fsw f10,41*8(sp) /* Store fa0 */ + fsw f11,42*8(sp) /* Store fa1 */ + fsw f12,43*8(sp) /* Store fa2 */ + fsw f13,44*8(sp) /* Store fa3 */ + fsw f14,45*8(sp) /* Store fa4 */ + fsw f15,46*8(sp) /* Store fa5 */ + fsw f16,47*8(sp) /* Store fa6 */ + fsw f17,48*8(sp) /* Store fa7 */ + fsw f28,59*8(sp) /* Store ft8 */ + fsw f29,60*8(sp) /* Store ft9 */ + fsw f30,61*8(sp) /* Store ft10 */ + fsw f31,62*8(sp) /* Store ft11 */ + csrr t0, fcsr + sd t0, 63*8(sp) /* Store fcsr */ +#elif defined(__riscv_float_abi_double) + fsd f0, 31*8(sp) /* Store ft0 */ + fsd f1, 32*8(sp) /* Store ft1 */ + fsd f2, 33*8(sp) /* Store ft2 */ + fsd f3, 34*8(sp) /* Store ft3 */ + fsd f4, 35*8(sp) /* Store ft4 */ + fsd f5, 36*8(sp) /* Store ft5 */ + fsd f6, 37*8(sp) /* Store ft6 */ + fsd f7, 38*8(sp) /* Store ft7 */ + fsd f10,41*8(sp) /* Store fa0 */ + fsd f11,42*8(sp) /* Store fa1 */ + fsd f12,43*8(sp) /* Store fa2 */ + fsd f13,44*8(sp) /* Store fa3 */ + fsd f14,45*8(sp) /* Store fa4 */ + fsd f15,46*8(sp) /* Store fa5 */ + fsd f16,47*8(sp) /* Store fa6 */ + fsd f17,48*8(sp) /* Store fa7 */ + fsd f28,59*8(sp) /* Store ft8 */ + fsd f29,60*8(sp) /* Store ft9 */ + fsd f30,61*8(sp) /* Store ft10 */ + fsd f31,62*8(sp) /* Store ft11 */ + csrr t0, fcsr + sd t0, 63*8(sp) /* Store fcsr */ +#endif + + /* Save the current stack pointer in the thread's control block. */ + /* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; */ + + /* Switch to the system stack. */ + /* sp = _tx_thread_system_stack_ptr; */ + + la t1, _tx_thread_current_ptr /* Pickup current thread pointer address */ + ld t1, 0(t1) /* Pickup current thread pointer */ + sd sp, 16(t1) /* Save stack pointer */ + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + /* _tx_execution_isr_enter is called with thread stack pointer */ + call _tx_execution_isr_enter /* Call the ISR execution enter function */ +#endif + + la t0, _tx_thread_system_stack_ptr /* Pickup system stack pointer address */ + ld sp, 0(t0) /* Switch to system stack */ + ret /* Return to calling ISR */ + + sd x17, 20*8(sp) // Store a7 + sd x28, 16*8(sp) // Store t3 + sd x29, 15*8(sp) // Store t4 + sd x30, 14*8(sp) // Store t5 + sd x31, 13*8(sp) // Store t6 csrr t0, mepc // Load exception program counter - STORE t0, 30*REGBYTES(sp) // Save it on the stack + sd t0, 30*8(sp) // Save it on the stack /* Save floating point scratch registers. */ #if defined(__riscv_float_abi_single) - fsw f0, 31*REGBYTES(sp) // Store ft0 - fsw f1, 32*REGBYTES(sp) // Store ft1 - fsw f2, 33*REGBYTES(sp) // Store ft2 - fsw f3, 34*REGBYTES(sp) // Store ft3 - fsw f4, 35*REGBYTES(sp) // Store ft4 - fsw f5, 36*REGBYTES(sp) // Store ft5 - fsw f6, 37*REGBYTES(sp) // Store ft6 - fsw f7, 38*REGBYTES(sp) // Store ft7 - fsw f10,41*REGBYTES(sp) // Store fa0 - fsw f11,42*REGBYTES(sp) // Store fa1 - fsw f12,43*REGBYTES(sp) // Store fa2 - fsw f13,44*REGBYTES(sp) // Store fa3 - fsw f14,45*REGBYTES(sp) // Store fa4 - fsw f15,46*REGBYTES(sp) // Store fa5 - fsw f16,47*REGBYTES(sp) // Store fa6 - fsw f17,48*REGBYTES(sp) // Store fa7 - fsw f28,59*REGBYTES(sp) // Store ft8 - fsw f29,60*REGBYTES(sp) // Store ft9 - fsw f30,61*REGBYTES(sp) // Store ft10 - fsw f31,62*REGBYTES(sp) // Store ft11 + fsw f0, 31*8(sp) // Store ft0 + fsw f1, 32*8(sp) // Store ft1 + fsw f2, 33*8(sp) // Store ft2 + fsw f3, 34*8(sp) // Store ft3 + fsw f4, 35*8(sp) // Store ft4 + fsw f5, 36*8(sp) // Store ft5 + fsw f6, 37*8(sp) // Store ft6 + fsw f7, 38*8(sp) // Store ft7 + fsw f10,41*8(sp) // Store fa0 + fsw f11,42*8(sp) // Store fa1 + fsw f12,43*8(sp) // Store fa2 + fsw f13,44*8(sp) // Store fa3 + fsw f14,45*8(sp) // Store fa4 + fsw f15,46*8(sp) // Store fa5 + fsw f16,47*8(sp) // Store fa6 + fsw f17,48*8(sp) // Store fa7 + fsw f28,59*8(sp) // Store ft8 + fsw f29,60*8(sp) // Store ft9 + fsw f30,61*8(sp) // Store ft10 + fsw f31,62*8(sp) // Store ft11 csrr t0, fcsr - STORE t0, 63*REGBYTES(sp) // Store fcsr + sd t0, 63*8(sp) // Store fcsr #elif defined(__riscv_float_abi_double) - fsd f0, 31*REGBYTES(sp) // Store ft0 - fsd f1, 32*REGBYTES(sp) // Store ft1 - fsd f2, 33*REGBYTES(sp) // Store ft2 - fsd f3, 34*REGBYTES(sp) // Store ft3 - fsd f4, 35*REGBYTES(sp) // Store ft4 - fsd f5, 36*REGBYTES(sp) // Store ft5 - fsd f6, 37*REGBYTES(sp) // Store ft6 - fsd f7, 38*REGBYTES(sp) // Store ft7 - fsd f10,41*REGBYTES(sp) // Store fa0 - fsd f11,42*REGBYTES(sp) // Store fa1 - fsd f12,43*REGBYTES(sp) // Store fa2 - fsd f13,44*REGBYTES(sp) // Store fa3 - fsd f14,45*REGBYTES(sp) // Store fa4 - fsd f15,46*REGBYTES(sp) // Store fa5 - fsd f16,47*REGBYTES(sp) // Store fa6 - fsd f17,48*REGBYTES(sp) // Store fa7 - fsd f28,59*REGBYTES(sp) // Store ft8 - fsd f29,60*REGBYTES(sp) // Store ft9 - fsd f30,61*REGBYTES(sp) // Store ft10 - fsd f31,62*REGBYTES(sp) // Store ft11 + fsd f0, 31*8(sp) // Store ft0 + fsd f1, 32*8(sp) // Store ft1 + fsd f2, 33*8(sp) // Store ft2 + fsd f3, 34*8(sp) // Store ft3 + fsd f4, 35*8(sp) // Store ft4 + fsd f5, 36*8(sp) // Store ft5 + fsd f6, 37*8(sp) // Store ft6 + fsd f7, 38*8(sp) // Store ft7 + fsd f10,41*8(sp) // Store fa0 + fsd f11,42*8(sp) // Store fa1 + fsd f12,43*8(sp) // Store fa2 + fsd f13,44*8(sp) // Store fa3 + fsd f14,45*8(sp) // Store fa4 + fsd f15,46*8(sp) // Store fa5 + fsd f16,47*8(sp) // Store fa6 + fsd f17,48*8(sp) // Store fa7 + fsd f28,59*8(sp) // Store ft8 + fsd f29,60*8(sp) // Store ft9 + fsd f30,61*8(sp) // Store ft10 + fsd f31,62*8(sp) // Store ft11 csrr t0, fcsr - STORE t0, 63*REGBYTES(sp) // Store fcsr + sd t0, 63*8(sp) // Store fcsr #endif /* Save the current stack pointer in the thread's control block. */ @@ -248,8 +324,9 @@ _tx_thread_not_nested_save: /* Switch to the system stack. */ /* sp = _tx_thread_system_stack_ptr; */ - LOAD t1, _tx_thread_current_ptr // Pickup current thread pointer - STORE sp, 2*REGBYTES(t1) // Save stack pointer + la x5, _tx_thread_current_ptr // Pickup current thread pointer address + ld t1, 0(x5) // Pickup current thread pointer + sd sp, 16(t1) // Save stack pointer #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY /* _tx_execution_isr_enter is called with thread stack pointer */ @@ -257,7 +334,8 @@ _tx_thread_not_nested_save: #endif - LOAD sp, _tx_thread_system_stack_ptr // Switch to system stack + la x5, _tx_thread_system_stack_ptr // Pickup system stack pointer address + ld sp, 0(x5) // Switch to system stack ret // Return to calling ISR /* } @@ -276,8 +354,8 @@ _tx_thread_idle_system_save: /* } } */ #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 65*REGBYTES // Recover stack frame - with floating point enabled + addi sp, sp, 65*8 // Recover stack frame - with floating point enabled #else - addi sp, sp, 32*REGBYTES // Recover the reserved stack space + addi sp, sp, 32*8 // Recover the reserved stack space #endif ret // Return to calling ISR diff --git a/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S b/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S index c75c7c47d..a540ffdca 100644 --- a/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S +++ b/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S @@ -19,8 +19,6 @@ /**************************************************************************/ /**************************************************************************/ - RETURN_MASK = 0x000000000000000F - SET_SR_MASK = 0xFFFFFFFFFFFFFFF0 .section .text /**************************************************************************/ @@ -66,16 +64,20 @@ .global _tx_thread_interrupt_control _tx_thread_interrupt_control: /* Pickup current interrupt lockout posture. */ + /* old_mstatus = mstatus; */ csrr t0, mstatus - mv t1, t0 // Save original mstatus for return + mv t1, t0 /* Save original mstatus for return */ - /* Apply the new interrupt posture. */ - - li t2, SET_SR_MASK // Build set SR mask - and t0, t0, t2 // Isolate interrupt lockout bits - or t0, t0, a0 // Put new lockout bits in + /* Apply the new interrupt posture while preserving unrelated mstatus bits. */ + /* Only modify the MIE bit (bit 3) */ + /* mstatus = (mstatus & ~MIE) | (new_posture & MIE); */ + + li t2, ~0x08 /* Build mask to clear MIE */ + and t0, t0, t2 /* Clear MIE bit */ + and a0, a0, 0x08 /* Mask incoming to only MIE bit */ + or t0, t0, a0 /* Set requested MIE state */ csrw mstatus, t0 - andi a0, t1, RETURN_MASK // Return original mstatus. + andi a0, t1, 0x08 /* Return original MIE bit */ ret /* } */ diff --git a/ports/risc-v64/gnu/src/tx_thread_schedule.S b/ports/risc-v64/gnu/src/tx_thread_schedule.S index c9be4c6f2..52f865c25 100644 --- a/ports/risc-v64/gnu/src/tx_thread_schedule.S +++ b/ports/risc-v64/gnu/src/tx_thread_schedule.S @@ -19,8 +19,6 @@ /**************************************************************************/ /**************************************************************************/ -#include "tx_port.h" - .section .text /**************************************************************************/ /* */ @@ -69,236 +67,253 @@ _tx_thread_schedule: /* Enable interrupts. */ - csrsi mstatus, 0x08 // Enable interrupts + csrsi mstatus, 0x08 /* Enable interrupts (MIE bit 3) */ /* Wait for a thread to execute. */ /* do { */ - la t0, _tx_thread_execute_ptr // Pickup address of execute ptr + la t0, _tx_thread_execute_ptr /* Pickup address of execute ptr */ _tx_thread_schedule_loop: - LOAD t1, 0(t0) // Pickup next thread to execute - beqz t1, _tx_thread_schedule_loop // If NULL, wait for thread to execute + ld t1, 0(t0) /* Pickup next thread to execute */ + +/* TX_USE_WFI_IDLE Configuration: + When defined, the scheduler enters WFI (Wait-For-Interrupt) mode when + no threads are ready, reducing power consumption. The core will wake + on any enabled interrupt. This is recommended for battery-powered or + low-power applications. Define TX_USE_WFI_IDLE in tx_user.h or via + compiler flags to enable this feature. */ +#ifdef TX_USE_WFI_IDLE + beqz t1, 1f + j 2f +1: wfi + j _tx_thread_schedule_loop +2: + beqz t1, _tx_thread_schedule_loop /* Fallback: If still NULL, loop */ +#else + beqz t1, _tx_thread_schedule_loop /* If NULL, wait for thread to execute */ +#endif /* } - while(_tx_thread_execute_ptr == TX_NULL); */ + while(_tx_thread_execute_ptr == NULL); */ /* Yes! We have a thread to execute. Lockout interrupts and transfer control to it. */ - csrci mstatus, 0x08 // Lockout interrupts + csrci mstatus, 0x08 /* Lockout interrupts */ /* Setup the current thread pointer. */ /* _tx_thread_current_ptr = _tx_thread_execute_ptr; */ - la t0, _tx_thread_current_ptr // Pickup current thread pointer address - STORE t1, 0(t0) // Set current thread pointer + la t0, _tx_thread_current_ptr /* Pickup current thread pointer address */ + sd t1, 0(t0) /* Set current thread pointer */ /* Increment the run count for this thread. */ /* _tx_thread_current_ptr -> tx_thread_run_count++; */ - LOAD t2, 1*REGBYTES(t1) // Pickup run count - LOAD t3, 6*REGBYTES(t1) // Pickup time slice value - addi t2, t2, 1 // Increment run count - STORE t2, 1*REGBYTES(t1) // Store new run count + ld t2, 8(t1) /* Pickup run count */ + ld t3, 48(t1) /* Pickup time slice value */ + addi t2, t2, 1 /* Increment run count */ + sd t2, 8(t1) /* Store new run count */ /* Setup time-slice, if present. */ /* _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice; */ - la t2, _tx_timer_time_slice // Pickup time-slice variable address + la t2, _tx_timer_time_slice /* Pickup time-slice variable address */ /* Switch to the thread's stack. */ /* SP = _tx_thread_execute_ptr -> tx_thread_stack_ptr; */ - LOAD sp, 2*REGBYTES(t1) // Switch to thread's stack - STORE t3, 0(t2) // Store new time-slice*/ + ld sp, 16(t1) /* Switch to thread's stack */ + sd t3, 0(t2) /* Store new time-slice*/ #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY - call _tx_execution_thread_enter // Call the thread execution enter function + call _tx_execution_thread_enter /* Call the thread execution enter function */ #endif /* Determine if an interrupt frame or a synchronous task suspension frame is present. */ - LOAD t2, 0(sp) // Pickup stack type - beqz t2, _tx_thread_synch_return // If 0, solicited thread return + ld t2, 0(sp) /* Pickup stack type */ + beqz t2, _tx_thread_synch_return /* If 0, solicited thread return */ /* Determine if floating point registers need to be recovered. */ #if defined(__riscv_float_abi_single) - flw f0, 31*REGBYTES(sp) // Recover ft0 - flw f1, 32*REGBYTES(sp) // Recover ft1 - flw f2, 33*REGBYTES(sp) // Recover ft2 - flw f3, 34*REGBYTES(sp) // Recover ft3 - flw f4, 35*REGBYTES(sp) // Recover ft4 - flw f5, 36*REGBYTES(sp) // Recover ft5 - flw f6, 37*REGBYTES(sp) // Recover ft6 - flw f7, 38*REGBYTES(sp) // Recover ft7 - flw f8, 39*REGBYTES(sp) // Recover fs0 - flw f9, 40*REGBYTES(sp) // Recover fs1 - flw f10,41*REGBYTES(sp) // Recover fa0 - flw f11,42*REGBYTES(sp) // Recover fa1 - flw f12,43*REGBYTES(sp) // Recover fa2 - flw f13,44*REGBYTES(sp) // Recover fa3 - flw f14,45*REGBYTES(sp) // Recover fa4 - flw f15,46*REGBYTES(sp) // Recover fa5 - flw f16,47*REGBYTES(sp) // Recover fa6 - flw f17,48*REGBYTES(sp) // Recover fa7 - flw f18,49*REGBYTES(sp) // Recover fs2 - flw f19,50*REGBYTES(sp) // Recover fs3 - flw f20,51*REGBYTES(sp) // Recover fs4 - flw f21,52*REGBYTES(sp) // Recover fs5 - flw f22,53*REGBYTES(sp) // Recover fs6 - flw f23,54*REGBYTES(sp) // Recover fs7 - flw f24,55*REGBYTES(sp) // Recover fs8 - flw f25,56*REGBYTES(sp) // Recover fs9 - flw f26,57*REGBYTES(sp) // Recover fs10 - flw f27,58*REGBYTES(sp) // Recover fs11 - flw f28,59*REGBYTES(sp) // Recover ft8 - flw f29,60*REGBYTES(sp) // Recover ft9 - flw f30,61*REGBYTES(sp) // Recover ft10 - flw f31,62*REGBYTES(sp) // Recover ft11 - LOAD t0, 63*REGBYTES(sp) // Recover fcsr - csrw fcsr, t0 // + flw f0, 31*8(sp) /* Recover ft0 */ + flw f1, 32*8(sp) /* Recover ft1 */ + flw f2, 33*8(sp) /* Recover ft2 */ + flw f3, 34*8(sp) /* Recover ft3 */ + flw f4, 35*8(sp) /* Recover ft4 */ + flw f5, 36*8(sp) /* Recover ft5 */ + flw f6, 37*8(sp) /* Recover ft6 */ + flw f7, 38*8(sp) /* Recover ft7 */ + flw f8, 39*8(sp) /* Recover fs0 */ + flw f9, 40*8(sp) /* Recover fs1 */ + flw f10,41*8(sp) /* Recover fa0 */ + flw f11,42*8(sp) /* Recover fa1 */ + flw f12,43*8(sp) /* Recover fa2 */ + flw f13,44*8(sp) /* Recover fa3 */ + flw f14,45*8(sp) /* Recover fa4 */ + flw f15,46*8(sp) /* Recover fa5 */ + flw f16,47*8(sp) /* Recover fa6 */ + flw f17,48*8(sp) /* Recover fa7 */ + flw f18,49*8(sp) /* Recover fs2 */ + flw f19,50*8(sp) /* Recover fs3 */ + flw f20,51*8(sp) /* Recover fs4 */ + flw f21,52*8(sp) /* Recover fs5 */ + flw f22,53*8(sp) /* Recover fs6 */ + flw f23,54*8(sp) /* Recover fs7 */ + flw f24,55*8(sp) /* Recover fs8 */ + flw f25,56*8(sp) /* Recover fs9 */ + flw f26,57*8(sp) /* Recover fs10 */ + flw f27,58*8(sp) /* Recover fs11 */ + flw f28,59*8(sp) /* Recover ft8 */ + flw f29,60*8(sp) /* Recover ft9 */ + flw f30,61*8(sp) /* Recover ft10 */ + flw f31,62*8(sp) /* Recover ft11 */ + ld t0, 63*8(sp) /* Recover fcsr */ + csrw fcsr, t0 /* Restore fcsr */ #elif defined(__riscv_float_abi_double) - fld f0, 31*REGBYTES(sp) // Recover ft0 - fld f1, 32*REGBYTES(sp) // Recover ft1 - fld f2, 33*REGBYTES(sp) // Recover ft2 - fld f3, 34*REGBYTES(sp) // Recover ft3 - fld f4, 35*REGBYTES(sp) // Recover ft4 - fld f5, 36*REGBYTES(sp) // Recover ft5 - fld f6, 37*REGBYTES(sp) // Recover ft6 - fld f7, 38*REGBYTES(sp) // Recover ft7 - fld f8, 39*REGBYTES(sp) // Recover fs0 - fld f9, 40*REGBYTES(sp) // Recover fs1 - fld f10,41*REGBYTES(sp) // Recover fa0 - fld f11,42*REGBYTES(sp) // Recover fa1 - fld f12,43*REGBYTES(sp) // Recover fa2 - fld f13,44*REGBYTES(sp) // Recover fa3 - fld f14,45*REGBYTES(sp) // Recover fa4 - fld f15,46*REGBYTES(sp) // Recover fa5 - fld f16,47*REGBYTES(sp) // Recover fa6 - fld f17,48*REGBYTES(sp) // Recover fa7 - fld f18,49*REGBYTES(sp) // Recover fs2 - fld f19,50*REGBYTES(sp) // Recover fs3 - fld f20,51*REGBYTES(sp) // Recover fs4 - fld f21,52*REGBYTES(sp) // Recover fs5 - fld f22,53*REGBYTES(sp) // Recover fs6 - fld f23,54*REGBYTES(sp) // Recover fs7 - fld f24,55*REGBYTES(sp) // Recover fs8 - fld f25,56*REGBYTES(sp) // Recover fs9 - fld f26,57*REGBYTES(sp) // Recover fs10 - fld f27,58*REGBYTES(sp) // Recover fs11 - fld f28,59*REGBYTES(sp) // Recover ft8 - fld f29,60*REGBYTES(sp) // Recover ft9 - fld f30,61*REGBYTES(sp) // Recover ft10 - fld f31,62*REGBYTES(sp) // Recover ft11 - LOAD t0, 63*REGBYTES(sp) // Recover fcsr + fld f0, 31*8(sp) // Recover ft0 + fld f1, 32*8(sp) // Recover ft1 + fld f2, 33*8(sp) // Recover ft2 + fld f3, 34*8(sp) // Recover ft3 + fld f4, 35*8(sp) // Recover ft4 + fld f5, 36*8(sp) // Recover ft5 + fld f6, 37*8(sp) // Recover ft6 + fld f7, 38*8(sp) // Recover ft7 + fld f8, 39*8(sp) // Recover fs0 + fld f9, 40*8(sp) // Recover fs1 + fld f10,41*8(sp) // Recover fa0 + fld f11,42*8(sp) // Recover fa1 + fld f12,43*8(sp) // Recover fa2 + fld f13,44*8(sp) // Recover fa3 + fld f14,45*8(sp) // Recover fa4 + fld f15,46*8(sp) // Recover fa5 + fld f16,47*8(sp) // Recover fa6 + fld f17,48*8(sp) // Recover fa7 + fld f18,49*8(sp) // Recover fs2 + fld f19,50*8(sp) // Recover fs3 + fld f20,51*8(sp) // Recover fs4 + fld f21,52*8(sp) // Recover fs5 + fld f22,53*8(sp) // Recover fs6 + fld f23,54*8(sp) // Recover fs7 + fld f24,55*8(sp) // Recover fs8 + fld f25,56*8(sp) // Recover fs9 + fld f26,57*8(sp) // Recover fs10 + fld f27,58*8(sp) // Recover fs11 + fld f28,59*8(sp) // Recover ft8 + fld f29,60*8(sp) // Recover ft9 + fld f30,61*8(sp) // Recover ft10 + fld f31,62*8(sp) // Recover ft11 + ld t0, 63*8(sp) // Recover fcsr + csrw fcsr, t0 // #endif /* Recover standard registers. */ - LOAD t0, 30*REGBYTES(sp) // Recover mepc - csrw mepc, t0 // Store mepc - li t0, 0x1880 // Prepare MPIP + ld t0, 30*8(sp) /* Recover mepc */ + csrw mepc, t0 /* Store mepc */ + li t0, 0x1880 /* Prepare mstatus: MPP=Machine(0x1800) | MPIE(0x80) */ #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - li t1, 1<<13 - or t0, t1, t0 + li t1, 0x2000 /* Set FS bits for FP state */ + or t0, t0, t1 #endif - csrw mstatus, t0 // Enable MPIP - - LOAD x1, 28*REGBYTES(sp) // Recover RA - LOAD x5, 19*REGBYTES(sp) // Recover t0 - LOAD x6, 18*REGBYTES(sp) // Recover t1 - LOAD x7, 17*REGBYTES(sp) // Recover t2 - LOAD x8, 12*REGBYTES(sp) // Recover s0 - LOAD x9, 11*REGBYTES(sp) // Recover s1 - LOAD x10, 27*REGBYTES(sp) // Recover a0 - LOAD x11, 26*REGBYTES(sp) // Recover a1 - LOAD x12, 25*REGBYTES(sp) // Recover a2 - LOAD x13, 24*REGBYTES(sp) // Recover a3 - LOAD x14, 23*REGBYTES(sp) // Recover a4 - LOAD x15, 22*REGBYTES(sp) // Recover a5 - LOAD x16, 21*REGBYTES(sp) // Recover a6 - LOAD x17, 20*REGBYTES(sp) // Recover a7 - LOAD x18, 10*REGBYTES(sp) // Recover s2 - LOAD x19, 9*REGBYTES(sp) // Recover s3 - LOAD x20, 8*REGBYTES(sp) // Recover s4 - LOAD x21, 7*REGBYTES(sp) // Recover s5 - LOAD x22, 6*REGBYTES(sp) // Recover s6 - LOAD x23, 5*REGBYTES(sp) // Recover s7 - LOAD x24, 4*REGBYTES(sp) // Recover s8 - LOAD x25, 3*REGBYTES(sp) // Recover s9 - LOAD x26, 2*REGBYTES(sp) // Recover s10 - LOAD x27, 1*REGBYTES(sp) // Recover s11 - LOAD x28, 16*REGBYTES(sp) // Recover t3 - LOAD x29, 15*REGBYTES(sp) // Recover t4 - LOAD x30, 14*REGBYTES(sp) // Recover t5 - LOAD x31, 13*REGBYTES(sp) // Recover t6 + csrw mstatus, t0 /* Set mstatus */ + + ld ra, 28*8(sp) /* Recover return address */ + ld t0, 19*8(sp) /* Recover t0 */ + ld t1, 18*8(sp) /* Recover t1 */ + ld t2, 17*8(sp) /* Recover t2 */ + ld s0, 12*8(sp) /* Recover s0 */ + ld s1, 11*8(sp) /* Recover s1 */ + ld a0, 27*8(sp) /* Recover a0 */ + ld a1, 26*8(sp) /* Recover a1 */ + ld a2, 25*8(sp) /* Recover a2 */ + ld a3, 24*8(sp) /* Recover a3 */ + ld a4, 23*8(sp) /* Recover a4 */ + ld a5, 22*8(sp) /* Recover a5 */ + ld a6, 21*8(sp) /* Recover a6 */ + ld a7, 20*8(sp) /* Recover a7 */ + ld s2, 10*8(sp) /* Recover s2 */ + ld s3, 9*8(sp) /* Recover s3 */ + ld s4, 8*8(sp) /* Recover s4 */ + ld s5, 7*8(sp) /* Recover s5 */ + ld s6, 6*8(sp) /* Recover s6 */ + ld s7, 5*8(sp) /* Recover s7 */ + ld s8, 4*8(sp) /* Recover s8 */ + ld s9, 3*8(sp) /* Recover s9 */ + ld s10, 2*8(sp) /* Recover s10 */ + ld s11, 1*8(sp) /* Recover s11 */ + ld t3, 16*8(sp) /* Recover t3 */ + ld t4, 15*8(sp) /* Recover t4 */ + ld t5, 14*8(sp) /* Recover t5 */ + ld t6, 13*8(sp) /* Recover t6 */ #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 65*REGBYTES // Recover stack frame - with floating point registers + addi sp, sp, 65*8 // Recover stack frame - with floating point registers #else - addi sp, sp, 32*REGBYTES // Recover stack frame - without floating point registers + addi sp, sp, 32*8 // Recover stack frame - without floating point registers #endif mret // Return to point of interrupt _tx_thread_synch_return: #if defined(__riscv_float_abi_single) - flw f8, 15*REGBYTES(sp) // Recover fs0 - flw f9, 16*REGBYTES(sp) // Recover fs1 - flw f18,17*REGBYTES(sp) // Recover fs2 - flw f19,18*REGBYTES(sp) // Recover fs3 - flw f20,19*REGBYTES(sp) // Recover fs4 - flw f21,20*REGBYTES(sp) // Recover fs5 - flw f22,21*REGBYTES(sp) // Recover fs6 - flw f23,22*REGBYTES(sp) // Recover fs7 - flw f24,23*REGBYTES(sp) // Recover fs8 - flw f25,24*REGBYTES(sp) // Recover fs9 - flw f26,25*REGBYTES(sp) // Recover fs10 - flw f27,26*REGBYTES(sp) // Recover fs11 - LOAD t0, 27*REGBYTES(sp) // Recover fcsr + flw f8, 15*8(sp) // Recover fs0 + flw f9, 16*8(sp) // Recover fs1 + flw f18,17*8(sp) // Recover fs2 + flw f19,18*8(sp) // Recover fs3 + flw f20,19*8(sp) // Recover fs4 + flw f21,20*8(sp) // Recover fs5 + flw f22,21*8(sp) // Recover fs6 + flw f23,22*8(sp) // Recover fs7 + flw f24,23*8(sp) // Recover fs8 + flw f25,24*8(sp) // Recover fs9 + flw f26,25*8(sp) // Recover fs10 + flw f27,26*8(sp) // Recover fs11 + ld t0, 27*8(sp) // Recover fcsr csrw fcsr, t0 // #elif defined(__riscv_float_abi_double) - fld f8, 15*REGBYTES(sp) // Recover fs0 - fld f9, 16*REGBYTES(sp) // Recover fs1 - fld f18,17*REGBYTES(sp) // Recover fs2 - fld f19,18*REGBYTES(sp) // Recover fs3 - fld f20,19*REGBYTES(sp) // Recover fs4 - fld f21,20*REGBYTES(sp) // Recover fs5 - fld f22,21*REGBYTES(sp) // Recover fs6 - fld f23,22*REGBYTES(sp) // Recover fs7 - fld f24,23*REGBYTES(sp) // Recover fs8 - fld f25,24*REGBYTES(sp) // Recover fs9 - fld f26,25*REGBYTES(sp) // Recover fs10 - fld f27,26*REGBYTES(sp) // Recover fs11 - LOAD t0, 27*REGBYTES(sp) // Recover fcsr + fld f8, 15*8(sp) // Recover fs0 + fld f9, 16*8(sp) // Recover fs1 + fld f18,17*8(sp) // Recover fs2 + fld f19,18*8(sp) // Recover fs3 + fld f20,19*8(sp) // Recover fs4 + fld f21,20*8(sp) // Recover fs5 + fld f22,21*8(sp) // Recover fs6 + fld f23,22*8(sp) // Recover fs7 + fld f24,23*8(sp) // Recover fs8 + fld f25,24*8(sp) // Recover fs9 + fld f26,25*8(sp) // Recover fs10 + fld f27,26*8(sp) // Recover fs11 + ld t0, 27*8(sp) // Recover fcsr csrw fcsr, t0 // #endif /* Recover standard preserved registers. */ /* Recover standard registers. */ - LOAD x1, 13*REGBYTES(sp) // Recover RA - LOAD x8, 12*REGBYTES(sp) // Recover s0 - LOAD x9, 11*REGBYTES(sp) // Recover s1 - LOAD x18, 10*REGBYTES(sp) // Recover s2 - LOAD x19, 9*REGBYTES(sp) // Recover s3 - LOAD x20, 8*REGBYTES(sp) // Recover s4 - LOAD x21, 7*REGBYTES(sp) // Recover s5 - LOAD x22, 6*REGBYTES(sp) // Recover s6 - LOAD x23, 5*REGBYTES(sp) // Recover s7 - LOAD x24, 4*REGBYTES(sp) // Recover s8 - LOAD x25, 3*REGBYTES(sp) // Recover s9 - LOAD x26, 2*REGBYTES(sp) // Recover s10 - LOAD x27, 1*REGBYTES(sp) // Recover s11 - LOAD t0, 14*REGBYTES(sp) // Recover mstatus - csrw mstatus, t0 // Store mstatus, enables interrupt + ld ra, 13*8(sp) /* Recover RA */ + ld s0, 12*8(sp) /* Recover s0 */ + ld s1, 11*8(sp) /* Recover s1 */ + ld s2, 10*8(sp) /* Recover s2 */ + ld s3, 9*8(sp) /* Recover s3 */ + ld s4, 8*8(sp) /* Recover s4 */ + ld s5, 7*8(sp) /* Recover s5 */ + ld s6, 6*8(sp) /* Recover s6 */ + ld s7, 5*8(sp) /* Recover s7 */ + ld s8, 4*8(sp) /* Recover s8 */ + ld s9, 3*8(sp) /* Recover s9 */ + ld s10, 2*8(sp) /* Recover s10 */ + ld s11, 1*8(sp) /* Recover s11 */ + ld t0, 14*8(sp) /* Recover mstatus */ + csrw mstatus, t0 /* Store mstatus, enables interrupt */ #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 29*REGBYTES // Recover stack frame + addi sp, sp, 29*8 // Recover stack frame #else - addi sp, sp, 16*REGBYTES // Recover stack frame + addi sp, sp, 16*8 // Recover stack frame #endif ret // Return to thread diff --git a/ports/risc-v64/gnu/src/tx_thread_stack_build.S b/ports/risc-v64/gnu/src/tx_thread_stack_build.S index 34d807eeb..a8b32a91e 100644 --- a/ports/risc-v64/gnu/src/tx_thread_stack_build.S +++ b/ports/risc-v64/gnu/src/tx_thread_stack_build.S @@ -19,8 +19,6 @@ /**************************************************************************/ /**************************************************************************/ -#include "tx_port.h" - .section .text /**************************************************************************/ /* */ @@ -43,7 +41,7 @@ /* thread_ptr Pointer to thread control blk */ /* function_ptr Pointer to return function */ /* */ -/* OUTPUT */ +/* OUTPUT */ /* */ /* None */ /* */ @@ -138,91 +136,91 @@ If floating point support: Stack Bottom: (higher memory address) */ - LOAD t0, 4*REGBYTES(a0) // Pickup end of stack area - li t1, ~15 // Build 16-byte alignment mask - and t0, t0, t1 // Make sure 16-byte alignment + ld t0, 32(a0) /* Pickup end of stack area */ + li t1, ~15 /* Build 16-byte alignment mask */ + and t0, t0, t1 /* Make sure 16-byte alignment */ /* Actually build the stack frame. */ #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi t0, t0, -65*REGBYTES + addi t0, t0, -65*8 #else - addi t0, t0, -32*REGBYTES // Allocate space for the stack frame + addi t0, t0, -32*8 /* Allocate space for the stack frame */ #endif - li t1, 1 // Build stack type - STORE t1, 0*REGBYTES(t0) // Place stack type on the top - STORE x0, 1*REGBYTES(t0) // Initial s11 - STORE x0, 2*REGBYTES(t0) // Initial s10 - STORE x0, 3*REGBYTES(t0) // Initial s9 - STORE x0, 4*REGBYTES(t0) // Initial s8 - STORE x0, 5*REGBYTES(t0) // Initial s7 - STORE x0, 6*REGBYTES(t0) // Initial s6 - STORE x0, 7*REGBYTES(t0) // Initial s5 - STORE x0, 8*REGBYTES(t0) // Initial s4 - STORE x0, 9*REGBYTES(t0) // Initial s3 - STORE x0, 10*REGBYTES(t0) // Initial s2 - STORE x0, 11*REGBYTES(t0) // Initial s1 - STORE x0, 12*REGBYTES(t0) // Initial s0 - STORE x0, 13*REGBYTES(t0) // Initial t6 - STORE x0, 14*REGBYTES(t0) // Initial t5 - STORE x0, 15*REGBYTES(t0) // Initial t4 - STORE x0, 16*REGBYTES(t0) // Initial t3 - STORE x0, 17*REGBYTES(t0) // Initial t2 - STORE x0, 18*REGBYTES(t0) // Initial t1 - STORE x0, 19*REGBYTES(t0) // Initial t0 - STORE x0, 20*REGBYTES(t0) // Initial a7 - STORE x0, 21*REGBYTES(t0) // Initial a6 - STORE x0, 22*REGBYTES(t0) // Initial a5 - STORE x0, 23*REGBYTES(t0) // Initial a4 - STORE x0, 24*REGBYTES(t0) // Initial a3 - STORE x0, 25*REGBYTES(t0) // Initial a2 - STORE x0, 26*REGBYTES(t0) // Initial a1 - STORE x0, 27*REGBYTES(t0) // Initial a0 - STORE x0, 28*REGBYTES(t0) // Initial ra - STORE a1, 30*REGBYTES(t0) // Initial mepc + li t1, 1 /* Build stack type */ + sd t1, 0*8(t0) /* Place stack type on the top */ + sd zero, 1*8(t0) /* Initial s11 */ + sd zero, 2*8(t0) /* Initial s10 */ + sd zero, 3*8(t0) /* Initial s9 */ + sd zero, 4*8(t0) /* Initial s8 */ + sd zero, 5*8(t0) /* Initial s7 */ + sd zero, 6*8(t0) /* Initial s6 */ + sd zero, 7*8(t0) /* Initial s5 */ + sd zero, 8*8(t0) /* Initial s4 */ + sd zero, 9*8(t0) /* Initial s3 */ + sd zero, 10*8(t0) /* Initial s2 */ + sd zero, 11*8(t0) /* Initial s1 */ + sd zero, 12*8(t0) /* Initial s0 */ + sd zero, 13*8(t0) /* Initial t6 */ + sd zero, 14*8(t0) /* Initial t5 */ + sd zero, 15*8(t0) /* Initial t4 */ + sd zero, 16*8(t0) /* Initial t3 */ + sd zero, 17*8(t0) /* Initial t2 */ + sd zero, 18*8(t0) /* Initial t1 */ + sd zero, 19*8(t0) /* Initial t0 */ + sd zero, 20*8(t0) /* Initial a7 */ + sd zero, 21*8(t0) /* Initial a6 */ + sd zero, 22*8(t0) /* Initial a5 */ + sd zero, 23*8(t0) /* Initial a4 */ + sd zero, 24*8(t0) /* Initial a3 */ + sd zero, 25*8(t0) /* Initial a2 */ + sd zero, 26*8(t0) /* Initial a1 */ + sd zero, 27*8(t0) /* Initial a0 */ + sd zero, 28*8(t0) /* Initial ra */ + sd a1, 30*8(t0) /* Initial mepc (thread entry point) */ #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - STORE x0, 31*REGBYTES(t0) // Inital ft0 - STORE x0, 32*REGBYTES(t0) // Inital ft1 - STORE x0, 33*REGBYTES(t0) // Inital ft2 - STORE x0, 34*REGBYTES(t0) // Inital ft3 - STORE x0, 35*REGBYTES(t0) // Inital ft4 - STORE x0, 36*REGBYTES(t0) // Inital ft5 - STORE x0, 37*REGBYTES(t0) // Inital ft6 - STORE x0, 38*REGBYTES(t0) // Inital ft7 - STORE x0, 39*REGBYTES(t0) // Inital fs0 - STORE x0, 40*REGBYTES(t0) // Inital fs1 - STORE x0, 41*REGBYTES(t0) // Inital fa0 - STORE x0, 42*REGBYTES(t0) // Inital fa1 - STORE x0, 43*REGBYTES(t0) // Inital fa2 - STORE x0, 44*REGBYTES(t0) // Inital fa3 - STORE x0, 45*REGBYTES(t0) // Inital fa4 - STORE x0, 46*REGBYTES(t0) // Inital fa5 - STORE x0, 47*REGBYTES(t0) // Inital fa6 - STORE x0, 48*REGBYTES(t0) // Inital fa7 - STORE x0, 49*REGBYTES(t0) // Inital fs2 - STORE x0, 50*REGBYTES(t0) // Inital fs3 - STORE x0, 51*REGBYTES(t0) // Inital fs4 - STORE x0, 52*REGBYTES(t0) // Inital fs5 - STORE x0, 53*REGBYTES(t0) // Inital fs6 - STORE x0, 54*REGBYTES(t0) // Inital fs7 - STORE x0, 55*REGBYTES(t0) // Inital fs8 - STORE x0, 56*REGBYTES(t0) // Inital fs9 - STORE x0, 57*REGBYTES(t0) // Inital fs10 - STORE x0, 58*REGBYTES(t0) // Inital fs11 - STORE x0, 59*REGBYTES(t0) // Inital ft8 - STORE x0, 60*REGBYTES(t0) // Inital ft9 - STORE x0, 61*REGBYTES(t0) // Inital ft10 - STORE x0, 62*REGBYTES(t0) // Inital ft11 - csrr a1, fcsr // Read fcsr and use it for initial value for each thread - STORE a1, 63*REGBYTES(t0) // Initial fscr - STORE x0, 64*REGBYTES(t0) // Reserved word (0) + sd zero, 31*8(t0) /* Initial ft0 */ + sd zero, 32*8(t0) /* Initial ft1 */ + sd zero, 33*8(t0) /* Initial ft2 */ + sd zero, 34*8(t0) /* Initial ft3 */ + sd zero, 35*8(t0) /* Initial ft4 */ + sd zero, 36*8(t0) /* Initial ft5 */ + sd zero, 37*8(t0) /* Initial ft6 */ + sd zero, 38*8(t0) /* Initial ft7 */ + sd zero, 39*8(t0) /* Initial fs0 */ + sd zero, 40*8(t0) /* Initial fs1 */ + sd zero, 41*8(t0) /* Initial fa0 */ + sd zero, 42*8(t0) /* Initial fa1 */ + sd zero, 43*8(t0) /* Initial fa2 */ + sd zero, 44*8(t0) /* Initial fa3 */ + sd zero, 45*8(t0) /* Initial fa4 */ + sd zero, 46*8(t0) /* Initial fa5 */ + sd zero, 47*8(t0) /* Initial fa6 */ + sd zero, 48*8(t0) /* Initial fa7 */ + sd zero, 49*8(t0) /* Initial fs2 */ + sd zero, 50*8(t0) /* Initial fs3 */ + sd zero, 51*8(t0) /* Initial fs4 */ + sd zero, 52*8(t0) /* Initial fs5 */ + sd zero, 53*8(t0) /* Initial fs6 */ + sd zero, 54*8(t0) /* Initial fs7 */ + sd zero, 55*8(t0) /* Initial fs8 */ + sd zero, 56*8(t0) /* Initial fs9 */ + sd zero, 57*8(t0) /* Initial fs10 */ + sd zero, 58*8(t0) /* Initial fs11 */ + sd zero, 59*8(t0) /* Initial ft8 */ + sd zero, 60*8(t0) /* Initial ft9 */ + sd zero, 61*8(t0) /* Initial ft10 */ + sd zero, 62*8(t0) /* Initial ft11 */ + csrr a1, fcsr /* Read fcsr for initial value */ + sd a1, 63*8(t0) /* Initial fcsr */ + sd zero, 64*8(t0) /* Reserved word (0) */ #else - STORE x0, 31*REGBYTES(t0) // Reserved word (0) + sd zero, 31*8(t0) /* Reserved word (0) */ #endif /* Setup stack pointer. */ /* thread_ptr -> tx_thread_stack_ptr = t0; */ - STORE t0, 2*REGBYTES(a0) // Save stack pointer in thread's - ret // control block and return + sd t0, 16(a0) /* Save stack pointer in thread's */ + ret /* control block and return */ /* } */ diff --git a/ports/risc-v64/gnu/src/tx_thread_system_return.S b/ports/risc-v64/gnu/src/tx_thread_system_return.S index 3da67ffbc..2e698a62a 100644 --- a/ports/risc-v64/gnu/src/tx_thread_system_return.S +++ b/ports/risc-v64/gnu/src/tx_thread_system_return.S @@ -19,8 +19,6 @@ /**************************************************************************/ /**************************************************************************/ -#include "tx_port.h" - .section .text /**************************************************************************/ /* */ @@ -68,99 +66,100 @@ _tx_thread_system_return: /* Save minimal context on the stack. */ + /* sp -= sizeof(stack_frame); */ #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, -29*REGBYTES // Allocate space on the stack - with floating point enabled + addi sp, sp, -29*8 /* Allocate space on the stack - with floating point enabled */ #else - addi sp, sp, -16*REGBYTES // Allocate space on the stack - without floating point enabled + addi sp, sp, -16*8 /* Allocate space on the stack - without floating point enabled */ #endif /* Store floating point preserved registers. */ #if defined(__riscv_float_abi_single) - fsw f8, 15*REGBYTES(sp) // Store fs0 - fsw f9, 16*REGBYTES(sp) // Store fs1 - fsw f18, 17*REGBYTES(sp) // Store fs2 - fsw f19, 18*REGBYTES(sp) // Store fs3 - fsw f20, 19*REGBYTES(sp) // Store fs4 - fsw f21, 20*REGBYTES(sp) // Store fs5 - fsw f22, 21*REGBYTES(sp) // Store fs6 - fsw f23, 22*REGBYTES(sp) // Store fs7 - fsw f24, 23*REGBYTES(sp) // Store fs8 - fsw f25, 24*REGBYTES(sp) // Store fs9 - fsw f26, 25*REGBYTES(sp) // Store fs10 - fsw f27, 26*REGBYTES(sp) // Store fs11 + fsw f8, 15*8(sp) /* Store fs0 */ + fsw f9, 16*8(sp) /* Store fs1 */ + fsw f18, 17*8(sp) /* Store fs2 */ + fsw f19, 18*8(sp) /* Store fs3 */ + fsw f20, 19*8(sp) /* Store fs4 */ + fsw f21, 20*8(sp) /* Store fs5 */ + fsw f22, 21*8(sp) /* Store fs6 */ + fsw f23, 22*8(sp) /* Store fs7 */ + fsw f24, 23*8(sp) /* Store fs8 */ + fsw f25, 24*8(sp) /* Store fs9 */ + fsw f26, 25*8(sp) /* Store fs10 */ + fsw f27, 26*8(sp) /* Store fs11 */ csrr t0, fcsr - STORE t0, 27*REGBYTES(sp) // Store fcsr + sd t0, 27*8(sp) /* Store fcsr */ #elif defined(__riscv_float_abi_double) - fsd f8, 15*REGBYTES(sp) // Store fs0 - fsd f9, 16*REGBYTES(sp) // Store fs1 - fsd f18, 17*REGBYTES(sp) // Store fs2 - fsd f19, 18*REGBYTES(sp) // Store fs3 - fsd f20, 19*REGBYTES(sp) // Store fs4 - fsd f21, 20*REGBYTES(sp) // Store fs5 - fsd f22, 21*REGBYTES(sp) // Store fs6 - fsd f23, 22*REGBYTES(sp) // Store fs7 - fsd f24, 23*REGBYTES(sp) // Store fs8 - fsd f25, 24*REGBYTES(sp) // Store fs9 - fsd f26, 25*REGBYTES(sp) // Store fs10 - fsd f27, 26*REGBYTES(sp) // Store fs11 + fsd f8, 15*8(sp) /* Store fs0 */ + fsd f9, 16*8(sp) /* Store fs1 */ + fsd f18, 17*8(sp) /* Store fs2 */ + fsd f19, 18*8(sp) /* Store fs3 */ + fsd f20, 19*8(sp) /* Store fs4 */ + fsd f21, 20*8(sp) /* Store fs5 */ + fsd f22, 21*8(sp) /* Store fs6 */ + fsd f23, 22*8(sp) /* Store fs7 */ + fsd f24, 23*8(sp) /* Store fs8 */ + fsd f25, 24*8(sp) /* Store fs9 */ + fsd f26, 25*8(sp) /* Store fs10 */ + fsd f27, 26*8(sp) /* Store fs11 */ csrr t0, fcsr - STORE t0, 27*REGBYTES(sp) // Store fcsr + sd t0, 27*8(sp) /* Store fcsr */ #endif - STORE x0, 0(sp) // Solicited stack type - STORE x1, 13*REGBYTES(sp) // Save RA - STORE x8, 12*REGBYTES(sp) // Save s0 - STORE x9, 11*REGBYTES(sp) // Save s1 - STORE x18, 10*REGBYTES(sp) // Save s2 - STORE x19, 9*REGBYTES(sp) // Save s3 - STORE x20, 8*REGBYTES(sp) // Save s4 - STORE x21, 7*REGBYTES(sp) // Save s5 - STORE x22, 6*REGBYTES(sp) // Save s6 - STORE x23, 5*REGBYTES(sp) // Save s7 - STORE x24, 4*REGBYTES(sp) // Save s8 - STORE x25, 3*REGBYTES(sp) // Save s9 - STORE x26, 2*REGBYTES(sp) // Save s10 - STORE x27, 1*REGBYTES(sp) // Save s11 - csrr t0, mstatus // Pickup mstatus - STORE t0, 14*REGBYTES(sp) // Save mstatus + sd zero, 0(sp) /* Solicited stack type */ + sd ra, 13*8(sp) /* Save return address */ + sd s0, 12*8(sp) /* Save s0 */ + sd s1, 11*8(sp) /* Save s1 */ + sd s2, 10*8(sp) /* Save s2 */ + sd s3, 9*8(sp) /* Save s3 */ + sd s4, 8*8(sp) /* Save s4 */ + sd s5, 7*8(sp) /* Save s5 */ + sd s6, 6*8(sp) /* Save s6 */ + sd s7, 5*8(sp) /* Save s7 */ + sd s8, 4*8(sp) /* Save s8 */ + sd s9, 3*8(sp) /* Save s9 */ + sd s10, 2*8(sp) /* Save s10 */ + sd s11, 1*8(sp) /* Save s11 */ + csrr t0, mstatus /* Pickup mstatus */ + sd t0, 14*8(sp) /* Save mstatus */ - /* Lockout interrupts. - will be enabled in _tx_thread_schedule */ + /* Lockout interrupts. will be enabled in _tx_thread_schedule */ - csrci mstatus, 0xF + csrci mstatus, 0x08 /* Disable interrupts (MIE bit 3) */ #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY - call _tx_execution_thread_exit // Call the thread execution exit function + call _tx_execution_thread_exit /* Call the thread execution exit function */ #endif - la t0, _tx_thread_current_ptr // Pickup address of pointer - LOAD t1, 0(t0) // Pickup current thread pointer - la t2,_tx_thread_system_stack_ptr // Pickup stack pointer address + la t0, _tx_thread_current_ptr /* Pickup address of pointer */ + ld t1, 0(t0) /* Pickup current thread pointer */ + la t2, _tx_thread_system_stack_ptr /* Pickup stack pointer address */ /* Save current stack and switch to system stack. */ /* _tx_thread_current_ptr -> tx_thread_stack_ptr = SP; SP = _tx_thread_system_stack_ptr; */ - STORE sp, 2*REGBYTES(t1) // Save stack pointer - LOAD sp, 0(t2) // Switch to system stack + sd sp, 16(t1) /* Save stack pointer */ + ld sp, 0(t2) /* Switch to system stack */ /* Determine if the time-slice is active. */ /* if (_tx_timer_time_slice) { */ - la t4, _tx_timer_time_slice // Pickup time slice variable addr - LOAD t3, 0(t4) // Pickup time slice value - la t2, _tx_thread_schedule // Pickup address of scheduling loop - beqz t3, _tx_thread_dont_save_ts // If no time-slice, don't save it + la t4, _tx_timer_time_slice /* Pickup time slice variable addr */ + ld t3, 0(t4) /* Pickup time slice value */ + la t2, _tx_thread_schedule /* Pickup address of scheduling loop */ + beqz t3, _tx_thread_dont_save_ts /* If no time-slice, don't save it */ /* Save time-slice for the thread and clear the current time-slice. */ /* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice; _tx_timer_time_slice = 0; */ - STORE t3, 6*REGBYTES(t1) // Save current time-slice for thread - STORE x0, 0(t4) // Clear time-slice variable + sd t3, 48(t1) /* Save current time-slice for thread */ + sd zero, 0(t4) /* Clear time-slice variable */ /* } */ _tx_thread_dont_save_ts: @@ -168,7 +167,7 @@ _tx_thread_dont_save_ts: /* Clear the current thread pointer. */ /* _tx_thread_current_ptr = TX_NULL; */ - STORE x0, 0(t0) // Clear current thread pointer + sd x0, 0(t0) // Clear current thread pointer jr t2 // Return to thread scheduler /* } */ diff --git a/ports/risc-v64/gnu/src/tx_timer_interrupt.S b/ports/risc-v64/gnu/src/tx_timer_interrupt.S new file mode 100644 index 000000000..146b08f09 --- /dev/null +++ b/ports/risc-v64/gnu/src/tx_timer_interrupt.S @@ -0,0 +1,210 @@ +/*************************************************************************** + * 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .section .text + .align 4 +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_interrupt RISC-V64/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Akif Ejaz, 10xEngineers */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the hardware timer interrupt. This */ +/* processing includes incrementing the system clock and checking for */ +/* time slice and/or timer expiration. If either is found, the */ +/* interrupt context save/restore functions are called along with the */ +/* expiration functions. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_timer_expiration_process Timer expiration processing */ +/* _tx_thread_time_slice Time slice interrupted thread */ +/* */ +/* CALLED BY */ +/* */ +/* interrupt vector */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-20-2023 Akif Ejaz Initial Version 6.2.1 */ +/* */ +/**************************************************************************/ +/* VOID _tx_timer_interrupt(VOID) +{ */ + .global _tx_timer_interrupt +_tx_timer_interrupt: + + /* Increment the system clock. */ + /* _tx_timer_system_clock++; */ + + la t0, _tx_timer_system_clock /* Pickup address of system clock */ + ld t1, 0(t0) /* Pickup system clock */ + la t2, _tx_timer_time_slice /* Pickup address of time slice */ + ld t3, 0(t2) /* Pickup time slice */ + addi t1, t1, 1 /* Increment system clock */ + sd t1, 0(t0) /* Store new system clock */ + li t6, 0 /* Clear local expired flag */ + + /* Test for time-slice expiration. */ + /* if (_tx_timer_time_slice) + { */ + + beqz t3, _tx_timer_no_time_slice /* If 0, skip time slice processing */ + addi t3, t3, -1 /* Decrement the time slice */ + + /* Decrement the time_slice. */ + /* _tx_timer_time_slice--; */ + + sd t3, 0(t2) /* Store new time slice */ + + /* Check for expiration. */ + /* if (_tx_timer_time_slice == 0) */ + + bgtz t3, _tx_timer_no_time_slice /* If not 0, has not expired yet */ + li t1, 1 /* Build expired flag */ + + /* Set the time-slice expired flag. */ + /* _tx_timer_expired_time_slice = TX_TRUE; */ + + la t4, _tx_timer_expired_time_slice /* Get address of expired flag */ + sw t1, 0(t4) /* Set expired flag (UINT) */ + ori t6, t6, 1 /* Set local expired flag */ + + /* } */ + +_tx_timer_no_time_slice: + + /* Test for timer expiration. */ + /* if (*_tx_timer_current_ptr) + { */ + + la t0, _tx_timer_current_ptr /* Pickup address of current ptr */ + ld t1, 0(t0) /* Pickup current pointer (double word) */ + ld t3, 0(t1) /* Pickup the current timer entry (double word) */ + la t2, _tx_timer_expired /* Pickup address of timer expired flag */ + li t4, 1 /* Build TX_TRUE flag */ + beqz t3, _tx_timer_no_timer /* If NULL, no timer has expired */ + + /* Set expiration flag. */ + /* _tx_timer_expired = TX_TRUE; */ + + ori t6, t6, 2 /* Set local expired flag */ + sw t4, 0(t2) /* Set expired flag in memory (UINT) */ + j _tx_timer_done /* Finished timer processing */ + + + /* } + else + { */ +_tx_timer_no_timer: + + /* No timer expired, increment the timer pointer. */ + /* _tx_timer_current_ptr++; */ + + /* Check for wrap-around. */ + /* if (_tx_timer_current_ptr == _tx_timer_list_end) */ + + la t2, _tx_timer_list_end /* Pickup address of list end pointer */ + ld t3, 0(t2) /* Pickup actual list end */ + addi t1, t1, 8 /* Point to next timer entry */ + sd t1, 0(t0) /* Store new timer pointer */ + bne t1, t3, _tx_timer_skip_wrap /* If not same, good pointer */ + + /* Wrap to beginning of list. */ + /* _tx_timer_current_ptr = _tx_timer_list_start; */ + + la t2, _tx_timer_list_start /* Pickup address of list start pointer */ + ld t4, 0(t2) /* Pickup start of the list */ + sd t4, 0(t0) /* Store new timer pointer */ + + +_tx_timer_skip_wrap: + /* } */ + +_tx_timer_done: + + + /* See if anything has expired. */ + /* if ((_tx_timer_expired_time_slice) || (_tx_timer_expired)) + { */ + + beqz t6, _tx_timer_nothing_expired /* If nothing expired skip the rest */ + addi sp, sp, -16 /* Allocate some storage on the stack */ + sd t6, 0(sp) /* Save local expired flag */ + sd ra, 8(sp) /* Save ra (8-byte aligned) */ + + /* Did a timer expire? */ + /* if (_tx_timer_expired) + { */ + + andi t2, t6, 2 /* Isolate the timer expired bit */ + beqz t2, _tx_timer_dont_activate /* No, timer not expired */ + + /* Call the timer expiration processing. */ + /* _tx_timer_expiration_process(void); */ + + call _tx_timer_expiration_process /* Call _tx_timer_expiration_process */ + ld t6, 0(sp) /* Recover local expired flag */ + + /* } */ +_tx_timer_dont_activate: + + /* Did time slice expire? */ + /* if (_tx_timer_expired_time_slice) + { */ + + andi t2, t6, 1 /* Is the timer expired bit set? */ + beqz t2, _tx_timer_not_ts_expiration /* If not, skip time slice processing */ + + /* Time slice interrupted thread. */ + /* _tx_thread_time_slice(); */ + + call _tx_thread_time_slice /* Call time slice */ + + /* } */ + +_tx_timer_not_ts_expiration: + + ld ra, 8(sp) /* Recover ra */ + addi sp, sp, 16 /* Recover stack space */ + /* } */ + +_tx_timer_nothing_expired: + + ret + +/* } */ diff --git a/ports/risc-v64/gnu/src/tx_timer_interrupt.c b/ports/risc-v64/gnu/src/tx_timer_interrupt.c deleted file mode 100644 index 3c90d0a61..000000000 --- a/ports/risc-v64/gnu/src/tx_timer_interrupt.c +++ /dev/null @@ -1,134 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2024 Microsoft Corporation - * - * 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 - **************************************************************************/ - - -/**************************************************************************/ -/**************************************************************************/ -/** */ -/** ThreadX Component */ -/** */ -/** Timer */ -/** */ -/**************************************************************************/ -/**************************************************************************/ - -#define TX_SOURCE_CODE - -/* Include necessary system files. */ - -#include "tx_api.h" -#include "tx_timer.h" -#include "tx_thread.h" - -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _tx_timer_interrupt RISC-V64/GNU */ -/* 6.2.1 */ -/* AUTHOR */ -/* */ -/* Scott Larson, Microsoft Corporation */ -/* */ -/* DESCRIPTION */ -/* */ -/* This function processes the hardware timer interrupt. This */ -/* processing includes incrementing the system clock and checking for */ -/* time slice and/or timer expiration. If either is found, the */ -/* interrupt context save/restore functions are called along with the */ -/* expiration functions. */ -/* */ -/* INPUT */ -/* */ -/* None */ -/* */ -/* OUTPUT */ -/* */ -/* None */ -/* */ -/* CALLS */ -/* */ -/* _tx_timer_expiration_process Timer expiration processing */ -/* _tx_thread_time_slice Time slice interrupted thread */ -/* */ -/* CALLED BY */ -/* */ -/* interrupt vector */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ -/* 03-08-2023 Scott Larson Initial Version 6.2.1 */ -/* */ -/**************************************************************************/ -VOID _tx_timer_interrupt(VOID) -{ - /* Increment system clock. */ - _tx_timer_system_clock++; - - /* Test for time-slice expiration. */ - if (_tx_timer_time_slice) - { - /* Decrement the time_slice. */ - _tx_timer_time_slice--; - - /* Check for expiration. */ - if (_tx_timer_time_slice == 0) - { - - /* Set the time-slice expired flag. */ - _tx_timer_expired_time_slice = TX_TRUE; - } - } - - /* Test for timer expiration. */ - if (*_tx_timer_current_ptr) - { - - /* Set expiration flag. */ - _tx_timer_expired = TX_TRUE; - } - else - { - - /* No timer expired, increment the timer pointer. */ - _tx_timer_current_ptr++; - - /* Check for wrap-around. */ - if (_tx_timer_current_ptr == _tx_timer_list_end) - { - - /* Wrap to beginning of list. */ - _tx_timer_current_ptr = _tx_timer_list_start; - } - } - - /* See if anything has expired. */ - if ((_tx_timer_expired_time_slice) || (_tx_timer_expired)) - { - - /* Did a timer expire? */ - if (_tx_timer_expired) - { - - /* Process timer expiration. */ - _tx_timer_expiration_process(); - } - - /* Did time slice expire? */ - if (_tx_timer_expired_time_slice) - { - - /* Time slice interrupted thread. */ - _tx_thread_time_slice(); - } - } -}