Compare commits
10 Commits
3fc721d6f2
...
2433b66dc0
| 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)
|
||||
add_subdirectory(third-party/threadx)
|
||||
target_link_libraries(threadx PUBLIC c)
|
||||
#Adds threadx_smp
|
||||
add_subdirectory(port/threadx_smp)
|
||||
target_link_libraries(threadx_smp PUBLIC c)
|
||||
# Adds netxduo
|
||||
set(NETXDUO_CUSTOM_PORT ${CMAKE_CURRENT_LIST_DIR}/port/threadx)
|
||||
set(NXD_ENABLE_FILE_SERVERS OFF)
|
||||
@@ -30,12 +33,12 @@ endif()
|
||||
###############################################################################
|
||||
project(threadx_demo C ASM)
|
||||
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")
|
||||
|
||||
function(setup_target TARGET)
|
||||
set(options)
|
||||
set(oneValueArgs) # none for now
|
||||
set(oneValueArgs) # none for now
|
||||
set(multiValueArgs LIBRARIES SOURCES)
|
||||
cmake_parse_arguments(ST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
if(ST_UNPARSED_ARGUMENTS)
|
||||
@@ -43,13 +46,13 @@ function(setup_target TARGET)
|
||||
endif()
|
||||
|
||||
add_executable(${TARGET})
|
||||
target_sources(${TARGET} PRIVATE
|
||||
port/picolibc/port.c
|
||||
port/moonlight/bootup.c
|
||||
port/moonlight/board.c
|
||||
port/moonlight/trap_non_vectored.c
|
||||
port/moonlight/exception.c
|
||||
port/moonlight/vector_table.c
|
||||
target_sources(${TARGET} PRIVATE
|
||||
port/picolibc/port.c
|
||||
port/moonlight/bootup.c
|
||||
port/moonlight/board.c
|
||||
port/moonlight/trap_non_vectored.c
|
||||
port/moonlight/exception.c
|
||||
port/moonlight/vector_table.c
|
||||
)
|
||||
if("netxduo" IN_LIST ST_LIBRARIES)
|
||||
target_sources(${TARGET} PRIVATE port/moonlight/mnrs_network_driver.c)
|
||||
@@ -67,7 +70,7 @@ function(setup_target TARGET)
|
||||
-ffunction-sections
|
||||
)
|
||||
if(NX_DEBUG)
|
||||
target_compile_definitions(${TARGET} PRIVATE NX_DEBUG NX_DEBUG_PACKET)
|
||||
target_compile_definitions(${TARGET} PRIVATE NX_DEBUG NX_DEBUG_PACKET)
|
||||
endif()
|
||||
target_link_directories(${TARGET} PRIVATE src) # needed for linker script includes
|
||||
target_link_options(${TARGET} PRIVATE
|
||||
@@ -80,19 +83,16 @@ function(setup_target TARGET)
|
||||
if(ST_LIBRARIES)
|
||||
target_link_libraries(${TARGET} PRIVATE ${ST_LIBRARIES})
|
||||
endif()
|
||||
target_link_libraries(${TARGET} PRIVATE threadx)
|
||||
|
||||
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 ${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}"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
setup_target(thread_demo SOURCES src/thread_demo/main.c)
|
||||
setup_target(tcp_demo
|
||||
LIBRARIES netxduo
|
||||
SOURCES src/tcp_demo/main.c
|
||||
)
|
||||
setup_target(thread_demo LIBRARIES threadx SOURCES src/thread_demo/main.c)
|
||||
setup_target(tcp_demo LIBRARIES threadx netxduo SOURCES src/tcp_demo/main.c)
|
||||
setup_target(smp_demo LIBRARIES threadx_smp SOURCES src/thread_demo/main.c)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <picotls.h>
|
||||
|
||||
#include <tx_port.h>
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN_C extern "C"
|
||||
#else
|
||||
@@ -50,7 +50,6 @@ extern int main(void);
|
||||
|
||||
// The linker script will place this in the reset entry point.
|
||||
// It will be 'called' with no stack or C runtime configuration.
|
||||
// NOTE - this only supports a single hart.
|
||||
// tp will not be initialized
|
||||
void _start(void) {
|
||||
// Setup SP and GP
|
||||
@@ -64,6 +63,24 @@ void _start(void) {
|
||||
"la gp, __global_pointer$;"
|
||||
".option pop;"
|
||||
"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;"
|
||||
: /* output: none %0 */
|
||||
: /* input: none */
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "hwtimer.h"
|
||||
#include "platform.h"
|
||||
#include "riscv-traps.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
@@ -39,6 +40,11 @@ void trap_handler(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval) {
|
||||
hwtimer_handler();
|
||||
_tx_timer_interrupt();
|
||||
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:
|
||||
puts("[INTERRUPT]: handler ext irq error!\n");
|
||||
while(1)
|
||||
|
||||
@@ -138,19 +138,19 @@ trap_handler:
|
||||
.extern __heap_start
|
||||
.extern board_init
|
||||
_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
|
||||
STORE t0, _tx_initialize_unused_memory, t1 // Save unused memory address
|
||||
la t0, __heap_start // Pickup first free address
|
||||
STORE t0, _tx_initialize_unused_memory, t1 // Save unused memory address
|
||||
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 )
|
||||
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)
|
||||
csrrs zero, mie, t0 // set mie
|
||||
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
|
||||
csrrs zero, mstatus, t0 // set MSTATUS_FS bit to open f/d isa in riscv
|
||||
fscsr x0
|
||||
#endif
|
||||
addi sp, sp, -8
|
||||
|
||||
@@ -27,6 +27,7 @@ set(THREADX_SMP_CUSTOM_SRC
|
||||
src/tx_thread_smp_unprotect.S
|
||||
src/tx_thread_stack_build.S
|
||||
src/tx_thread_system_return.S
|
||||
src/tx_timer_interrupt.c
|
||||
)
|
||||
|
||||
threadx_smp_add_offsets(
|
||||
@@ -34,13 +35,11 @@ threadx_smp_add_offsets(
|
||||
OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated
|
||||
SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/tx_asm_offsets.c
|
||||
INCLUDE_DIRS
|
||||
${THREADX_COMMON_SMP_DIR}/inc
|
||||
${THREADX_SMP_CUSTOM_INC}
|
||||
COMPILE_DEFINITIONS
|
||||
TX_QUEUE_MESSAGE_MAX_SIZE=16
|
||||
${THREADX_COMMON_SMP_DIR}/inc
|
||||
${THREADX_SMP_CUSTOM_INC}
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/inc/tx_port.h
|
||||
${THREADX_COMMON_SMP_DIR}/inc/tx_api.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/inc/tx_port.h
|
||||
${THREADX_COMMON_SMP_DIR}/inc/tx_api.h
|
||||
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
|
||||
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")
|
||||
|
||||
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)
|
||||
continue()
|
||||
endif()
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
#define LWU lw
|
||||
#define LOG_REGBYTES 2
|
||||
#endif
|
||||
#define REGBYTES (1 << LOG_REGBYTES)
|
||||
#define REGBYTES (1 << LOG_REGBYTES)
|
||||
|
||||
#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. */
|
||||
#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 inline
|
||||
@@ -105,6 +112,10 @@
|
||||
|
||||
#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. */
|
||||
|
||||
#ifdef TX_THREAD_SMP_WAKEUP_LOGIC
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
#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)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,85 @@
|
||||
|
||||
#include "csr.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
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
@@ -81,4 +160,4 @@ _tx_initialize_low_level:
|
||||
addi sp, sp, 8
|
||||
la t0, trap_entry
|
||||
csrw mtvec, t0
|
||||
ret
|
||||
ret
|
||||
|
||||
@@ -1,23 +1,71 @@
|
||||
#include "tx_port.h"
|
||||
|
||||
#include "csr.h"
|
||||
.section .text
|
||||
.align 2
|
||||
|
||||
.global _tx_thread_smp_initialize_wait
|
||||
.type _tx_thread_smp_initialize_wait, @function
|
||||
.extern _tx_thread_schedule
|
||||
_tx_thread_smp_initialize_wait:
|
||||
|
||||
/* Core 0 continues initialization. All other harts wait until the
|
||||
release flag is set by the low-level SMP initialization path. */
|
||||
/* Lockout interrupts while startup synchronization is in progress. */
|
||||
csrci mstatus, 0x08 // Lockout interrupts
|
||||
|
||||
/* Pickup current hart ID. */
|
||||
csrr t0, mhartid // Pickup current hart ID
|
||||
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:
|
||||
LWU t2, 0(t1) // Pickup release flag
|
||||
bnez t2, _tx_thread_smp_initialize_done // Exit once core 0 releases secondaries
|
||||
j _tx_thread_smp_initialize_wait_loop // Keep waiting
|
||||
/* Wait until ThreadX has acknowledged this hart by setting its
|
||||
system state to TX_INITIALIZE_IN_PROGRESS. */
|
||||
li t3, 0xF0F0F0F0 // TX_INITIALIZE_IN_PROGRESS
|
||||
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:
|
||||
ret
|
||||
|
||||
@@ -6,26 +6,4 @@
|
||||
.global _tx_thread_smp_low_level_initialize
|
||||
.type _tx_thread_smp_low_level_initialize, @function
|
||||
_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
|
||||
|
||||
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