Compare commits
10 Commits
3fc721d6f2
...
feature/sm
| Author | SHA1 | Date | |
|---|---|---|---|
| 2433b66dc0 | |||
| 2d0ec274ac | |||
| 58fc04bbb3 | |||
| 3ba7cdda9e | |||
| 239cd26a5c | |||
| ebe891dad6 | |||
| c390c4b8db | |||
| 1da9671197 | |||
| 28aaf8fd96 | |||
| 6d635345dd |
@@ -15,6 +15,9 @@ target_link_libraries(c PUBLIC gcc)
|
|||||||
set(THREADX_CUSTOM_PORT ${CMAKE_CURRENT_LIST_DIR}/port/threadx)
|
set(THREADX_CUSTOM_PORT ${CMAKE_CURRENT_LIST_DIR}/port/threadx)
|
||||||
add_subdirectory(third-party/threadx)
|
add_subdirectory(third-party/threadx)
|
||||||
target_link_libraries(threadx PUBLIC c)
|
target_link_libraries(threadx PUBLIC c)
|
||||||
|
#Adds threadx_smp
|
||||||
|
add_subdirectory(port/threadx_smp)
|
||||||
|
target_link_libraries(threadx_smp PUBLIC c)
|
||||||
# Adds netxduo
|
# Adds netxduo
|
||||||
set(NETXDUO_CUSTOM_PORT ${CMAKE_CURRENT_LIST_DIR}/port/threadx)
|
set(NETXDUO_CUSTOM_PORT ${CMAKE_CURRENT_LIST_DIR}/port/threadx)
|
||||||
set(NXD_ENABLE_FILE_SERVERS OFF)
|
set(NXD_ENABLE_FILE_SERVERS OFF)
|
||||||
@@ -30,12 +33,12 @@ endif()
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
project(threadx_demo C ASM)
|
project(threadx_demo C ASM)
|
||||||
option(NX_DEBUG "compile netxduo debug output in" OFF)
|
option(NX_DEBUG "compile netxduo debug output in" OFF)
|
||||||
set(TARGET_MEM "ram" CACHE STRING "memory map to use" )
|
set(TARGET_MEM "ram" CACHE STRING "memory map to use")
|
||||||
set(CMAKE_EXECUTABLE_SUFFIX_C ".elf")
|
set(CMAKE_EXECUTABLE_SUFFIX_C ".elf")
|
||||||
|
|
||||||
function(setup_target TARGET)
|
function(setup_target TARGET)
|
||||||
set(options)
|
set(options)
|
||||||
set(oneValueArgs) # none for now
|
set(oneValueArgs) # none for now
|
||||||
set(multiValueArgs LIBRARIES SOURCES)
|
set(multiValueArgs LIBRARIES SOURCES)
|
||||||
cmake_parse_arguments(ST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
cmake_parse_arguments(ST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
if(ST_UNPARSED_ARGUMENTS)
|
if(ST_UNPARSED_ARGUMENTS)
|
||||||
@@ -43,13 +46,13 @@ function(setup_target TARGET)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(${TARGET})
|
add_executable(${TARGET})
|
||||||
target_sources(${TARGET} PRIVATE
|
target_sources(${TARGET} PRIVATE
|
||||||
port/picolibc/port.c
|
port/picolibc/port.c
|
||||||
port/moonlight/bootup.c
|
port/moonlight/bootup.c
|
||||||
port/moonlight/board.c
|
port/moonlight/board.c
|
||||||
port/moonlight/trap_non_vectored.c
|
port/moonlight/trap_non_vectored.c
|
||||||
port/moonlight/exception.c
|
port/moonlight/exception.c
|
||||||
port/moonlight/vector_table.c
|
port/moonlight/vector_table.c
|
||||||
)
|
)
|
||||||
if("netxduo" IN_LIST ST_LIBRARIES)
|
if("netxduo" IN_LIST ST_LIBRARIES)
|
||||||
target_sources(${TARGET} PRIVATE port/moonlight/mnrs_network_driver.c)
|
target_sources(${TARGET} PRIVATE port/moonlight/mnrs_network_driver.c)
|
||||||
@@ -67,7 +70,7 @@ function(setup_target TARGET)
|
|||||||
-ffunction-sections
|
-ffunction-sections
|
||||||
)
|
)
|
||||||
if(NX_DEBUG)
|
if(NX_DEBUG)
|
||||||
target_compile_definitions(${TARGET} PRIVATE NX_DEBUG NX_DEBUG_PACKET)
|
target_compile_definitions(${TARGET} PRIVATE NX_DEBUG NX_DEBUG_PACKET)
|
||||||
endif()
|
endif()
|
||||||
target_link_directories(${TARGET} PRIVATE src) # needed for linker script includes
|
target_link_directories(${TARGET} PRIVATE src) # needed for linker script includes
|
||||||
target_link_options(${TARGET} PRIVATE
|
target_link_options(${TARGET} PRIVATE
|
||||||
@@ -80,19 +83,16 @@ function(setup_target TARGET)
|
|||||||
if(ST_LIBRARIES)
|
if(ST_LIBRARIES)
|
||||||
target_link_libraries(${TARGET} PRIVATE ${ST_LIBRARIES})
|
target_link_libraries(${TARGET} PRIVATE ${ST_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(${TARGET} PRIVATE threadx)
|
|
||||||
|
|
||||||
add_custom_command(TARGET ${TARGET} POST_BUILD
|
add_custom_command(TARGET ${TARGET} POST_BUILD
|
||||||
COMMAND ${OBJCOPY} -O ihex $<TARGET_FILE:${TARGET}> ${CMAKE_BINARY_DIR}/${TARGET}.hex
|
COMMAND ${OBJCOPY} -O ihex $<TARGET_FILE:${TARGET}> ${CMAKE_BINARY_DIR}/${TARGET}.hex
|
||||||
COMMAND ${OBJCOPY} -O binary $<TARGET_FILE:${TARGET}> ${CMAKE_BINARY_DIR}/${TARGET}.bin
|
COMMAND ${OBJCOPY} -O binary $<TARGET_FILE:${TARGET}> ${CMAKE_BINARY_DIR}/${TARGET}.bin
|
||||||
COMMAND ${SIZE} $<TARGET_FILE:${TARGET}>
|
COMMAND ${SIZE} $<TARGET_FILE:${TARGET}>
|
||||||
COMMAND ${OBJDUMP} -S $<TARGET_FILE:${TARGET}> > ${TARGET}.dis
|
COMMAND ${OBJDUMP} -S $<TARGET_FILE:${TARGET}> > ${TARGET}.dis
|
||||||
COMMENT "Creating collateral for ${TARGET}"
|
COMMENT "Creating collateral for ${TARGET}"
|
||||||
)
|
)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
setup_target(thread_demo SOURCES src/thread_demo/main.c)
|
setup_target(thread_demo LIBRARIES threadx SOURCES src/thread_demo/main.c)
|
||||||
setup_target(tcp_demo
|
setup_target(tcp_demo LIBRARIES threadx netxduo SOURCES src/tcp_demo/main.c)
|
||||||
LIBRARIES netxduo
|
setup_target(smp_demo LIBRARIES threadx_smp SOURCES src/thread_demo/main.c)
|
||||||
SOURCES src/tcp_demo/main.c
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <picotls.h>
|
#include <picotls.h>
|
||||||
|
#include <tx_port.h>
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#define EXTERN_C extern "C"
|
#define EXTERN_C extern "C"
|
||||||
#else
|
#else
|
||||||
@@ -50,7 +50,6 @@ extern int main(void);
|
|||||||
|
|
||||||
// The linker script will place this in the reset entry point.
|
// The linker script will place this in the reset entry point.
|
||||||
// It will be 'called' with no stack or C runtime configuration.
|
// It will be 'called' with no stack or C runtime configuration.
|
||||||
// NOTE - this only supports a single hart.
|
|
||||||
// tp will not be initialized
|
// tp will not be initialized
|
||||||
void _start(void) {
|
void _start(void) {
|
||||||
// Setup SP and GP
|
// Setup SP and GP
|
||||||
@@ -64,6 +63,24 @@ void _start(void) {
|
|||||||
"la gp, __global_pointer$;"
|
"la gp, __global_pointer$;"
|
||||||
".option pop;"
|
".option pop;"
|
||||||
"la sp, _sp;"
|
"la sp, _sp;"
|
||||||
|
#if defined(__riscv_zicsr)
|
||||||
|
"csrr t0, mhartid;"
|
||||||
|
#else
|
||||||
|
"li t0, 0;"
|
||||||
|
#endif
|
||||||
|
"la t1, __stack_size;"
|
||||||
|
"la t1, __stack_size;"
|
||||||
|
"la sp, _sp;"
|
||||||
|
// Loop incase M extension is not present
|
||||||
|
"1:;"
|
||||||
|
"beqz t0, 2f;"
|
||||||
|
"sub sp, sp, t1;"
|
||||||
|
"addi t0, t0, -1;"
|
||||||
|
"j 1b;"
|
||||||
|
"2:;"
|
||||||
|
#ifdef TX_THREAD_SMP_MAX_CORES
|
||||||
|
"call _tx_thread_smp_initialize_wait;"
|
||||||
|
#endif
|
||||||
"jal zero, _initialize;"
|
"jal zero, _initialize;"
|
||||||
: /* output: none %0 */
|
: /* output: none %0 */
|
||||||
: /* input: none */
|
: /* input: none */
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "hwtimer.h"
|
#include "hwtimer.h"
|
||||||
|
#include "platform.h"
|
||||||
#include "riscv-traps.h"
|
#include "riscv-traps.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -39,6 +40,11 @@ void trap_handler(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval) {
|
|||||||
hwtimer_handler();
|
hwtimer_handler();
|
||||||
_tx_timer_interrupt();
|
_tx_timer_interrupt();
|
||||||
break;
|
break;
|
||||||
|
#ifdef TX_THREAD_SMP_INTER_CORE_INTERRUPT
|
||||||
|
case RISCV_INT_MSI:
|
||||||
|
set_aclint_msip(aclint, csr_read_mhartid(), 0);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
case RISCV_INT_MEI:
|
case RISCV_INT_MEI:
|
||||||
puts("[INTERRUPT]: handler ext irq error!\n");
|
puts("[INTERRUPT]: handler ext irq error!\n");
|
||||||
while(1)
|
while(1)
|
||||||
|
|||||||
@@ -138,19 +138,19 @@ trap_handler:
|
|||||||
.extern __heap_start
|
.extern __heap_start
|
||||||
.extern board_init
|
.extern board_init
|
||||||
_tx_initialize_low_level:
|
_tx_initialize_low_level:
|
||||||
STORE sp, _tx_thread_system_stack_ptr, t0 // Save system stack pointer
|
STORE sp, _tx_thread_system_stack_ptr, t0 // Save system stack pointer
|
||||||
|
|
||||||
la t0, __heap_start // Pickup first free address
|
la t0, __heap_start // Pickup first free address
|
||||||
STORE t0, _tx_initialize_unused_memory, t1 // Save unused memory address
|
STORE t0, _tx_initialize_unused_memory, t1 // Save unused memory address
|
||||||
li t0, MSTATUS_MIE
|
li t0, MSTATUS_MIE
|
||||||
csrrc zero, mstatus, t0 // clear MSTATUS_MIE bit
|
csrrc zero, mstatus, t0 // clear MSTATUS_MIE bit
|
||||||
li t0, (MSTATUS_MPP_M | MSTATUS_MPIE )
|
li t0, (MSTATUS_MPP_M | MSTATUS_MPIE )
|
||||||
csrrs zero, mstatus, t0 // set MSTATUS_MPP, MPIE bit
|
csrrs zero, mstatus, t0 // set MSTATUS_MPP, MPIE bit
|
||||||
li t0, (MIE_MTIE | MIE_MSIE | MIE_MEIE)
|
li t0, (MIE_MTIE | MIE_MSIE | MIE_MEIE)
|
||||||
csrrs zero, mie, t0 // set mie
|
csrrs zero, mie, t0 // set mie
|
||||||
#ifdef __riscv_flen
|
#ifdef __riscv_flen
|
||||||
li t0, MSTATUS_FS
|
li t0, MSTATUS_FS
|
||||||
csrrs zero, mstatus, t0 // set MSTATUS_FS bit to open f/d isa in riscv
|
csrrs zero, mstatus, t0 // set MSTATUS_FS bit to open f/d isa in riscv
|
||||||
fscsr x0
|
fscsr x0
|
||||||
#endif
|
#endif
|
||||||
addi sp, sp, -8
|
addi sp, sp, -8
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ set(THREADX_SMP_CUSTOM_SRC
|
|||||||
src/tx_thread_smp_unprotect.S
|
src/tx_thread_smp_unprotect.S
|
||||||
src/tx_thread_stack_build.S
|
src/tx_thread_stack_build.S
|
||||||
src/tx_thread_system_return.S
|
src/tx_thread_system_return.S
|
||||||
|
src/tx_timer_interrupt.c
|
||||||
)
|
)
|
||||||
|
|
||||||
threadx_smp_add_offsets(
|
threadx_smp_add_offsets(
|
||||||
@@ -34,13 +35,11 @@ threadx_smp_add_offsets(
|
|||||||
OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated
|
OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated
|
||||||
SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/tx_asm_offsets.c
|
SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/tx_asm_offsets.c
|
||||||
INCLUDE_DIRS
|
INCLUDE_DIRS
|
||||||
${THREADX_COMMON_SMP_DIR}/inc
|
${THREADX_COMMON_SMP_DIR}/inc
|
||||||
${THREADX_SMP_CUSTOM_INC}
|
${THREADX_SMP_CUSTOM_INC}
|
||||||
COMPILE_DEFINITIONS
|
|
||||||
TX_QUEUE_MESSAGE_MAX_SIZE=16
|
|
||||||
DEPENDS
|
DEPENDS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/inc/tx_port.h
|
${CMAKE_CURRENT_SOURCE_DIR}/inc/tx_port.h
|
||||||
${THREADX_COMMON_SMP_DIR}/inc/tx_api.h
|
${THREADX_COMMON_SMP_DIR}/inc/tx_api.h
|
||||||
OUT_INCLUDE_DIR THREADX_SMP_GENERATED_INC_DIR
|
OUT_INCLUDE_DIR THREADX_SMP_GENERATED_INC_DIR
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -59,13 +58,3 @@ target_include_directories(threadx_smp PRIVATE
|
|||||||
)
|
)
|
||||||
target_compile_definitions(threadx_smp PRIVATE TX_QUEUE_MESSAGE_MAX_SIZE=16) #This is addressed in PR #503
|
target_compile_definitions(threadx_smp PRIVATE TX_QUEUE_MESSAGE_MAX_SIZE=16) #This is addressed in PR #503
|
||||||
add_dependencies(threadx_smp threadx_smp_offsets)
|
add_dependencies(threadx_smp threadx_smp_offsets)
|
||||||
|
|
||||||
add_executable(smp_demo)
|
|
||||||
target_include_directories(smp_demo PRIVATE
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../moonlight
|
|
||||||
)
|
|
||||||
target_link_libraries(smp_demo PRIVATE threadx_smp)
|
|
||||||
|
|
||||||
target_sources(smp_demo PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../src/thread_demo/main.c)
|
|
||||||
|
|
||||||
#cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=$PWD/../../cmake/rv32gc_gnu.cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=YES
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ file(STRINGS "${INPUT}" OFFSET_LINES REGEX "->")
|
|||||||
set(OFFSET_CONTENT "/* Generated by GenerateAsmOffsets.cmake. */\n")
|
set(OFFSET_CONTENT "/* Generated by GenerateAsmOffsets.cmake. */\n")
|
||||||
|
|
||||||
foreach(LINE IN LISTS OFFSET_LINES)
|
foreach(LINE IN LISTS OFFSET_LINES)
|
||||||
string(REGEX MATCH "->([A-Za-z0-9_]+)[^0-9-]*(-?[0-9]+)" _ "${LINE}")
|
string(REGEX MATCH "-->([A-Za-z0-9_]+)[^0-9-]*(-?[0-9]+)" _ "${LINE}")
|
||||||
if(NOT CMAKE_MATCH_1)
|
if(NOT CMAKE_MATCH_1)
|
||||||
continue()
|
continue()
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -69,7 +69,7 @@
|
|||||||
#define LWU lw
|
#define LWU lw
|
||||||
#define LOG_REGBYTES 2
|
#define LOG_REGBYTES 2
|
||||||
#endif
|
#endif
|
||||||
#define REGBYTES (1 << LOG_REGBYTES)
|
#define REGBYTES (1 << LOG_REGBYTES)
|
||||||
|
|
||||||
#include "tx_asm_offsets.inc"
|
#include "tx_asm_offsets.inc"
|
||||||
|
|
||||||
@@ -89,6 +89,13 @@
|
|||||||
#define TX_THREAD_SMP_CORE_MASK 0xF /* Where bit 0 represents Core 0, bit 1 represents Core 1, etc. */
|
#define TX_THREAD_SMP_CORE_MASK 0xF /* Where bit 0 represents Core 0, bit 1 represents Core 1, etc. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Declare ThreadX to discover the cores dynamically. The ceiling is given by TX_THREAD_SMP_MAX_CORES */
|
||||||
|
/*
|
||||||
|
The current implementation does not support dynamic discovery, but simply set the runtime determined number to
|
||||||
|
TX_THREAD_SMP_MAX_CORES. See tx_thread_smp_low_level_initialize.S
|
||||||
|
#define TX_THREAD_SMP_DYNAMIC_CORE_MAX
|
||||||
|
*/
|
||||||
|
|
||||||
/* Define INLINE_DECLARE */
|
/* Define INLINE_DECLARE */
|
||||||
|
|
||||||
#define INLINE_DECLARE inline
|
#define INLINE_DECLARE inline
|
||||||
@@ -105,6 +112,10 @@
|
|||||||
|
|
||||||
#define TX_THREAD_SMP_INTER_CORE_INTERRUPT
|
#define TX_THREAD_SMP_INTER_CORE_INTERRUPT
|
||||||
|
|
||||||
|
/* Use default wakeup logic*/
|
||||||
|
|
||||||
|
#define TX_THREAD_SMP_DEFAULT_WAKEUP_LOGIC
|
||||||
|
|
||||||
/* Determine if there is customer-specific wakeup logic needed. */
|
/* Determine if there is customer-specific wakeup logic needed. */
|
||||||
|
|
||||||
#ifdef TX_THREAD_SMP_WAKEUP_LOGIC
|
#ifdef TX_THREAD_SMP_WAKEUP_LOGIC
|
||||||
|
|||||||
@@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
#include "tx_api.h"
|
#include "tx_api.h"
|
||||||
|
|
||||||
|
#define TX_ASM_OFFSET(symbol, value) __asm__ volatile("\n.ascii \"-->" #symbol " %c0\\n\"" : : "i"(value))
|
||||||
#define TX_ASM_OFFSET(symbol, value) __asm__ volatile("\n.ascii \"->" #symbol " %c0\\n\"" : : "i" (value))
|
|
||||||
|
|
||||||
|
|
||||||
void tx_asm_offsets_generate(void)
|
void tx_asm_offsets_generate(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,6 +10,85 @@
|
|||||||
|
|
||||||
#include "csr.h"
|
#include "csr.h"
|
||||||
#include "tx_port.h"
|
#include "tx_port.h"
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
.align 4
|
||||||
|
/**************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* FUNCTION RELEASE */
|
||||||
|
/* */
|
||||||
|
/* trap_entry RISC-V64/GNU */
|
||||||
|
/* 6.2.1 */
|
||||||
|
/* AUTHOR */
|
||||||
|
/* */
|
||||||
|
/* Jer6y , luojun@oerv.isrc.iscas.ac.cn */
|
||||||
|
/* */
|
||||||
|
/* DESCRIPTION */
|
||||||
|
/* */
|
||||||
|
/* This function is responsible for riscv processor trap handle */
|
||||||
|
/* It will do the contex save and call c trap_handler and do contex */
|
||||||
|
/* load */
|
||||||
|
/* */
|
||||||
|
/* INPUT */
|
||||||
|
/* */
|
||||||
|
/* None */
|
||||||
|
/* */
|
||||||
|
/* OUTPUT */
|
||||||
|
/* */
|
||||||
|
/* None */
|
||||||
|
/* */
|
||||||
|
/* CALLS */
|
||||||
|
/* */
|
||||||
|
/* trap_handler */
|
||||||
|
/* */
|
||||||
|
/* CALLED BY */
|
||||||
|
/* */
|
||||||
|
/* hardware exception */
|
||||||
|
/* RELEASE HISTORY */
|
||||||
|
/* */
|
||||||
|
/* DATE NAME DESCRIPTION */
|
||||||
|
/* */
|
||||||
|
/* 10-25-2024 Jerry Luo */
|
||||||
|
/* */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/**************************************************************************/
|
||||||
|
/** */
|
||||||
|
/** ThreadX Component */
|
||||||
|
/** */
|
||||||
|
/** Initialize */
|
||||||
|
/** */
|
||||||
|
/**************************************************************************/
|
||||||
|
/**************************************************************************/
|
||||||
|
.global trap_entry
|
||||||
|
.extern _tx_thread_context_restore
|
||||||
|
trap_entry:
|
||||||
|
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
|
||||||
|
addi sp, sp, -65*REGBYTES // Allocate space for all registers - with floating point enabled
|
||||||
|
#else
|
||||||
|
addi sp, sp, -32*REGBYTES // Allocate space for all registers - without floating point enabled
|
||||||
|
#endif
|
||||||
|
|
||||||
|
STORE x1, 28*REGBYTES(sp) // Store RA, 28*REGBYTES(because call will override ra [ra is a calle register in riscv])
|
||||||
|
|
||||||
|
call _tx_thread_context_save
|
||||||
|
|
||||||
|
csrr a0, mcause
|
||||||
|
csrr a1, mepc
|
||||||
|
csrr a2, mtval
|
||||||
|
addi sp, sp, -8
|
||||||
|
STORE ra, 0(sp)
|
||||||
|
call trap_handler
|
||||||
|
LOAD ra, 0(sp)
|
||||||
|
addi sp, sp, 8
|
||||||
|
call _tx_thread_context_restore
|
||||||
|
// it will nerver return
|
||||||
|
.weak trap_handler
|
||||||
|
trap_handler:
|
||||||
|
1:
|
||||||
|
j 1b
|
||||||
.section .text
|
.section .text
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/* */
|
/* */
|
||||||
@@ -81,4 +160,4 @@ _tx_initialize_low_level:
|
|||||||
addi sp, sp, 8
|
addi sp, sp, 8
|
||||||
la t0, trap_entry
|
la t0, trap_entry
|
||||||
csrw mtvec, t0
|
csrw mtvec, t0
|
||||||
ret
|
ret
|
||||||
|
|||||||
@@ -1,23 +1,71 @@
|
|||||||
#include "tx_port.h"
|
#include "tx_port.h"
|
||||||
|
#include "csr.h"
|
||||||
.section .text
|
.section .text
|
||||||
.align 2
|
.align 2
|
||||||
|
|
||||||
.global _tx_thread_smp_initialize_wait
|
.global _tx_thread_smp_initialize_wait
|
||||||
.type _tx_thread_smp_initialize_wait, @function
|
.type _tx_thread_smp_initialize_wait, @function
|
||||||
|
.extern _tx_thread_schedule
|
||||||
_tx_thread_smp_initialize_wait:
|
_tx_thread_smp_initialize_wait:
|
||||||
|
|
||||||
/* Core 0 continues initialization. All other harts wait until the
|
/* Lockout interrupts while startup synchronization is in progress. */
|
||||||
release flag is set by the low-level SMP initialization path. */
|
csrci mstatus, 0x08 // Lockout interrupts
|
||||||
|
|
||||||
|
/* Pickup current hart ID. */
|
||||||
csrr t0, mhartid // Pickup current hart ID
|
csrr t0, mhartid // Pickup current hart ID
|
||||||
beqz t0, _tx_thread_smp_initialize_done // Core 0 does not wait
|
beqz t0, _tx_thread_smp_initialize_done // Core 0 does not wait
|
||||||
|
|
||||||
la t1, _tx_thread_smp_release_cores_flag // Release flag address
|
/* Build per-hart offsets for ULONG and pointer arrays. */
|
||||||
|
slli t1, t0, 2 // ULONG array offset
|
||||||
|
slli t2, t0, LOG_REGBYTES // Pointer array offset
|
||||||
|
|
||||||
_tx_thread_smp_initialize_wait_loop:
|
/* Wait until ThreadX has acknowledged this hart by setting its
|
||||||
LWU t2, 0(t1) // Pickup release flag
|
system state to TX_INITIALIZE_IN_PROGRESS. */
|
||||||
bnez t2, _tx_thread_smp_initialize_done // Exit once core 0 releases secondaries
|
li t3, 0xF0F0F0F0 // TX_INITIALIZE_IN_PROGRESS
|
||||||
j _tx_thread_smp_initialize_wait_loop // Keep waiting
|
la t4, _tx_thread_system_state // Base of system state array
|
||||||
|
add t5, t4, t1 // This hart's system state slot
|
||||||
|
|
||||||
|
_tx_thread_smp_wait_for_initialize:
|
||||||
|
LWU t6, 0(t5) // Pickup current hart's system state
|
||||||
|
bne t6, t3, _tx_thread_smp_wait_for_initialize
|
||||||
|
|
||||||
|
/* Save the system stack pointer for this hart. */
|
||||||
|
la t3, _tx_thread_system_stack_ptr // Base of system stack pointer array
|
||||||
|
add t3, t3, t2 // Select this hart's slot
|
||||||
|
STORE sp, 0(t3) // Save system stack pointer
|
||||||
|
|
||||||
|
/* Wait for core 0 to release the secondary harts. */
|
||||||
|
la t3, _tx_thread_smp_release_cores_flag // Release flag address
|
||||||
|
|
||||||
|
_tx_thread_smp_wait_for_release:
|
||||||
|
LWU t6, 0(t3) // Pickup release flag
|
||||||
|
beqz t6, _tx_thread_smp_wait_for_release
|
||||||
|
|
||||||
|
/* Acknowledge the release by clearing this hart's system state. */
|
||||||
|
sw x0, 0(t5) // Set this hart's system state to zero
|
||||||
|
|
||||||
|
/* Wait for core 0 to finish initialization. */
|
||||||
|
_tx_thread_smp_wait_for_core0:
|
||||||
|
LWU t6, 0(t4) // Pickup core 0 system state
|
||||||
|
bnez t6, _tx_thread_smp_wait_for_core0
|
||||||
|
|
||||||
|
/* Prepare interrupt state */
|
||||||
|
li t0, MSTATUS_MIE
|
||||||
|
csrrc zero, mstatus, t0 // clear MSTATUS_MIE bit
|
||||||
|
li t0, (MSTATUS_MPP_M | MSTATUS_MPIE )
|
||||||
|
csrrs zero, mstatus, t0 // set MSTATUS_MPP, MPIE bit
|
||||||
|
li t0, (MIE_MTIE | MIE_MSIE | MIE_MEIE)
|
||||||
|
csrrs zero, mie, t0 // set mie
|
||||||
|
#ifdef __riscv_flen
|
||||||
|
li t0, MSTATUS_FS
|
||||||
|
csrrs zero, mstatus, t0 // set MSTATUS_FS bit to open f/d isa in riscv
|
||||||
|
fscsr x0
|
||||||
|
#endif
|
||||||
|
la t0, trap_entry
|
||||||
|
csrw mtvec, t0
|
||||||
|
|
||||||
|
/* Initialization is complete for this hart, enter the scheduler. */
|
||||||
|
j _tx_thread_schedule
|
||||||
|
|
||||||
_tx_thread_smp_initialize_done:
|
_tx_thread_smp_initialize_done:
|
||||||
ret
|
ret
|
||||||
|
|||||||
@@ -6,26 +6,4 @@
|
|||||||
.global _tx_thread_smp_low_level_initialize
|
.global _tx_thread_smp_low_level_initialize
|
||||||
.type _tx_thread_smp_low_level_initialize, @function
|
.type _tx_thread_smp_low_level_initialize, @function
|
||||||
_tx_thread_smp_low_level_initialize:
|
_tx_thread_smp_low_level_initialize:
|
||||||
|
|
||||||
/* Only hart 0 performs low-level SMP initialization. */
|
|
||||||
csrr t0, mhartid // Pickup current hart ID
|
|
||||||
bnez t0, _tx_thread_smp_low_level_initialize_done
|
|
||||||
|
|
||||||
/* Keep secondary harts parked until kernel-enter releases them. */
|
|
||||||
la t1, _tx_thread_smp_release_cores_flag
|
|
||||||
sw x0, 0(t1) // Clear release flag
|
|
||||||
|
|
||||||
#ifdef TX_THREAD_SMP_DYNAMIC_CORE_MAX
|
|
||||||
/* Record the detected core count supplied by the caller. */
|
|
||||||
la t1, _tx_thread_smp_detected_cores
|
|
||||||
sw a0, 0(t1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Platform-specific secondary-hart startup can go here.
|
|
||||||
This is where core 0 would program boot addresses, send startup IPIs,
|
|
||||||
or otherwise bring the other harts online. */
|
|
||||||
|
|
||||||
fence rw, rw // Publish startup state
|
|
||||||
|
|
||||||
_tx_thread_smp_low_level_initialize_done:
|
|
||||||
ret
|
ret
|
||||||
|
|||||||
129
port/threadx_smp/src/tx_timer_interrupt.c
Normal file
129
port/threadx_smp/src/tx_timer_interrupt.c
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* 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
|
||||||
|
#define TX_THREAD_SMP_SOURCE_CODE
|
||||||
|
|
||||||
|
/* Include necessary system files. */
|
||||||
|
|
||||||
|
#include "tx_api.h"
|
||||||
|
#include "tx_thread.h"
|
||||||
|
#include "tx_timer.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)
|
||||||
|
{
|
||||||
|
UINT saved_posture;
|
||||||
|
|
||||||
|
|
||||||
|
/* Only core 0 advances the global timer wheel. */
|
||||||
|
if (TX_SMP_CORE_ID != ((UINT) 0))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the protection. */
|
||||||
|
saved_posture = _tx_thread_smp_protect();
|
||||||
|
|
||||||
|
/* Indicate timer interrupt processing is active. */
|
||||||
|
_tx_timer_interrupt_active++;
|
||||||
|
|
||||||
|
/* Increment system clock. */
|
||||||
|
_tx_timer_system_clock++;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Did a timer expire? */
|
||||||
|
if (_tx_timer_expired)
|
||||||
|
{
|
||||||
|
/* Process timer expiration. */
|
||||||
|
_tx_timer_expiration_process();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process time-slice expiration for all cores. */
|
||||||
|
_tx_thread_time_slice();
|
||||||
|
|
||||||
|
/* Timer interrupt processing is no longer active. */
|
||||||
|
_tx_timer_interrupt_active--;
|
||||||
|
|
||||||
|
/* Release the protection. */
|
||||||
|
_tx_thread_smp_unprotect(saved_posture);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user