Compare commits

..

55 Commits

Author SHA1 Message Date
alex 5b8c72cd9d changes ULONG to UINT32 for 64bit netxduo 2026-04-12 19:10:55 +02:00
alex 91632bcdee updates test for smp 2026-04-10 16:25:15 +02:00
alex 5b2da239d2 enables smp demo 2026-04-10 16:19:26 +02:00
alex 1165785154 formats file 2026-04-10 16:16:29 +02:00
alex ba39d23a18 adds hooks in bootup do move smp booting into the smp port lib 2026-04-10 14:40:21 +02:00
alex d97e71ca83 updates test to work with new build system 2026-04-10 14:13:18 +02:00
alex 4c15a3e15f enables tcp demo 2026-04-10 13:28:16 +02:00
alex 68057507c9 adds small cleanups towards updating the entire build system 2026-04-10 13:22:54 +02:00
alex 32df317b38 adds board header 2026-04-10 13:21:40 +02:00
alex 12ae01cda2 WIP: makes moonlight now the base library with no dependencies to be consumed by others 2026-04-10 13:14:40 +02:00
alex ff0f81e9c0 corrects bootup code
not tested if tls actually works
2026-04-10 13:14:04 +02:00
alex f989e21bad makes uart.h now also provide init 2026-04-10 13:13:05 +02:00
alex e3a7a9ccaf adds missing build system changes from a prio commit 2026-04-10 13:12:35 +02:00
alex c717297b30 removes more dependencies 2026-04-10 13:12:05 +02:00
alex b16a0ed956 splits low_level_init to allow usage of c file
this also makes threadx hook into the isrs
2026-04-10 13:10:50 +02:00
alex 21f95341af removes dependency of board.c to libc 2026-04-10 13:09:26 +02:00
alex 86025e020d moves linker script file into moonlight 2026-04-10 12:35:55 +02:00
alex 764ccd4a52 adds tracing to thread demo
this hardcodes the trace buffer
2026-04-10 10:13:14 +02:00
alex 27438ef6a5 also corrects LONG (not just ULONG) 2026-04-04 11:45:39 +02:00
alex f58aa42abd changes regression such that non-smp test run before smp tests 2026-04-02 14:52:02 +02:00
alex ac1fb36e2c adds MinSizeRel to the regression 2026-04-02 14:49:43 +02:00
alex c0386ea4a1 makes bootup code work for any number of cores 2026-04-02 14:26:24 +02:00
alex ffc49bc6a9 small formatting 2026-04-02 14:25:58 +02:00
alex 8772df619f adds 64 bit versions to regression 2026-04-02 11:38:16 +02:00
alex a6a6a034d6 removes convoluted generation of offsets
Ass ULONG is now 8 bytes on RV64, the SMP offset is the only one left, harcoding it as a magic number is simpler
2026-04-02 11:35:37 +02:00
alex 9212d40d86 adds newest version of patched threadx tests 2026-04-02 11:00:50 +02:00
alex c16e6b0446 adjust SMP port to also use ULONG = 8 bytes 2026-04-02 10:48:43 +02:00
alex eda2a85dc1 makes ULONG 64 bit on RV64 2026-04-02 10:31:12 +02:00
alex bdf3893bf2 updates latest image for regression 2026-04-01 18:21:20 +02:00
alex 8dfc5ab688 parallelizes ctest and build in regression 2026-03-31 22:52:50 +02:00
alex 856b5f9d32 updates threadx 2026-03-31 21:59:05 +02:00
alex 27fc04011c forces rebuild for cmake 2026-03-31 17:39:44 +02:00
alex bb79d43ff7 removes parallel build to enable searching for build error 2026-03-31 17:34:12 +02:00
alex 3cd42fcb10 adds submodules to checkout 2026-03-31 17:31:31 +02:00
alex ea1945983f Removes parameters for latest image and simulator path
also addresses latest error
2026-03-31 17:28:03 +02:00
alex dc30c46763 adds quote do cred ID 2026-03-31 17:24:38 +02:00
alex 0e0ad03e63 adds auth to docker login 2026-03-31 17:20:09 +02:00
alex 6b16e22ba6 next try at debugging the Jenkinsfile 2026-03-31 16:59:58 +02:00
alex f366a9211e adds Info for debugging 2026-03-31 16:51:52 +02:00
alex 9d698fb911 removes ansiColor step 2026-03-31 16:21:20 +02:00
alex 6e82d49488 adds Jenkinsfile 2026-03-31 16:13:53 +02:00
alex b5016c23b0 updates README 2026-03-31 16:13:45 +02:00
alex 824b71c283 adds csr.h to the moonlight port (adds duplicate as it is also in port/threadx/inc) 2026-03-31 16:13:34 +02:00
alex 7e2e162fe1 cleans up nx_port dependency 2026-03-31 16:09:44 +02:00
alex dd0c837930 corrects stack alignment 2026-03-30 19:48:09 +02:00
alex 870a5f9c36 adds newer version of threadx fork;
regression tx and smp now works for Debug32 and Release32
2026-03-26 16:18:04 +01:00
alex ab6c2d0bc4 adds newest version of threadx fork
ATP Debug32 passes all tx and smp regression tests
2026-03-26 15:56:47 +01:00
alex 8a41f3e0fa small cleanuo to smp asm files 2026-03-26 15:55:32 +01:00
alex 1aa9944581 corrects timeout for smp ctest 2026-03-25 09:27:44 +01:00
alex c9c2d2009f adds regression for smp 2026-03-25 08:49:20 +01:00
alex c11f68d20c initial test harness for smp regression 2026-03-24 18:00:50 +01:00
alex 7253aadd52 corrects alignment for 64bit in port 2026-03-24 14:38:16 +01:00
alex 24d22e42f6 moves threadx to minres fork 2026-03-24 14:37:47 +01:00
alex e02a58e25f switches to tohost based exit code, reducing complexity in deciding failure / pass 2026-03-23 16:58:56 +01:00
alex 4e87ae718b removes patching of kernel tets, as a correct testsuite requires a patched threadx anyways
This will not build, as atp threadx is still checked in clean
2026-03-23 16:32:33 +01:00
61 changed files with 1983 additions and 958 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
[submodule "third-party/threadx"] [submodule "third-party/threadx"]
path = third-party/threadx path = third-party/threadx
url = https://github.com/eclipse-threadx/threadx.git url = https://github.com/Minres/threadx.git
[submodule "third-party/netxduo"] [submodule "third-party/netxduo"]
path = third-party/netxduo path = third-party/netxduo
url = https://github.com/eclipse-threadx/netxduo.git url = https://github.com/eclipse-threadx/netxduo.git
+12 -21
View File
@@ -4,43 +4,44 @@ cmake_minimum_required(VERSION 3.21)
set(BUILD_SHARED_LIBS OFF) set(BUILD_SHARED_LIBS OFF)
include(${CMAKE_TOOLCHAIN_FILE}) include(${CMAKE_TOOLCHAIN_FILE})
############################################################################### ###############################################################################
add_subdirectory(port/moonlight)
set(TARGET_MEM "ram" CACHE STRING "memory map to use")
###############################################################################
# Adds picolibc # Adds picolibc
#set(CMAKE_SYSTEM_PROCESSOR riscv) #set(CMAKE_SYSTEM_PROCESSOR riscv)
set(__THREAD_LOCAL_STORAGE OFF) set(__THREAD_LOCAL_STORAGE OFF)
add_subdirectory(third-party/picolibc) add_subdirectory(third-party/picolibc)
#add_subdirectory(picolibc/semihost) #add_subdirectory(picolibc/semihost)
target_link_libraries(c PUBLIC gcc) target_sources(c PRIVATE ${CMAKE_CURRENT_LIST_DIR}/port/picolibc/port.c)
target_link_libraries(c PUBLIC moonlight gcc)
############################################################################### ###############################################################################
# Adds threadx # Adds threadx
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 moonlight)
#Adds threadx_smp #Adds threadx_smp
add_subdirectory(port/threadx_smp) add_subdirectory(port/threadx_smp)
target_link_libraries(threadx_smp PUBLIC c) target_link_libraries(threadx_smp PUBLIC c moonlight)
# Adds netxduo # Adds netxduo
set(NETXDUO_CUSTOM_PORT ${CMAKE_CURRENT_LIST_DIR}/port/threadx) set(NETXDUO_CUSTOM_PORT ${CMAKE_CURRENT_LIST_DIR}/port/netxduo)
set(NXD_ENABLE_FILE_SERVERS OFF) set(NXD_ENABLE_FILE_SERVERS OFF)
set(NX_USER_FILE ${CMAKE_CURRENT_LIST_DIR}/port/threadx/inc/nx_user.h)
add_subdirectory(third-party/netxduo) add_subdirectory(third-party/netxduo)
target_link_libraries(netxduo PUBLIC c)
if(NX_DEBUG) if(NX_DEBUG)
target_compile_definitions(netxduo PRIVATE NX_DEBUG NX_DEBUG_PACKET NX_ENABLE_PACKET_DEBUG_INFO) target_compile_definitions(netxduo PRIVATE NX_DEBUG NX_DEBUG_PACKET NX_ENABLE_PACKET_DEBUG_INFO)
endif() endif()
if(TX_TRACE) if(TX_TRACE)
target_compile_definitions(threadx PUBLIC TX_ENABLE_EVENT_TRACE)
target_compile_definitions(threadx_smp PUBLIC TX_ENABLE_EVENT_TRACE)
target_compile_definitions(netxduo PUBLIC TX_ENABLE_EVENT_TRACE) target_compile_definitions(netxduo PUBLIC TX_ENABLE_EVENT_TRACE)
endif() 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") option(TX_TRACE "Enable dump of traces to be read by TraceX" OFF)
set(CMAKE_EXECUTABLE_SUFFIX_C ".elf") set(CMAKE_EXECUTABLE_SUFFIX_C ".elf")
add_subdirectory(port/moonlight)
function(setup_target TARGET) function(setup_target TARGET)
set(options) set(options)
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)
@@ -51,12 +52,6 @@ function(setup_target TARGET)
set_target_properties(${TARGET} PROPERTIES set_target_properties(${TARGET} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
) )
target_add_moonlight_platform(${TARGET})
if("netxduo" IN_LIST ST_LIBRARIES)
target_add_moonlight_network_driver(${TARGET})
endif()
if(ST_SOURCES) if(ST_SOURCES)
target_sources(${TARGET} PRIVATE ${ST_SOURCES}) target_sources(${TARGET} PRIVATE ${ST_SOURCES})
endif() endif()
@@ -66,10 +61,6 @@ function(setup_target TARGET)
endif() endif()
target_link_options(${TARGET} PRIVATE target_link_options(${TARGET} PRIVATE
-nostartfiles
-nostdlib
-T ${CMAKE_SOURCE_DIR}/src/${TARGET_MEM}.lds
-Wl,--gc-sections
-Wl,-Map=${CMAKE_BINARY_DIR}/${TARGET}.map) -Wl,-Map=${CMAKE_BINARY_DIR}/${TARGET}.map)
add_custom_command(TARGET ${TARGET} POST_BUILD add_custom_command(TARGET ${TARGET} POST_BUILD
@@ -82,5 +73,5 @@ function(setup_target TARGET)
endfunction() endfunction()
setup_target(thread_demo LIBRARIES threadx SOURCES src/thread_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(tcp_demo LIBRARIES netxduo threadx SOURCES src/tcp_demo/main.c)
setup_target(smp_demo LIBRARIES threadx_smp SOURCES src/thread_demo/main.c) setup_target(smp_demo LIBRARIES threadx_smp SOURCES src/thread_demo/main.c)
Vendored
+158
View File
@@ -0,0 +1,158 @@
def suites = ['threadx', 'smp']
def presets = ['Debug32', 'Release32', 'MinSizeRel32','Debug', 'Release', 'MinSizeRel']
def simulatorImageLatest = 'git.minres.com/here/here-vp:latest'
def threadxTestSimulator = '/usr/local/bin/riscv-vp'
def runOneRegression(String suite, String preset, String simulatorPath) {
def suiteDir = "test/${suite}"
def buildDir = "../../build/${preset}/test/${suite}"
stage("${suite}-${preset}") {
dir(suiteDir) {
sh """
set -eu
test -n "${simulatorPath}"
test -x "${simulatorPath}"
cmake --fresh --preset "${preset}" \\
-DTHREADX_TEST_SIMULATOR="${simulatorPath}"
cmake --build --preset "${preset}" --parallel "\$(nproc)"
ctest \\
--test-dir "${buildDir}" \\
--output-on-failure \\
--output-junit "${buildDir}/ctest-results.xml" \\
--parallel "4"
"""
}
}
}
def resolveImageCommit(String image) {
withCredentials([usernamePassword(
credentialsId: 'gitea-jenkins',
usernameVariable: 'REGISTRY_USER',
passwordVariable: 'REGISTRY_PASS'
)]) {
return sh(
script: """
set -eu
echo "\$REGISTRY_PASS" | docker login "git.minres.com" -u "\$REGISTRY_USER" --password-stdin >/dev/null
docker pull "${image}" >/dev/null
docker image inspect --format='{{ index .Config.Labels "git-commit" }}' "${image}"
""",
returnStdout: true
).trim()
}
}
def runRegressionLane(String image, String simulatorPath, boolean allowFailure, List suiteNames, List presetNames) {
docker.image(image).inside {
sh '''
set -eu
cmake --version
ctest --version
'''
for (String suite : suiteNames) {
def suiteName = suite
def parallelTasks = [:]
for (String preset : presetNames) {
def presetName = preset
def taskName = "${suiteName}-${presetName}"
parallelTasks[taskName] = {
if (allowFailure) {
catchError(buildResult: 'UNSTABLE', stageResult: 'UNSTABLE') {
runOneRegression(suiteName, presetName, simulatorPath)
}
} else {
runOneRegression(suiteName, presetName, simulatorPath)
}
}
}
stage("${suiteName} Suite") {
parallel parallelTasks
}
}
}
}
properties([
parameters([
string(
name: 'SIMULATOR_IMAGE_PINNED',
defaultValue: 'git.minres.com/here/here-vp:4fcc192',
description: 'Version-pinned Docker image used for the blocking regression lane'
)
])
])
def canaryShouldRun = true
node {
timestamps {
try {
stage('Checkout') {
checkout scm
sh '''
git submodule sync --recursive
git submodule update --init --recursive
'''
}
stage('Check Canary Divergence') {
def pinnedCommit = resolveImageCommit(params.SIMULATOR_IMAGE_PINNED)
def latestCommit = resolveImageCommit(simulatorImageLatest)
if (!pinnedCommit) {
error "Missing git-commit label on ${params.SIMULATOR_IMAGE_PINNED}"
}
if (!latestCommit) {
error "Missing git-commit label on ${simulatorImageLatest}"
}
canaryShouldRun = (pinnedCommit != latestCommit)
if (canaryShouldRun) {
echo "Canary enabled: ${simulatorImageLatest} (${latestCommit}) diverges from ${params.SIMULATOR_IMAGE_PINNED} (${pinnedCommit})"
} else {
echo "Canary skipped: ${simulatorImageLatest} and ${params.SIMULATOR_IMAGE_PINNED} both use git-commit ${pinnedCommit}"
}
}
stage('Stable Regression') {
runRegressionLane(params.SIMULATOR_IMAGE_PINNED, threadxTestSimulator, false, suites, presets)
}
stage('Simulator Canary') {
if (canaryShouldRun) {
runRegressionLane(simulatorImageLatest, threadxTestSimulator, true, suites, presets)
} else {
echo 'Skipping canary lane because latest and pinned images are identical.'
}
}
} catch (err) {
currentBuild.result = 'FAILURE'
throw err
} finally {
junit allowEmptyResults: true, testResults: 'build/*/test/*/ctest-results.xml'
archiveArtifacts artifacts: 'build/*/test/*/Testing/**', allowEmptyArchive: true
if (currentBuild.currentResult == 'SUCCESS') {
rocketSend ":thumbsup: ThreadX regression run passed, results at ${env.RUN_DISPLAY_URL} "
} else if (currentBuild.currentResult == 'UNSTABLE') {
rocketSend ":warning: ThreadX canary regression is unstable on ${simulatorImageLatest}, please check ${env.RUN_DISPLAY_URL} "
} else if (currentBuild.currentResult == 'FAILURE') {
archiveArtifacts artifacts: 'failed_seeds_*.txt', followSymlinks: false, onlyIfSuccessful: false
rocketSend ":thumbsdown: ThreadX regression failed, please check ${env.RUN_DISPLAY_URL} "
emailext recipientProviders: [culprits(), requestor()],
subject: "ThreadX Pipeline Failed: ${currentBuild.fullDisplayName}",
body: """
<p>Build Status: ${currentBuild.currentResult}</p>
<p> Check logs at <a href='${env.BUILD_URL}console'> Build Console Logs </a> or at <a href='${env.RUN_DISPLAY_URL}'> Overview </a></p>
"""
}
}
}
}
+33 -6
View File
@@ -1,19 +1,46 @@
# Running the RTOS # ThreadX Port for the TGFS cores and accompanying Virtual prototypes
This repositiory contains prototypical RISC-V implementation of ThreadX designed to run on the RISC-V VP by MINRES (tested on commit [d96cd4a](https://github.com/Minres/RISCV-VP/tree/d96cd4a01de1f4bcc77db3eceb57f5c144395847)). This repositiory contains a RISC-V implementation of ThreadX designed to run on the TGFS cores or the RISC-V VP by MINRES (available on [Github](https://github.com/Minres/RISCV-VP/tree/d96cd4a01de1f4bcc77db3eceb57f5c144395847)).
**Note**: SMP support additionally requires a VP variant that allows the number of cores to be configured.
## Building the RTOS ## Building the RTOS
Four presets are provided, targetting RV32 and RV64 combined with GC or IMAC. The presets use rv32imac and rv64imac. A set of presets is provided, targetting 32 and 64-bit systems.
E.g. building for the RV64IMAC configuration:
```bash
cmake --preset Debug
cmake --build --preset Debug --parallel
```
## Running on the VP ## Running on the VP
A run command can look like this: A run command can look like this:
```bash ```bash
riscv-vp --isa=rv64gc_m -f build/Debug/main.elf riscv-vp --isa=rv64imac_m -f build/Debug/thread_demo.elf
``` ```
## What is running? ## Running the Regression Suites
The current implementation is just a demo, taken from the existing threadx qemu implementation. The regression suites live in test/. Both suites register their cases with CTest and require the path to the MINRES `riscv-vp` simulator to be provided through `THREADX_TEST_SIMULATOR`.
The SMP regression suite additionally requires a `riscv-vp` variant that supports a configurable number of cores.
Examples:
```bash
cmake -S test/threadx --preset Debug32 -DTHREADX_TEST_SIMULATOR=/opt/riscv-vp/bin/riscv-vp
cmake --build --preset Debug32 --parallel
ctest --test-dir ../../build/Debug32/test/threadx --output-on-failure --parallel 4
```
## Demo Applications
The repository currently provides three demo applications:
- `thread_demo`: a basic single-kernel ThreadX demo based on the standard ThreadX sample application
- `smp_demo`: the same basic demo application for running on a ThreadX SMP kernel
- `tcp_demo`: a NetX Duo demo that exercises the TCP/IP stack on top of ThreadX
+27 -48
View File
@@ -1,62 +1,41 @@
cmake_minimum_required(VERSION 3.21)
project(moonlight LANGUAGES C)
set(MOONLIGHT_ROOT ${CMAKE_CURRENT_LIST_DIR}) set(MOONLIGHT_ROOT ${CMAKE_CURRENT_LIST_DIR})
set(THREADX4TGFS_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)
set(MOONLIGHT_SRC_DIR ${MOONLIGHT_ROOT}/src)
set(MOONLIGHT_INC_DIR ${MOONLIGHT_ROOT}/inc) set(MOONLIGHT_INC_DIR ${MOONLIGHT_ROOT}/inc)
set(MOONLIGHT_SRC_DIR ${MOONLIGHT_ROOT}/src)
set(MOONLIGHT_LDS_DIR ${MOONLIGHT_ROOT}/lds)
if(NOT DEFINED TARGET_MEM)
set(TARGET_MEM "ram" CACHE STRING "memory map to use")
endif()
if(NOT DEFINED MOONLIGHT_TRAP_SOURCE) if(NOT DEFINED MOONLIGHT_TRAP_SOURCE)
set(MOONLIGHT_TRAP_SOURCE ${MOONLIGHT_SRC_DIR}/trap_non_vectored.c) set(MOONLIGHT_TRAP_SOURCE ${MOONLIGHT_SRC_DIR}/trap_non_vectored.c)
endif() endif()
set(MOONLIGHT_PLATFORM_SOURCES add_library(moonlight STATIC
${THREADX4TGFS_ROOT}/port/picolibc/port.c
${MOONLIGHT_SRC_DIR}/bootup.c
${MOONLIGHT_SRC_DIR}/board.c ${MOONLIGHT_SRC_DIR}/board.c
${MOONLIGHT_TRAP_SOURCE} ${MOONLIGHT_SRC_DIR}/bootup.c
${MOONLIGHT_SRC_DIR}/exception.c ${MOONLIGHT_SRC_DIR}/exception.c
${MOONLIGHT_SRC_DIR}/vector_table.c) ${MOONLIGHT_TRAP_SOURCE}
)
add_library(moonlight_platform_defaults INTERFACE) target_include_directories(moonlight PUBLIC ${MOONLIGHT_INC_DIR})
target_include_directories(moonlight_platform_defaults INTERFACE target_link_directories(moonlight INTERFACE ${MOONLIGHT_LDS_DIR})
${MOONLIGHT_INC_DIR}
${THREADX4TGFS_ROOT}/src) target_compile_options(moonlight
target_compile_options(moonlight_platform_defaults INTERFACE PUBLIC
-ffreestanding -ffreestanding
-fno-builtin -fno-builtin
-fdata-sections -fdata-sections
-ffunction-sections) -ffunction-sections
target_link_directories(moonlight_platform_defaults INTERFACE )
${THREADX4TGFS_ROOT}/src)
if(NX_DEBUG)
target_compile_definitions(moonlight_platform_defaults INTERFACE
NX_DEBUG
NX_DEBUG_PACKET)
endif()
add_library(moonlight_platform_common OBJECT target_link_options(moonlight
${MOONLIGHT_PLATFORM_SOURCES}) INTERFACE
target_link_libraries(moonlight_platform_common PUBLIC -nostartfiles
moonlight_platform_defaults -T ${MOONLIGHT_LDS_DIR}/${TARGET_MEM}.lds
c -Wl,--gc-sections
threadx) )
if(DEFINED NETXDUO_CUSTOM_PORT)
add_library(moonlight_network_driver OBJECT
${MOONLIGHT_SRC_DIR}/mnrs_network_driver.c)
target_link_libraries(moonlight_network_driver PUBLIC
moonlight_platform_defaults
c
threadx
netxduo)
endif()
function(target_add_moonlight_platform TARGET)
target_link_libraries(${TARGET} PRIVATE moonlight_platform_common)
endfunction()
function(target_add_moonlight_network_driver TARGET)
if(NOT TARGET moonlight_network_driver)
message(FATAL_ERROR "moonlight_network_driver requires netxduo to be available in this build")
endif()
target_link_libraries(${TARGET} PRIVATE moonlight_network_driver)
endfunction()
+4
View File
@@ -0,0 +1,4 @@
int uart_putc(int ch);
int uart_getc(void);
int board_init(void);
int register_irq_handler(unsigned irq_num, void (*handler)());
+371
View File
@@ -0,0 +1,371 @@
/***************************************************************************
* 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
**************************************************************************/
#ifndef CSR_H
#define CSR_H
// Machine Status Register, mstatus
#define MSTATUS_MPP_MASK (3L << 11) // previous mode.
#define MSTATUS_MPP_M (3L << 11)
#define MSTATUS_MPP_S (1L << 11)
#define MSTATUS_MPP_U (0L << 11)
#define MSTATUS_MIE (1L << 3) // machine-mode interrupt enable.
#define MSTATUS_MPIE (1L << 7)
#define MSTATUS_FS (1L << 13)
// Machine-mode Interrupt Enable
#define MIE_MTIE (1L << 7)
#define MIE_MSIE (1L << 3)
#define MIE_MEIE (1L << 11)
#define MIE_STIE (1L << 5) // supervisor timer
#define MIE_SSIE (1L << 1)
#define MIE_SEIE (1L << 9)
// Supervisor Status Register, sstatus
#define SSTATUS_SPP (1L << 8) // Previous mode, 1=Supervisor, 0=User
#define SSTATUS_SPIE (1L << 5) // Supervisor Previous Interrupt Enable
#define SSTATUS_UPIE (1L << 4) // User Previous Interrupt Enable
#define SSTATUS_SIE (1L << 1) // Supervisor Interrupt Enable
#define SSTATUS_UIE (1L << 0) // User Interrupt Enable
#define SSTATUS_SPIE (1L << 5)
#define SSTATUS_UPIE (1L << 4)
// Supervisor Interrupt Enable
#define SIE_SEIE (1L << 9) // external
#define SIE_STIE (1L << 5) // timer
#define SIE_SSIE (1L << 1) // software
#ifndef __ASSEMBLER__
#include <stdint.h>
static inline uint64_t riscv_get_core()
{
uint64_t x;
asm volatile("csrr %0, mhartid" : "=r"(x));
return x;
}
static inline uint64_t riscv_get_mstatus()
{
uint64_t x;
asm volatile("csrr %0, mstatus" : "=r"(x));
return x;
}
static inline void riscv_writ_mstatus(uint64_t x)
{
asm volatile("csrw mstatus, %0" : : "r"(x));
}
// machine exception program counter, holds the
// instruction address to which a return from
// exception will go.
static inline void riscv_writ_mepc(uint64_t x)
{
asm volatile("csrw mepc, %0" : : "r"(x));
}
static inline uint64_t riscv_get_sstatus()
{
uint64_t x;
asm volatile("csrr %0, sstatus" : "=r"(x));
return x;
}
static inline void riscv_writ_sstatus(uint64_t x)
{
asm volatile("csrw sstatus, %0" : : "r"(x));
}
// Supervisor Interrupt Pending
static inline uint64_t riscv_get_sip()
{
uint64_t x;
asm volatile("csrr %0, sip" : "=r"(x));
return x;
}
static inline void riscv_writ_sip(uint64_t x)
{
asm volatile("csrw sip, %0" : : "r"(x));
}
static inline uint64_t riscv_get_sie()
{
uint64_t x;
asm volatile("csrr %0, sie" : "=r"(x));
return x;
}
static inline void riscv_writ_sie(uint64_t x)
{
asm volatile("csrw sie, %0" : : "r"(x));
}
static inline uint64_t riscv_get_mie()
{
uint64_t x;
asm volatile("csrr %0, mie" : "=r"(x));
return x;
}
static inline void riscv_writ_mie(uint64_t x)
{
asm volatile("csrw mie, %0" : : "r"(x));
}
// supervisor exception program counter, holds the
// instruction address to which a return from
// exception will go.
static inline void riscv_writ_sepc(uint64_t x)
{
asm volatile("csrw sepc, %0" : : "r"(x));
}
static inline uint64_t riscv_get_sepc()
{
uint64_t x;
asm volatile("csrr %0, sepc" : "=r"(x));
return x;
}
// Machine Exception Delegation
static inline uint64_t riscv_get_medeleg()
{
uint64_t x;
asm volatile("csrr %0, medeleg" : "=r"(x));
return x;
}
static inline void riscv_writ_medeleg(uint64_t x)
{
asm volatile("csrw medeleg, %0" : : "r"(x));
}
// Machine Interrupt Delegation
static inline uint64_t riscv_get_mideleg()
{
uint64_t x;
asm volatile("csrr %0, mideleg" : "=r"(x));
return x;
}
static inline void riscv_writ_mideleg(uint64_t x)
{
asm volatile("csrw mideleg, %0" : : "r"(x));
}
// Supervisor Trap-Vector Base Address
// low two bits are mode.
static inline void riscv_writ_stvec(uint64_t x)
{
asm volatile("csrw stvec, %0" : : "r"(x));
}
static inline uint64_t riscv_get_stvec()
{
uint64_t x;
asm volatile("csrr %0, stvec" : "=r"(x));
return x;
}
// Supervisor Timer Comparison Register
static inline uint64_t riscv_get_stimecmp()
{
uint64_t x;
// asm volatile("csrr %0, stimecmp" : "=r" (x) );
asm volatile("csrr %0, 0x14d" : "=r"(x));
return x;
}
static inline void riscv_writ_stimecmp(uint64_t x)
{
// asm volatile("csrw stimecmp, %0" : : "r" (x));
asm volatile("csrw 0x14d, %0" : : "r"(x));
}
// Machine Environment Configuration Register
static inline uint64_t riscv_get_menvcfg()
{
uint64_t x;
// asm volatile("csrr %0, menvcfg" : "=r" (x) );
asm volatile("csrr %0, 0x30a" : "=r"(x));
return x;
}
static inline void riscv_writ_menvcfg(uint64_t x)
{
// asm volatile("csrw menvcfg, %0" : : "r" (x));
asm volatile("csrw 0x30a, %0" : : "r"(x));
}
// Physical Memory Protection
static inline void riscv_writ_pmpcfg0(uint64_t x)
{
asm volatile("csrw pmpcfg0, %0" : : "r"(x));
}
static inline void riscv_writ_pmpaddr0(uint64_t x)
{
asm volatile("csrw pmpaddr0, %0" : : "r"(x));
}
// supervisor address translation and protection;
// holds the address of the page table.
static inline void riscv_writ_satp(uint64_t x)
{
asm volatile("csrw satp, %0" : : "r"(x));
}
static inline uint64_t riscv_get_satp()
{
uint64_t x;
asm volatile("csrr %0, satp" : "=r"(x));
return x;
}
// Supervisor Trap Cause
static inline uint64_t riscv_get_scause()
{
uint64_t x;
asm volatile("csrr %0, scause" : "=r"(x));
return x;
}
// Supervisor Trap Value
static inline uint64_t riscv_get_stval()
{
uint64_t x;
asm volatile("csrr %0, stval" : "=r"(x));
return x;
}
// Machine-mode Counter-Enable
static inline void riscv_writ_mcounteren(uint64_t x)
{
asm volatile("csrw mcounteren, %0" : : "r"(x));
}
static inline uint64_t riscv_get_mcounteren()
{
uint64_t x;
asm volatile("csrr %0, mcounteren" : "=r"(x));
return x;
}
// machine-mode cycle counter
static inline uint64_t riscv_get_time()
{
uint64_t x;
asm volatile("csrr %0, time" : "=r"(x));
return x;
}
// enable device interrupts
static inline void riscv_sintr_on()
{
uint64_t sstatus = riscv_get_sstatus();
sstatus |= SSTATUS_SIE;
riscv_writ_sstatus(sstatus);
}
// disable device interrupts
static inline void riscv_sintr_off()
{
uint64_t sstatus = riscv_get_sstatus();
sstatus &= (~SSTATUS_SIE);
riscv_writ_sstatus(sstatus);
}
// are device interrupts enabled?
static inline int riscv_sintr_get()
{
uint64_t x = riscv_get_sstatus();
return (x & SSTATUS_SIE) != 0;
}
static inline void riscv_sintr_restore(int x)
{
if (x)
riscv_sintr_on();
else
riscv_sintr_off();
}
// enable device interrupts
static inline void riscv_mintr_on()
{
uint64_t mstatus = riscv_get_mstatus();
mstatus |= MSTATUS_MIE;
riscv_writ_mstatus(mstatus);
}
// disable device interrupts
static inline void riscv_mintr_off()
{
uint64_t mstatus = riscv_get_mstatus();
mstatus &= (~MSTATUS_MIE);
riscv_writ_mstatus(mstatus);
}
// are device interrupts enabled?
static inline int riscv_mintr_get()
{
uint64_t x = riscv_get_mstatus();
return (x & MSTATUS_MIE) != 0;
}
static inline void riscv_mintr_restore(int x)
{
if (x)
riscv_mintr_on();
else
riscv_mintr_off();
}
static inline uint64_t riscv_get_sp()
{
uint64_t x;
asm volatile("mv %0, sp" : "=r"(x));
return x;
}
// read and write tp, the thread pointer, which xv6 uses to hold
// this core's hartid (core number), the index into cpus[].
static inline uint64_t riscv_get_tp()
{
uint64_t x;
asm volatile("mv %0, tp" : "=r"(x));
return x;
}
static inline void riscv_writ_tp(uint64_t x)
{
asm volatile("mv tp, %0" : : "r"(x));
}
static inline uint64_t riscv_get_ra()
{
uint64_t x;
asm volatile("mv %0, ra" : "=r"(x));
return x;
}
// flush the TLB.
static inline void sfence_vma()
{
// the zero, zero means flush all TLB entries.
asm volatile("sfence.vma zero, zero");
}
#endif // __ASSEMBLER__
#endif
+4
View File
@@ -33,4 +33,8 @@ static inline uint8_t uart_read(volatile uart_t* reg)
return res; return res;
} }
static inline int uart_init(void)
{
return 0;
}
#endif /* _DEVICES_UART_H */ #endif /* _DEVICES_UART_H */
-7
View File
@@ -2,8 +2,6 @@
#include "csr.h" #include "csr.h"
#include "platform.h" #include "platform.h"
#include "uart.h" #include "uart.h"
#include <stdio.h>
#include <stdarg.h>
// needed by picolibc/port.c // needed by picolibc/port.c
int uart_putc(int ch) { int uart_putc(int ch) {
@@ -22,11 +20,6 @@ int uart_getc(void) {
return ch; return ch;
} }
int uart_init(void) {
puts("[UART0] : Uart Init Done, this is Test output!");
return 0;
};
int board_init(void) { int board_init(void) {
int ret; int ret;
ret = uart_init(); ret = uart_init();
+32 -10
View File
@@ -6,10 +6,9 @@
*/ */
#include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <picotls.h>
#include <tx_port.h>
#include <riscv-csr.h> #include <riscv-csr.h>
#ifdef __cplusplus #ifdef __cplusplus
#define EXTERN_C extern "C" #define EXTERN_C extern "C"
@@ -37,6 +36,7 @@ EXTERN_C function_t __init_array_start;
EXTERN_C function_t __init_array_end; EXTERN_C function_t __init_array_end;
EXTERN_C function_t __fini_array_start; EXTERN_C function_t __fini_array_start;
EXTERN_C function_t __fini_array_end; EXTERN_C function_t __fini_array_end;
EXTERN_C volatile uintptr_t tohost;
// This function will be placed by the linker script according to the section // This function will be placed by the linker script according to the section
// Raw function 'called' by the CPU with no runtime. // Raw function 'called' by the CPU with no runtime.
@@ -44,11 +44,17 @@ EXTERN_C void _start(void) __attribute__ ((naked,section(".text.boot")));
// Entry and exit points as C functions. // Entry and exit points as C functions.
EXTERN_C void _initialize(void) __attribute__ ((noreturn,section(".text.boot"))); EXTERN_C void _initialize(void) __attribute__ ((noreturn,section(".text.boot")));
EXTERN_C void _secondary_initialize(void) __attribute__ ((noreturn,section(".text.boot"),weak));
EXTERN_C void _exit(int exit_code) __attribute__ ((noreturn,noinline,weak)); EXTERN_C void _exit(int exit_code) __attribute__ ((noreturn,noinline,weak));
EXTERN_C void bootup_wake_secondary_cores(void) __attribute__ ((weak));
// Standard entry point, no arguments. // Standard entry point, no arguments.
extern int main(void); extern int main(void);
#ifdef __THREAD_LOCAL_STORAGE
EXTERN_C void _set_tls(uint8_t*) __attribute__ ((noreturn,section(".text.boot")));
#endif
// 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.
// tp will not be initialized // tp will not be initialized
@@ -73,15 +79,16 @@ void _start(void) {
"la t1, __stack_size;" "la t1, __stack_size;"
"la sp, _sp;" "la sp, _sp;"
// Loop incase M extension is not present // Loop incase M extension is not present
"mv t2, t0;"
"1:;" "1:;"
"beqz t0, 2f;" "beqz t2, 2f;"
"sub sp, sp, t1;" "sub sp, sp, t1;"
"addi t0, t0, -1;" "addi t2, t2, -1;"
"j 1b;" "j 1b;"
"2:;" "2:;"
#ifdef TX_THREAD_SMP_MAX_CORES "beqz t0, 3f;"
"call _tx_thread_smp_initialize_wait;" "jal zero, _secondary_initialize;"
#endif "3:;"
"jal zero, _initialize;" "jal zero, _initialize;"
: /* output: none %0 */ : /* output: none %0 */
: /* input: none */ : /* input: none */
@@ -106,6 +113,7 @@ void _initialize(void) {
++entry) { ++entry) {
(*entry)(); (*entry)();
} }
bootup_wake_secondary_cores();
#ifdef __THREAD_LOCAL_STORAGE #ifdef __THREAD_LOCAL_STORAGE
_set_tls(__tls_base) _set_tls(__tls_base)
#endif #endif
@@ -119,9 +127,23 @@ void _initialize(void) {
_exit(rc); _exit(rc);
} }
// This should never be called. Busy loop with the CPU in idle state. void _secondary_initialize(void) {
void _exit(int exit_code) { // sleep forever
(void)exit_code; csr_clr_bits_mie(MIE_MTI_BIT_MASK);
csr_clr_bits_mstatus(MSTATUS_MIE_BIT_MASK);
while (1) {
__asm__ volatile ("wfi");
}
}
void bootup_wake_secondary_cores(void) {
}
// This should never be called. Report the exit code through HTIF and idle the CPU.
void _exit(int exit_code) {
uintptr_t htif_exit_code = (((uintptr_t)(unsigned int)exit_code) << 1) | 1u;
tohost = htif_exit_code;
csr_clr_bits_mie(MIE_MTI_BIT_MASK); csr_clr_bits_mie(MIE_MTI_BIT_MASK);
csr_clr_bits_mstatus(MSTATUS_MIE_BIT_MASK); csr_clr_bits_mstatus(MSTATUS_MIE_BIT_MASK);
while (1) { while (1) {
-20
View File
@@ -3,8 +3,6 @@
#include "riscv-traps.h" #include "riscv-traps.h"
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <tx_api.h>
#include <tx_port.h>
#if __riscv_xlen == 64 #if __riscv_xlen == 64
#define INTERRUPT_BIT 0x8000000000000000ull #define INTERRUPT_BIT 0x8000000000000000ull
@@ -16,7 +14,6 @@
#define OS_IS_SOFT_INT(mcause) (mcause == (0x3 | INTERRUPT_BIT)) #define OS_IS_SOFT_INT(mcause) (mcause == (0x3 | INTERRUPT_BIT))
#define OS_IS_EXT_INT(mcause) (mcause == (0xb | INTERRUPT_BIT)) #define OS_IS_EXT_INT(mcause) (mcause == (0xb | INTERRUPT_BIT))
extern void _tx_timer_interrupt(void);
extern uintptr_t exception(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval); extern uintptr_t exception(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval);
void (*irq_handler[__riscv_xlen])(); void (*irq_handler[__riscv_xlen])();
@@ -33,23 +30,6 @@ void trap_handler(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval) {
if(OS_IS_INTERRUPT(mcause)) { if(OS_IS_INTERRUPT(mcause)) {
unsigned irq_id = mcause&(__riscv_xlen-1); unsigned irq_id = mcause&(__riscv_xlen-1);
switch(irq_id){ switch(irq_id){
case RISCV_INT_MTI:
#ifdef NX_DEBUG
printf("Timer interrupt being handled (pc=%lx)\n", mepc);
#endif
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)
;
break;
default: default:
if(irq_handler[irq_id]) if(irq_handler[irq_id])
irq_handler[irq_id](); irq_handler[irq_id]();
+12
View File
@@ -0,0 +1,12 @@
target_sources(${PROJECT_NAME}
PRIVATE
# {{BEGIN_TARGET_SOURCES}}
${CMAKE_CURRENT_LIST_DIR}/src/mnrs_network_driver.c
# {{END_TARGET_SOURCES}}
)
target_include_directories(${PROJECT_NAME}
PUBLIC
${CMAKE_CURRENT_LIST_DIR}/inc
)
@@ -47,7 +47,6 @@
#ifndef NX_PORT_H #ifndef NX_PORT_H
#define NX_PORT_H #define NX_PORT_H
#include "tx_port.h"
/* Determine if the optional NetX user define file should be used. */ /* Determine if the optional NetX user define file should be used. */
#ifdef NX_INCLUDE_USER_DEFINE_FILE #ifdef NX_INCLUDE_USER_DEFINE_FILE
@@ -57,6 +56,9 @@
#include "nx_user.h" #include "nx_user.h"
#endif #endif
#include "tx_port.h"
typedef unsigned int UINT32;
_Static_assert(sizeof(UINT32) == 4, "UINT32 must be 4 bytes");
/* Default to little endian, since this is what most RISC-V targets are. */ /* Default to little endian, since this is what most RISC-V targets are. */
@@ -64,10 +66,10 @@
/* Define macros that swap the endian for little endian ports. */ /* Define macros that swap the endian for little endian ports. */
#ifdef NX_LITTLE_ENDIAN #ifdef NX_LITTLE_ENDIAN
#define NX_CHANGE_ULONG_ENDIAN(arg) \ #define NX_CHANGE_UINT32_ENDIAN(arg) \
{ \ { \
ULONG _i; \ UINT32 _i; \
ULONG _tmp; \ UINT32 _tmp; \
_i = (UINT)arg; \ _i = (UINT)arg; \
/* _i = A, B, C, D */ \ /* _i = A, B, C, D */ \
_tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \
@@ -83,11 +85,11 @@
#define NX_CHANGE_USHORT_ENDIAN(a) (a = (((a >> 8) | (a << 8)) & 0xFFFF)) #define NX_CHANGE_USHORT_ENDIAN(a) (a = (((a >> 8) | (a << 8)) & 0xFFFF))
#ifndef htonl #ifndef htonl
#define htonl(val) NX_CHANGE_ULONG_ENDIAN(val) #define htonl(val) NX_CHANGE_UINT32_ENDIAN(val)
#endif /* htonl */ #endif /* htonl */
#ifndef ntohl #ifndef ntohl
#define ntohl(val) NX_CHANGE_ULONG_ENDIAN(val) #define ntohl(val) NX_CHANGE_UINT32_ENDIAN(val)
#endif /* ntohl */ #endif /* ntohl */
#ifndef htons #ifndef htons
@@ -100,7 +102,7 @@
#else #else
#define NX_CHANGE_ULONG_ENDIAN(a) #define NX_CHANGE_UINT32_ENDIAN(a)
#define NX_CHANGE_USHORT_ENDIAN(a) #define NX_CHANGE_USHORT_ENDIAN(a)
#ifndef htons #ifndef htons
@@ -139,7 +139,6 @@
/* /*
#define NX_DISABLE_IPV6 #define NX_DISABLE_IPV6
*/ */
/* Define the number of entries in IPv6 address pool. */ /* Define the number of entries in IPv6 address pool. */
/* /*
#ifdef NX_MAX_PHYSICAL_INTERFACES #ifdef NX_MAX_PHYSICAL_INTERFACES
@@ -66,8 +66,8 @@ extern int register_irq_handler(unsigned irq_num, void (*handler)());
/* For the ethernet driver, physical addresses are allocated starting /* For the ethernet driver, physical addresses are allocated starting
at the preset value and then incremented before the next allocation. */ at the preset value and then incremented before the next allocation. */
// Locally Administered Addresses that can be assigned by network, range is 02-00-00 to 02-00-5E // Locally Administered Addresses that can be assigned by network, range is 02-00-00 to 02-00-5E
const ULONG mnrs_mac_address_msw = 0x0200; const UINT32 mnrs_mac_address_msw = 0x0200;
const ULONG mnrs_mac_address_lsw = 0x00334450; const UINT32 mnrs_mac_address_lsw = 0x00334450;
/* Define driver prototypes. */ /* Define driver prototypes. */
VOID nx_mnrs_network_driver(NX_IP_DRIVER* driver_req_ptr); VOID nx_mnrs_network_driver(NX_IP_DRIVER* driver_req_ptr);
@@ -81,8 +81,8 @@ static VOID _nx_mnrs_eth_recv_packet_eth1(VOID);
#define NX_MNRS_DRIVER_MAX_MCAST_ADDRESSES 3 #define NX_MNRS_DRIVER_MAX_MCAST_ADDRESSES 3
typedef struct MAC_ADDRESS_STRUCT typedef struct MAC_ADDRESS_STRUCT
{ {
ULONG nx_mac_address_msw; UINT32 nx_mac_address_msw;
ULONG nx_mac_address_lsw; UINT32 nx_mac_address_lsw;
} MAC_ADDRESS; } MAC_ADDRESS;
/* Define an application-specific data structure that holds internal /* Define an application-specific data structure that holds internal
@@ -173,7 +173,7 @@ VOID nx_mnrs_network_driver(NX_IP_DRIVER* driver_req_ptr)
UINT interface_index; UINT interface_index;
USHORT ether_type; USHORT ether_type;
#ifndef NX_ENABLE_VLAN #ifndef NX_ENABLE_VLAN
ULONG* ethernet_frame_ptr; UINT32* ethernet_frame_ptr;
#endif /* NX_ENABLE_VLAN */ #endif /* NX_ENABLE_VLAN */
/* Setup the IP pointer from the driver request. */ /* Setup the IP pointer from the driver request. */
@@ -408,7 +408,7 @@ VOID nx_mnrs_network_driver(NX_IP_DRIVER* driver_req_ptr)
/* Setup the ethernet frame pointer to build the ethernet frame. Backup another 2 /* Setup the ethernet frame pointer to build the ethernet frame. Backup another 2
bytes to get 32-bit word alignment. */ bytes to get 32-bit word alignment. */
/*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */ /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
ethernet_frame_ptr = (ULONG*)(packet_ptr->nx_packet_prepend_ptr - 2); ethernet_frame_ptr = (UINT32*)(packet_ptr->nx_packet_prepend_ptr - 2);
/* Build the ethernet frame. */ /* Build the ethernet frame. */
*ethernet_frame_ptr = driver_req_ptr->nx_ip_driver_physical_address_msw; *ethernet_frame_ptr = driver_req_ptr->nx_ip_driver_physical_address_msw;
*(ethernet_frame_ptr + 1) = driver_req_ptr->nx_ip_driver_physical_address_lsw; *(ethernet_frame_ptr + 1) = driver_req_ptr->nx_ip_driver_physical_address_lsw;
@@ -416,10 +416,10 @@ VOID nx_mnrs_network_driver(NX_IP_DRIVER* driver_req_ptr)
(interface_ptr->nx_interface_physical_address_lsw >> 16); (interface_ptr->nx_interface_physical_address_lsw >> 16);
*(ethernet_frame_ptr + 3) = (interface_ptr->nx_interface_physical_address_lsw << 16) | ether_type; *(ethernet_frame_ptr + 3) = (interface_ptr->nx_interface_physical_address_lsw << 16) | ether_type;
/* Endian swapping if NX_LITTLE_ENDIAN is defined. */ /* Endian swapping if NX_LITTLE_ENDIAN is defined. */
NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr)); NX_CHANGE_UINT32_ENDIAN(*(ethernet_frame_ptr));
NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 1)); NX_CHANGE_UINT32_ENDIAN(*(ethernet_frame_ptr + 1));
NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 2)); NX_CHANGE_UINT32_ENDIAN(*(ethernet_frame_ptr + 2));
NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 3)); NX_CHANGE_UINT32_ENDIAN(*(ethernet_frame_ptr + 3));
#endif /* NX_ENABLE_VLAN */ #endif /* NX_ENABLE_VLAN */
#ifdef NX_DEBUG_PACKET #ifdef NX_DEBUG_PACKET
printf("NetX MNRS ETH Driver Packet Send - %s\n", ip_ptr->nx_ip_name); printf("NetX MNRS ETH Driver Packet Send - %s\n", ip_ptr->nx_ip_name);
@@ -840,11 +840,11 @@ void _nx_mnrs_network_driver_receive(NX_IP* ip_ptr, NX_PACKET* packet_ptr, UINT
UINT _nx_mnrs_eth_send_packet(NX_PACKET* packet_ptr, volatile ethmac_t* ethmac) UINT _nx_mnrs_eth_send_packet(NX_PACKET* packet_ptr, volatile ethmac_t* ethmac)
{ {
ULONG size = 0; UINT32 size = 0;
UCHAR* data; UCHAR* data;
UINT i; UINT i;
ULONG buffer; UINT32 buffer;
ULONG words; UINT32 words;
/* Make sure the data length is less than MTU. */ /* Make sure the data length is less than MTU. */
if (packet_ptr->nx_packet_length > NX_MAX_PACKET_SIZE) if (packet_ptr->nx_packet_length > NX_MAX_PACKET_SIZE)
@@ -967,7 +967,7 @@ VOID _nx_mnrs_eth_recv_packet(UINT i)
VOID _nx_mnrs_eth_recv_packet_eth0(VOID) VOID _nx_mnrs_eth_recv_packet_eth0(VOID)
{ {
ULONG old_threshold; UINT32 old_threshold;
if (get_ethmac_mac_ctrl_rx_pending(ethmac0)) if (get_ethmac_mac_ctrl_rx_pending(ethmac0))
{ {
@@ -986,7 +986,7 @@ VOID _nx_mnrs_eth_recv_packet_eth0(VOID)
VOID _nx_mnrs_eth_recv_packet_eth1(VOID) VOID _nx_mnrs_eth_recv_packet_eth1(VOID)
{ {
ULONG old_threshold; UINT32 old_threshold;
if (get_ethmac_mac_ctrl_rx_pending(ethmac1)) if (get_ethmac_mac_ctrl_rx_pending(ethmac1))
{ {
+1 -3
View File
@@ -1,8 +1,6 @@
#include <stdio.h> #include <stdio.h>
#include <sys/types.h> #include <sys/types.h>
#include "board.h"
extern void uart_putc(char c);
extern int uart_getc(void);
static int static int
board_putc(char c, FILE *file) board_putc(char c, FILE *file)
+7 -1
View File
@@ -1,8 +1,14 @@
#required for tests to hook into the ISR path
if(NOT DEFINED THREADX_LOW_LEVEL_INIT_SOURCE)
set(THREADX_LOW_LEVEL_INIT_SOURCE
${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.c)
endif()
target_sources(${PROJECT_NAME} target_sources(${PROJECT_NAME}
PRIVATE PRIVATE
# {{BEGIN_TARGET_SOURCES}} # {{BEGIN_TARGET_SOURCES}}
${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S ${CMAKE_CURRENT_LIST_DIR}/src/trap_entry.S
${THREADX_LOW_LEVEL_INIT_SOURCE}
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S
+2 -5
View File
@@ -67,8 +67,6 @@
#define LOG_REGBYTES 2 #define LOG_REGBYTES 2
#endif #endif
#define REGBYTES (1 << LOG_REGBYTES) #define REGBYTES (1 << LOG_REGBYTES)
#define TX_THREAD_STACK_END_OFFSET 2 * 4 + 2 * REGBYTES
#define TX_THREAD_TIME_SLICE_OFFSET 3 * 4 + 3 * REGBYTES
#else /*not __ASSEMBLER__ */ #else /*not __ASSEMBLER__ */
@@ -79,7 +77,6 @@
/* Yes, include the user defines in tx_user.h. The defines in this file may /* Yes, include the user defines in tx_user.h. The defines in this file may
alternately be defined on the command line. */ alternately be defined on the command line. */
#include "nx_user.h"
#include "tx_user.h" #include "tx_user.h"
#endif #endif
@@ -95,8 +92,8 @@ typedef char CHAR;
typedef unsigned char UCHAR; typedef unsigned char UCHAR;
typedef int INT; typedef int INT;
typedef unsigned int UINT; typedef unsigned int UINT;
typedef int LONG; typedef long LONG;
typedef unsigned int ULONG; typedef unsigned long ULONG;
typedef unsigned long long ULONG64; typedef unsigned long long ULONG64;
typedef short SHORT; typedef short SHORT;
typedef unsigned short USHORT; typedef unsigned short USHORT;
@@ -7,12 +7,9 @@
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
**************************************************************************/ **************************************************************************/
#include "csr.h"
#include "tx_port.h"
.section .text .section .text
.align 4 .align 4
#include "tx_port.h"
/**************************************************************************/ /**************************************************************************/
/* */ /* */
/* FUNCTION RELEASE */ /* FUNCTION RELEASE */
@@ -90,74 +87,3 @@ trap_handler:
1: 1:
j 1b j 1b
.section .text .section .text
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_initialize_low_level RISC-V64/GNU */
/* 6.2.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for any low-level processor */
/* initialization, including setting up interrupt vectors, setting */
/* up a periodic timer interrupt source, saving the system stack */
/* pointer for use in ISR processing later, and finding the first */
/* available RAM memory address for tx_application_define. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _tx_initialize_kernel_enter ThreadX entry function */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 03-08-2023 Scott Larson Initial Version 6.2.1 */
/* */
/**************************************************************************/
/* VOID _tx_initialize_low_level(VOID)
*/
.global _tx_initialize_low_level
.weak _tx_initialize_low_level
.extern __heap_start
.extern board_init
_tx_initialize_low_level:
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
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
addi sp, sp, -8
STORE ra, 0(sp)
call board_init
LOAD ra, 0(sp)
addi sp, sp, 8
la t0, trap_entry
csrw mtvec, t0
ret
@@ -0,0 +1,51 @@
#include "board.h"
#include "csr.h"
#include "hwtimer.h"
#include "riscv-traps.h"
#include "tx_port.h"
#include <stdio.h>
extern CHAR __heap_start;
extern void trap_entry(void);
extern void _tx_timer_interrupt(void);
extern ULONG* _tx_thread_system_stack_ptr;
extern ULONG* _tx_initialize_unused_memory;
void handle_RISCV_INT_MTI(void)
{
hwtimer_handler();
_tx_timer_interrupt();
}
void handle_RISCV_INT_MEI()
{
puts("[INTERRUPT]: handler ext irq error!\n");
while (1)
;
}
VOID _tx_initialize_low_level(VOID)
{
_tx_thread_system_stack_ptr = (VOID*)(ULONG)riscv_get_sp();
_tx_initialize_unused_memory = (VOID*)&__heap_start;
// disable interrupts
asm volatile("csrrc zero, mstatus, %0" : : "r"(MSTATUS_MIE));
// set previous interrupt enable and previous priv mode to be set when executing "mret"
asm volatile("csrrs zero, mstatus, %0" : : "r"(MSTATUS_MPP_M | MSTATUS_MPIE));
// enable timer, software and external interrupts
asm volatile("csrrs zero, mie, %0" : : "r"(MIE_MTIE | MIE_MSIE | MIE_MEIE));
#ifdef __riscv_flen
// enable f extension and reset state
asm volatile("csrrs zero, mstatus, %0" : : "r"(MSTATUS_FS));
asm volatile("fscsr x0");
#endif
board_init();
register_irq_handler(RISCV_INT_MTI, handle_RISCV_INT_MTI);
register_irq_handler(RISCV_INT_MEI, handle_RISCV_INT_MEI);
asm volatile("csrw mtvec, %0" : : "r"((uintptr_t)trap_entry));
}
+6 -6
View File
@@ -80,9 +80,9 @@ _tx_thread_context_restore:
{ */ { */
la t0, _tx_thread_system_state // Pickup addr of nested interrupt count la t0, _tx_thread_system_state // Pickup addr of nested interrupt count
lw t1, 0(t0) // Pickup nested interrupt count LOAD t1, 0(t0) // Pickup nested interrupt count
addi t1, t1, -1 // Decrement the nested interrupt counter addi t1, t1, -1 // Decrement the nested interrupt counter
sw t1, 0(t0) // Store new nested count STORE t1, 0(t0) // Store new nested count
beqz t1, _tx_thread_not_nested_restore // If 0, not nested restore beqz t1, _tx_thread_not_nested_restore // If 0, not nested restore
/* Interrupts are nested. */ /* Interrupts are nested. */
@@ -190,7 +190,7 @@ _tx_thread_not_nested_restore:
LOAD t1, _tx_thread_current_ptr // Pickup current thread pointer LOAD t1, _tx_thread_current_ptr // Pickup current thread pointer
beqz t1, _tx_thread_idle_system_restore // If NULL, idle system restore beqz t1, _tx_thread_idle_system_restore // If NULL, idle system restore
LOAD t2, _tx_thread_preempt_disable // Pickup preempt disable flag LWU t2, _tx_thread_preempt_disable // Pickup preempt disable flag
bgtz t2, _tx_thread_no_preempt_restore // If set, restore interrupted thread bgtz t2, _tx_thread_no_preempt_restore // If set, restore interrupted thread
LOAD t2, _tx_thread_execute_ptr // Pickup thread execute pointer LOAD t2, _tx_thread_execute_ptr // Pickup thread execute pointer
@@ -354,14 +354,14 @@ _tx_thread_preempt_restore:
{ */ { */
la t0, _tx_timer_time_slice // Pickup time slice variable address la t0, _tx_timer_time_slice // Pickup time slice variable address
lw t2, 0(t0) // Pickup time slice LOAD t2, 0(t0) // Pickup time slice
beqz t2, _tx_thread_dont_save_ts // If 0, skip time slice processing 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_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice
_tx_timer_time_slice = 0; */ _tx_timer_time_slice = 0; */
sw t2, TX_THREAD_TIME_SLICE_OFFSET(t1) // Save current time slice STORE t2, 6*REGBYTES(t1) // Save current time slice
sw x0, 0(t0) // Clear global time slice STORE x0, 0(t0) // Clear global time slice
/* } */ /* } */
+2 -2
View File
@@ -74,14 +74,14 @@ _tx_thread_context_save:
STORE t1, 18*REGBYTES(sp) STORE t1, 18*REGBYTES(sp)
la t0, _tx_thread_system_state // Pickup address of system state la t0, _tx_thread_system_state // Pickup address of system state
lw t1, 0(t0) // Pickup system state LOAD t1, 0(t0) // Pickup system state
/* Check for a nested interrupt condition. */ /* Check for a nested interrupt condition. */
/* if (_tx_thread_system_state++) /* if (_tx_thread_system_state++)
{ */ { */
beqz t1, _tx_thread_not_nested_save // If 0, first interrupt condition beqz t1, _tx_thread_not_nested_save // If 0, first interrupt condition
addi t1, t1, 1 // Increment the interrupt counter addi t1, t1, 1 // Increment the interrupt counter
sw t1, 0(t0) // Store the interrupt counter STORE t1, 0(t0) // Store the interrupt counter
/* Nested interrupt condition. /* Nested interrupt condition.
Save the reset of the scratch registers on the stack and return to the Save the reset of the scratch registers on the stack and return to the
+1 -1
View File
@@ -105,12 +105,12 @@ _tx_thread_schedule_loop:
/* _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice; */ /* _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
STORE t3, 0(t2) // Store new time-slice*/
/* Switch to the thread's stack. */ /* Switch to the thread's stack. */
/* SP = _tx_thread_execute_ptr -> tx_thread_stack_ptr; */ /* SP = _tx_thread_execute_ptr -> tx_thread_stack_ptr; */
LOAD sp, 2*REGBYTES(t1) // Switch to thread's stack LOAD sp, 2*REGBYTES(t1) // Switch to thread's stack
STORE t3, 0(t2) // Store new time-slice*/
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+2 -2
View File
@@ -138,8 +138,8 @@ If floating point support:
Stack Bottom: (higher memory address) */ Stack Bottom: (higher memory address) */
LOAD t0, TX_THREAD_STACK_END_OFFSET(a0) // Pickup end of stack area LOAD t0, 4*REGBYTES(a0) // Pickup end of stack area
andi t0, t0, -4*REGBYTES // Ensure alignment (16-byte for RV32 & 32-byte for RV64) andi t0, t0, -16 // Ensure 16-byte alignment
/* Actually build the stack frame. */ /* Actually build the stack frame. */
+3 -3
View File
@@ -151,7 +151,7 @@ _tx_thread_system_return:
{ */ { */
la t4, _tx_timer_time_slice // Pickup time slice variable addr la t4, _tx_timer_time_slice // Pickup time slice variable addr
lw t3, 0(t4) // Pickup time slice value LOAD t3, 0(t4) // Pickup time slice value
la t2, _tx_thread_schedule // Pickup address of scheduling loop 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 beqz t3, _tx_thread_dont_save_ts // If no time-slice, don't save it
@@ -159,8 +159,8 @@ _tx_thread_system_return:
/* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice; /* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
_tx_timer_time_slice = 0; */ _tx_timer_time_slice = 0; */
sw t3, TX_THREAD_TIME_SLICE_OFFSET(t1) // Save current time-slice for thread STORE t3, 6*REGBYTES(t1) // Save current time-slice for thread
sw x0, 0(t4) // Clear time-slice variable STORE x0, 0(t4) // Clear time-slice variable
/* } */ /* } */
_tx_thread_dont_save_ts: _tx_thread_dont_save_ts:
+205 -19
View File
@@ -1,8 +1,6 @@
cmake_minimum_required(VERSION 3.24) cmake_minimum_required(VERSION 3.24)
project(smp_demo LANGUAGES C ASM) project(smp_demo LANGUAGES C ASM)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/ThreadXSmpOffsets.cmake)
set(THREADX_COMMON_SMP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../third-party/threadx/common_smp) set(THREADX_COMMON_SMP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../third-party/threadx/common_smp)
if(NOT EXISTS "${THREADX_COMMON_SMP_DIR}") if(NOT EXISTS "${THREADX_COMMON_SMP_DIR}")
message(FATAL_ERROR "could not find ThreadX SMP sources, is the submodule checked out?") message(FATAL_ERROR "could not find ThreadX SMP sources, is the submodule checked out?")
@@ -12,10 +10,19 @@ set(THREADX_SMP_CUSTOM_INC
${CMAKE_CURRENT_SOURCE_DIR}/inc ${CMAKE_CURRENT_SOURCE_DIR}/inc
${CMAKE_CURRENT_SOURCE_DIR}/../moonlight/inc # needed for Moonlight SMP support headers ${CMAKE_CURRENT_SOURCE_DIR}/../moonlight/inc # needed for Moonlight SMP support headers
) )
#required for tests to hook into the ISR path
if(NOT DEFINED THREADX_LOW_LEVEL_INIT_SOURCE)
set(THREADX_LOW_LEVEL_INIT_SOURCE
${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.c)
endif()
set(THREADX_SMP_CUSTOM_SRC set(THREADX_SMP_CUSTOM_SRC
src/tx_initialize_low_level.S src/trap_entry.S
${THREADX_LOW_LEVEL_INIT_SOURCE}
src/tx_thread_context_restore.S src/tx_thread_context_restore.S
src/tx_thread_context_save.S src/tx_thread_context_save.S
src/tx_thread_interrupt_control.S
src/tx_thread_schedule.S src/tx_thread_schedule.S
src/tx_thread_smp_core_get.S src/tx_thread_smp_core_get.S
src/tx_thread_smp_core_preempt.c src/tx_thread_smp_core_preempt.c
@@ -30,20 +37,203 @@ set(THREADX_SMP_CUSTOM_SRC
src/tx_timer_interrupt.c src/tx_timer_interrupt.c
) )
threadx_smp_add_offsets( set(THREADX_SMP_SOURCES
TARGET threadx_smp_offsets ${THREADX_COMMON_SMP_DIR}/src/tx_block_allocate.c
OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated ${THREADX_COMMON_SMP_DIR}/src/tx_block_pool_cleanup.c
SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/tx_asm_offsets.c ${THREADX_COMMON_SMP_DIR}/src/tx_block_pool_create.c
INCLUDE_DIRS ${THREADX_COMMON_SMP_DIR}/src/tx_block_pool_delete.c
${THREADX_COMMON_SMP_DIR}/inc ${THREADX_COMMON_SMP_DIR}/src/tx_block_pool_info_get.c
${THREADX_SMP_CUSTOM_INC} ${THREADX_COMMON_SMP_DIR}/src/tx_block_pool_initialize.c
DEPENDS ${THREADX_COMMON_SMP_DIR}/src/tx_block_pool_performance_info_get.c
${CMAKE_CURRENT_SOURCE_DIR}/inc/tx_port.h ${THREADX_COMMON_SMP_DIR}/src/tx_block_pool_performance_system_info_get.c
${THREADX_COMMON_SMP_DIR}/inc/tx_api.h ${THREADX_COMMON_SMP_DIR}/src/tx_block_pool_prioritize.c
OUT_INCLUDE_DIR THREADX_SMP_GENERATED_INC_DIR ${THREADX_COMMON_SMP_DIR}/src/tx_block_release.c
${THREADX_COMMON_SMP_DIR}/src/tx_byte_allocate.c
${THREADX_COMMON_SMP_DIR}/src/tx_byte_pool_cleanup.c
${THREADX_COMMON_SMP_DIR}/src/tx_byte_pool_create.c
${THREADX_COMMON_SMP_DIR}/src/tx_byte_pool_delete.c
${THREADX_COMMON_SMP_DIR}/src/tx_byte_pool_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_byte_pool_initialize.c
${THREADX_COMMON_SMP_DIR}/src/tx_byte_pool_performance_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_byte_pool_performance_system_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_byte_pool_prioritize.c
${THREADX_COMMON_SMP_DIR}/src/tx_byte_pool_search.c
${THREADX_COMMON_SMP_DIR}/src/tx_byte_release.c
${THREADX_COMMON_SMP_DIR}/src/txe_block_allocate.c
${THREADX_COMMON_SMP_DIR}/src/txe_block_pool_create.c
${THREADX_COMMON_SMP_DIR}/src/txe_block_pool_delete.c
${THREADX_COMMON_SMP_DIR}/src/txe_block_pool_info_get.c
${THREADX_COMMON_SMP_DIR}/src/txe_block_pool_prioritize.c
${THREADX_COMMON_SMP_DIR}/src/txe_block_release.c
${THREADX_COMMON_SMP_DIR}/src/txe_byte_allocate.c
${THREADX_COMMON_SMP_DIR}/src/txe_byte_pool_create.c
${THREADX_COMMON_SMP_DIR}/src/txe_byte_pool_delete.c
${THREADX_COMMON_SMP_DIR}/src/txe_byte_pool_info_get.c
${THREADX_COMMON_SMP_DIR}/src/txe_byte_pool_prioritize.c
${THREADX_COMMON_SMP_DIR}/src/txe_byte_release.c
${THREADX_COMMON_SMP_DIR}/src/txe_event_flags_create.c
${THREADX_COMMON_SMP_DIR}/src/txe_event_flags_delete.c
${THREADX_COMMON_SMP_DIR}/src/txe_event_flags_get.c
${THREADX_COMMON_SMP_DIR}/src/txe_event_flags_info_get.c
${THREADX_COMMON_SMP_DIR}/src/txe_event_flags_set.c
${THREADX_COMMON_SMP_DIR}/src/txe_event_flags_set_notify.c
${THREADX_COMMON_SMP_DIR}/src/txe_mutex_create.c
${THREADX_COMMON_SMP_DIR}/src/txe_mutex_delete.c
${THREADX_COMMON_SMP_DIR}/src/txe_mutex_get.c
${THREADX_COMMON_SMP_DIR}/src/txe_mutex_info_get.c
${THREADX_COMMON_SMP_DIR}/src/txe_mutex_prioritize.c
${THREADX_COMMON_SMP_DIR}/src/txe_mutex_put.c
${THREADX_COMMON_SMP_DIR}/src/txe_queue_create.c
${THREADX_COMMON_SMP_DIR}/src/txe_queue_delete.c
${THREADX_COMMON_SMP_DIR}/src/txe_queue_flush.c
${THREADX_COMMON_SMP_DIR}/src/txe_queue_front_send.c
${THREADX_COMMON_SMP_DIR}/src/txe_queue_info_get.c
${THREADX_COMMON_SMP_DIR}/src/txe_queue_prioritize.c
${THREADX_COMMON_SMP_DIR}/src/txe_queue_receive.c
${THREADX_COMMON_SMP_DIR}/src/txe_queue_send.c
${THREADX_COMMON_SMP_DIR}/src/txe_queue_send_notify.c
${THREADX_COMMON_SMP_DIR}/src/txe_semaphore_ceiling_put.c
${THREADX_COMMON_SMP_DIR}/src/txe_semaphore_create.c
${THREADX_COMMON_SMP_DIR}/src/txe_semaphore_delete.c
${THREADX_COMMON_SMP_DIR}/src/txe_semaphore_get.c
${THREADX_COMMON_SMP_DIR}/src/txe_semaphore_info_get.c
${THREADX_COMMON_SMP_DIR}/src/txe_semaphore_prioritize.c
${THREADX_COMMON_SMP_DIR}/src/txe_semaphore_put.c
${THREADX_COMMON_SMP_DIR}/src/txe_semaphore_put_notify.c
${THREADX_COMMON_SMP_DIR}/src/txe_thread_create.c
${THREADX_COMMON_SMP_DIR}/src/txe_thread_delete.c
${THREADX_COMMON_SMP_DIR}/src/txe_thread_entry_exit_notify.c
${THREADX_COMMON_SMP_DIR}/src/txe_thread_info_get.c
${THREADX_COMMON_SMP_DIR}/src/txe_thread_preemption_change.c
${THREADX_COMMON_SMP_DIR}/src/txe_thread_priority_change.c
${THREADX_COMMON_SMP_DIR}/src/txe_thread_relinquish.c
${THREADX_COMMON_SMP_DIR}/src/txe_thread_reset.c
${THREADX_COMMON_SMP_DIR}/src/txe_thread_resume.c
${THREADX_COMMON_SMP_DIR}/src/txe_thread_suspend.c
${THREADX_COMMON_SMP_DIR}/src/txe_thread_terminate.c
${THREADX_COMMON_SMP_DIR}/src/txe_thread_time_slice_change.c
${THREADX_COMMON_SMP_DIR}/src/txe_thread_wait_abort.c
${THREADX_COMMON_SMP_DIR}/src/txe_timer_activate.c
${THREADX_COMMON_SMP_DIR}/src/txe_timer_change.c
${THREADX_COMMON_SMP_DIR}/src/txe_timer_create.c
${THREADX_COMMON_SMP_DIR}/src/txe_timer_deactivate.c
${THREADX_COMMON_SMP_DIR}/src/txe_timer_delete.c
${THREADX_COMMON_SMP_DIR}/src/txe_timer_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_event_flags_cleanup.c
${THREADX_COMMON_SMP_DIR}/src/tx_event_flags_create.c
${THREADX_COMMON_SMP_DIR}/src/tx_event_flags_delete.c
${THREADX_COMMON_SMP_DIR}/src/tx_event_flags_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_event_flags_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_event_flags_initialize.c
${THREADX_COMMON_SMP_DIR}/src/tx_event_flags_performance_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_event_flags_performance_system_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_event_flags_set.c
${THREADX_COMMON_SMP_DIR}/src/tx_event_flags_set_notify.c
${THREADX_COMMON_SMP_DIR}/src/tx_initialize_high_level.c
${THREADX_COMMON_SMP_DIR}/src/tx_initialize_kernel_enter.c
${THREADX_COMMON_SMP_DIR}/src/tx_initialize_kernel_setup.c
${THREADX_COMMON_SMP_DIR}/src/tx_misra.c
${THREADX_COMMON_SMP_DIR}/src/tx_mutex_cleanup.c
${THREADX_COMMON_SMP_DIR}/src/tx_mutex_create.c
${THREADX_COMMON_SMP_DIR}/src/tx_mutex_delete.c
${THREADX_COMMON_SMP_DIR}/src/tx_mutex_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_mutex_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_mutex_initialize.c
${THREADX_COMMON_SMP_DIR}/src/tx_mutex_performance_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_mutex_performance_system_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_mutex_prioritize.c
${THREADX_COMMON_SMP_DIR}/src/tx_mutex_priority_change.c
${THREADX_COMMON_SMP_DIR}/src/tx_mutex_put.c
${THREADX_COMMON_SMP_DIR}/src/tx_queue_cleanup.c
${THREADX_COMMON_SMP_DIR}/src/tx_queue_create.c
${THREADX_COMMON_SMP_DIR}/src/tx_queue_delete.c
${THREADX_COMMON_SMP_DIR}/src/tx_queue_flush.c
${THREADX_COMMON_SMP_DIR}/src/tx_queue_front_send.c
${THREADX_COMMON_SMP_DIR}/src/tx_queue_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_queue_initialize.c
${THREADX_COMMON_SMP_DIR}/src/tx_queue_performance_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_queue_performance_system_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_queue_prioritize.c
${THREADX_COMMON_SMP_DIR}/src/tx_queue_receive.c
${THREADX_COMMON_SMP_DIR}/src/tx_queue_send.c
${THREADX_COMMON_SMP_DIR}/src/tx_queue_send_notify.c
${THREADX_COMMON_SMP_DIR}/src/tx_semaphore_ceiling_put.c
${THREADX_COMMON_SMP_DIR}/src/tx_semaphore_cleanup.c
${THREADX_COMMON_SMP_DIR}/src/tx_semaphore_create.c
${THREADX_COMMON_SMP_DIR}/src/tx_semaphore_delete.c
${THREADX_COMMON_SMP_DIR}/src/tx_semaphore_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_semaphore_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_semaphore_initialize.c
${THREADX_COMMON_SMP_DIR}/src/tx_semaphore_performance_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_semaphore_performance_system_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_semaphore_prioritize.c
${THREADX_COMMON_SMP_DIR}/src/tx_semaphore_put.c
${THREADX_COMMON_SMP_DIR}/src/tx_semaphore_put_notify.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_create.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_delete.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_entry_exit_notify.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_identify.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_initialize.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_performance_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_performance_system_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_preemption_change.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_priority_change.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_relinquish.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_reset.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_resume.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_shell_entry.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_sleep.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_smp_core_exclude.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_smp_core_exclude_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_smp_current_state_set.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_smp_debug_entry_insert.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_smp_high_level_initialize.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_smp_rebalance_execute_list.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_smp_utilities.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_stack_analyze.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_stack_error_handler.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_stack_error_notify.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_suspend.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_system_preempt_check.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_system_resume.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_system_suspend.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_terminate.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_timeout.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_time_slice.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_time_slice_change.c
${THREADX_COMMON_SMP_DIR}/src/tx_thread_wait_abort.c
${THREADX_COMMON_SMP_DIR}/src/tx_time_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_timer_activate.c
${THREADX_COMMON_SMP_DIR}/src/tx_timer_change.c
${THREADX_COMMON_SMP_DIR}/src/tx_timer_create.c
${THREADX_COMMON_SMP_DIR}/src/tx_timer_deactivate.c
${THREADX_COMMON_SMP_DIR}/src/tx_timer_delete.c
${THREADX_COMMON_SMP_DIR}/src/tx_timer_expiration_process.c
${THREADX_COMMON_SMP_DIR}/src/tx_timer_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_timer_initialize.c
${THREADX_COMMON_SMP_DIR}/src/tx_timer_performance_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_timer_performance_system_info_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_timer_smp_core_exclude.c
${THREADX_COMMON_SMP_DIR}/src/tx_timer_smp_core_exclude_get.c
${THREADX_COMMON_SMP_DIR}/src/tx_timer_system_activate.c
${THREADX_COMMON_SMP_DIR}/src/tx_timer_system_deactivate.c
${THREADX_COMMON_SMP_DIR}/src/tx_timer_thread_entry.c
${THREADX_COMMON_SMP_DIR}/src/tx_time_set.c
${THREADX_COMMON_SMP_DIR}/src/tx_trace_buffer_full_notify.c
${THREADX_COMMON_SMP_DIR}/src/tx_trace_disable.c
${THREADX_COMMON_SMP_DIR}/src/tx_trace_enable.c
${THREADX_COMMON_SMP_DIR}/src/tx_trace_event_filter.c
${THREADX_COMMON_SMP_DIR}/src/tx_trace_event_unfilter.c
${THREADX_COMMON_SMP_DIR}/src/tx_trace_initialize.c
${THREADX_COMMON_SMP_DIR}/src/tx_trace_interrupt_control.c
${THREADX_COMMON_SMP_DIR}/src/tx_trace_isr_enter_insert.c
${THREADX_COMMON_SMP_DIR}/src/tx_trace_isr_exit_insert.c
${THREADX_COMMON_SMP_DIR}/src/tx_trace_object_register.c
${THREADX_COMMON_SMP_DIR}/src/tx_trace_object_unregister.c
${THREADX_COMMON_SMP_DIR}/src/tx_trace_user_event_insert.c
) )
file(GLOB THREADX_SMP_SOURCES ${THREADX_COMMON_SMP_DIR}/src/*.c)
add_library(threadx_smp STATIC) add_library(threadx_smp STATIC)
target_sources(threadx_smp PRIVATE target_sources(threadx_smp PRIVATE
${THREADX_SMP_SOURCES} ${THREADX_SMP_SOURCES}
@@ -53,8 +243,4 @@ target_include_directories(threadx_smp PUBLIC
${THREADX_COMMON_SMP_DIR}/inc ${THREADX_COMMON_SMP_DIR}/inc
${THREADX_SMP_CUSTOM_INC} ${THREADX_SMP_CUSTOM_INC}
) )
target_include_directories(threadx_smp PRIVATE
${THREADX_SMP_GENERATED_INC_DIR}
)
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)
@@ -1,67 +0,0 @@
function(threadx_smp_add_offsets)
set(options)
set(oneValueArgs TARGET OUTPUT_DIR SOURCE OUT_INCLUDE_DIR)
set(multiValueArgs INCLUDE_DIRS COMPILE_DEFINITIONS DEPENDS)
cmake_parse_arguments(THREADX_SMP_OFFSETS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT THREADX_SMP_OFFSETS_TARGET)
message(FATAL_ERROR "threadx_smp_add_offsets requires TARGET")
endif()
if(NOT THREADX_SMP_OFFSETS_OUTPUT_DIR)
message(FATAL_ERROR "threadx_smp_add_offsets requires OUTPUT_DIR")
endif()
if(NOT THREADX_SMP_OFFSETS_SOURCE)
message(FATAL_ERROR "threadx_smp_add_offsets requires SOURCE")
endif()
if(NOT THREADX_SMP_OFFSETS_OUT_INCLUDE_DIR)
message(FATAL_ERROR "threadx_smp_add_offsets requires OUT_INCLUDE_DIR")
endif()
set(threadx_smp_generate_script "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/GenerateAsmOffsets.cmake")
set(threadx_smp_offset_asm "${THREADX_SMP_OFFSETS_OUTPUT_DIR}/tx_asm_offsets.s")
set(threadx_smp_offset_inc "${THREADX_SMP_OFFSETS_OUTPUT_DIR}/tx_asm_offsets.inc")
set(threadx_smp_offset_include_args ${THREADX_SMP_OFFSETS_INCLUDE_DIRS})
list(TRANSFORM threadx_smp_offset_include_args PREPEND -I)
set(threadx_smp_offset_define_args ${THREADX_SMP_OFFSETS_COMPILE_DEFINITIONS})
list(TRANSFORM threadx_smp_offset_define_args PREPEND -D)
set(threadx_smp_offset_cflags ${CMAKE_C_FLAGS})
if(CMAKE_BUILD_TYPE)
string(TOUPPER "${CMAKE_BUILD_TYPE}" threadx_smp_build_type_upper)
list(APPEND threadx_smp_offset_cflags ${CMAKE_C_FLAGS_${threadx_smp_build_type_upper}})
endif()
separate_arguments(threadx_smp_offset_cflags)
add_custom_command(
OUTPUT ${threadx_smp_offset_inc}
BYPRODUCTS ${threadx_smp_offset_asm}
COMMAND ${CMAKE_COMMAND} -E make_directory ${THREADX_SMP_OFFSETS_OUTPUT_DIR}
COMMAND ${CMAKE_C_COMPILER}
${CMAKE_C_COMPILER_ARG1}
${threadx_smp_offset_cflags}
${threadx_smp_offset_include_args}
${threadx_smp_offset_define_args}
-S
-o ${threadx_smp_offset_asm}
${THREADX_SMP_OFFSETS_SOURCE}
COMMAND ${CMAKE_COMMAND}
-DINPUT=${threadx_smp_offset_asm}
-DOUTPUT=${threadx_smp_offset_inc}
-P ${threadx_smp_generate_script}
DEPENDS
${THREADX_SMP_OFFSETS_SOURCE}
${threadx_smp_generate_script}
${THREADX_SMP_OFFSETS_DEPENDS}
COMMAND_EXPAND_LISTS
VERBATIM
)
add_custom_target(${THREADX_SMP_OFFSETS_TARGET} DEPENDS ${threadx_smp_offset_inc})
set(${THREADX_SMP_OFFSETS_OUT_INCLUDE_DIR} ${THREADX_SMP_OFFSETS_OUTPUT_DIR} PARENT_SCOPE)
endfunction()
+112 -3
View File
@@ -61,22 +61,28 @@
#define STORE sd #define STORE sd
#define LOAD ld #define LOAD ld
#define LWU lwu #define LWU lwu
#define AMOSWAP_AQ amoswap.d.aq
#define AMOSWAP_RL amoswap.d.rl
#define LOG_REGBYTES 3 #define LOG_REGBYTES 3
#define TX_THREAD_SMP_LOCK_READY_BIT_OFFSET 312 // This changes if thread or timer internal extensions are used
#else #else
#define SLL32 sll #define SLL32 sll
#define STORE sw #define STORE sw
#define LOAD lw #define LOAD lw
#define LWU lw #define LWU lw
#define AMOSWAP_AQ amoswap.w.aq
#define AMOSWAP_RL amoswap.w.rl
#define LOG_REGBYTES 2 #define LOG_REGBYTES 2
#define TX_THREAD_SMP_LOCK_READY_BIT_OFFSET 168 // This changes if thread or timer internal extensions are used
#endif #endif
#define REGBYTES (1 << LOG_REGBYTES) #define REGBYTES (1 << LOG_REGBYTES)
#include "tx_asm_offsets.inc"
#else /*not __ASSEMBLER__ */ #else /*not __ASSEMBLER__ */
/************* Define ThreadX SMP constants. *************/ /************* Define ThreadX SMP constants. *************/
#define TX_DISABLE_INLINE
/* Define the ThreadX SMP maximum number of cores. */ /* Define the ThreadX SMP maximum number of cores. */
#ifndef TX_THREAD_SMP_MAX_CORES #ifndef TX_THREAD_SMP_MAX_CORES
@@ -164,7 +170,7 @@ typedef unsigned char UCHAR;
typedef int INT; typedef int INT;
typedef unsigned int UINT; typedef unsigned int UINT;
typedef int LONG; typedef int LONG;
typedef unsigned int ULONG; typedef unsigned long ULONG;
typedef unsigned long long ULONG64; typedef unsigned long long ULONG64;
typedef short SHORT; typedef short SHORT;
typedef unsigned short USHORT; typedef unsigned short USHORT;
@@ -271,6 +277,109 @@ typedef unsigned short USHORT;
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) #define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) #define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
/* Define automated regression test extensions. These are required for the
ThreadX regression tests. */
typedef unsigned int TEST_FLAG;
extern TEST_FLAG threadx_byte_allocate_loop_test;
extern TEST_FLAG threadx_byte_release_loop_test;
extern TEST_FLAG threadx_mutex_suspension_put_test;
extern TEST_FLAG threadx_mutex_suspension_priority_test;
#ifndef TX_TIMER_PROCESS_IN_ISR
extern TEST_FLAG threadx_delete_timer_thread;
#endif
extern void abort_and_resume_byte_allocating_thread(void);
extern void abort_all_threads_suspended_on_mutex(void);
extern void suspend_lowest_priority(void);
#ifndef TX_TIMER_PROCESS_IN_ISR
extern void delete_timer_thread(void);
#endif
extern TEST_FLAG test_stack_analyze_flag;
extern TEST_FLAG test_initialize_flag;
extern TEST_FLAG test_forced_mutex_timeout;
#ifdef TX_REGRESSION_TEST
/* Define extension macros for automated coverage tests. */
#define TX_BYTE_ALLOCATE_EXTENSION \
if (threadx_byte_allocate_loop_test == ((TEST_FLAG)1)) \
{ \
pool_ptr->tx_byte_pool_owner = TX_NULL; \
threadx_byte_allocate_loop_test = ((TEST_FLAG)0); \
}
#define TX_BYTE_RELEASE_EXTENSION \
if (threadx_byte_release_loop_test == ((TEST_FLAG)1)) \
{ \
threadx_byte_release_loop_test = ((TEST_FLAG)0); \
abort_and_resume_byte_allocating_thread(); \
}
#define TX_MUTEX_PUT_EXTENSION_1 \
if (threadx_mutex_suspension_put_test == ((TEST_FLAG)1)) \
{ \
threadx_mutex_suspension_put_test = ((TEST_FLAG)0); \
abort_all_threads_suspended_on_mutex(); \
}
#define TX_MUTEX_PUT_EXTENSION_2 \
if (test_forced_mutex_timeout == ((TEST_FLAG)1)) \
{ \
test_forced_mutex_timeout = ((TEST_FLAG)0); \
_tx_thread_wait_abort(mutex_ptr->tx_mutex_suspension_list); \
}
#define TX_MUTEX_PRIORITY_CHANGE_EXTENSION \
if (threadx_mutex_suspension_priority_test == ((TEST_FLAG)1)) \
{ \
threadx_mutex_suspension_priority_test = ((TEST_FLAG)0); \
suspend_lowest_priority(); \
}
#ifndef TX_TIMER_PROCESS_IN_ISR
#define TX_TIMER_INITIALIZE_EXTENSION(a) \
if (threadx_delete_timer_thread == ((TEST_FLAG)1)) \
{ \
threadx_delete_timer_thread = ((TEST_FLAG)0); \
delete_timer_thread(); \
(a) = ((UINT)1); \
}
#endif
#define TX_THREAD_STACK_ANALYZE_EXTENSION \
if (test_stack_analyze_flag == ((TEST_FLAG)1)) \
{ \
thread_ptr->tx_thread_id = ((TEST_FLAG)0); \
test_stack_analyze_flag = ((TEST_FLAG)0); \
} \
else if (test_stack_analyze_flag == ((TEST_FLAG)2)) \
{ \
stack_ptr = thread_ptr->tx_thread_stack_start; \
test_stack_analyze_flag = ((TEST_FLAG)0); \
} \
else if (test_stack_analyze_flag == ((TEST_FLAG)3)) \
{ \
*stack_ptr = TX_STACK_FILL; \
test_stack_analyze_flag = ((TEST_FLAG)0); \
} \
else \
{ \
test_stack_analyze_flag = ((TEST_FLAG)0); \
}
#define TX_INITIALIZE_KERNEL_ENTER_EXTENSION \
if (test_initialize_flag == ((TEST_FLAG)1)) \
{ \
test_initialize_flag = ((TEST_FLAG)0); \
return; \
}
#endif
/* Define the ThreadX object creation extensions for the remaining objects. */ /* Define the ThreadX object creation extensions for the remaining objects. */
#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr) #define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
@@ -7,12 +7,9 @@
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
**************************************************************************/ **************************************************************************/
#include "csr.h"
#include "tx_port.h"
.section .text .section .text
.align 4 .align 4
#include "tx_port.h"
/**************************************************************************/ /**************************************************************************/
/* */ /* */
/* FUNCTION RELEASE */ /* FUNCTION RELEASE */
@@ -90,74 +87,3 @@ trap_handler:
1: 1:
j 1b j 1b
.section .text .section .text
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_initialize_low_level RISC-V64/GNU */
/* 6.2.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for any low-level processor */
/* initialization, including setting up interrupt vectors, setting */
/* up a periodic timer interrupt source, saving the system stack */
/* pointer for use in ISR processing later, and finding the first */
/* available RAM memory address for tx_application_define. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _tx_initialize_kernel_enter ThreadX entry function */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 03-08-2023 Scott Larson Initial Version 6.2.1 */
/* */
/**************************************************************************/
/* VOID _tx_initialize_low_level(VOID)
*/
.global _tx_initialize_low_level
.weak _tx_initialize_low_level
.extern __heap_start
.extern board_init
_tx_initialize_low_level:
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
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
addi sp, sp, -8
STORE ra, 0(sp)
call board_init
LOAD ra, 0(sp)
addi sp, sp, 8
la t0, trap_entry
csrw mtvec, t0
ret
-12
View File
@@ -1,12 +0,0 @@
#include <stddef.h>
#include "tx_api.h"
#define TX_ASM_OFFSET(symbol, value) __asm__ volatile("\n.ascii \"-->" #symbol " %c0\\n\"" : : "i"(value))
void tx_asm_offsets_generate(void)
{
TX_ASM_OFFSET(TX_THREAD_STACK_END_OFFSET, offsetof(TX_THREAD, tx_thread_stack_end));
TX_ASM_OFFSET(TX_THREAD_TIME_SLICE_OFFSET, offsetof(TX_THREAD, tx_thread_time_slice));
TX_ASM_OFFSET(TX_THREAD_SMP_LOCK_READY_BIT_OFFSET, offsetof(TX_THREAD, tx_thread_smp_lock_ready_bit));
}
@@ -0,0 +1,113 @@
#include "aclint.h"
#include "aclint_ipi.h"
#include "board.h"
#include "csr.h"
#include "hwtimer.h"
#include "riscv-csr.h"
#include "riscv-traps.h"
#include "tx_port.h"
#include <stdio.h>
extern CHAR __heap_start;
extern void trap_entry(void);
extern void _tx_timer_interrupt(void);
extern ULONG* _tx_thread_system_stack_ptr;
extern ULONG* _tx_initialize_unused_memory;
extern void _tx_thread_smp_initialize_wait(void) __attribute__((noreturn));
void handle_RISCV_INT_MTI(void)
{
hwtimer_handler();
_tx_timer_interrupt();
}
void handle_RISCV_INT_MEI()
{
puts("[INTERRUPT]: handler ext irq error!\n");
while (1)
;
}
#ifdef TX_THREAD_SMP_INTER_CORE_INTERRUPT
void handle_RISCV_INT_MSI()
{
set_aclint_msip(aclint, csr_read_mhartid(), 0);
}
#endif
static void __attribute__((used)) bootup_ipi_clear_handler(void)
{
set_aclint_msip(aclint, csr_read_mhartid(), 0);
}
void _secondary_ipi_trap(void) __attribute__((naked, noreturn, section(".text.boot")));
void _secondary_initialize(void) __attribute__((noreturn, section(".text.boot")));
void bootup_wake_secondary_cores(void);
void _secondary_initialize(void)
{
csr_write_mtvec((uint_xlen_t)_secondary_ipi_trap);
csr_set_bits_mie(MIE_MSI_BIT_MASK);
csr_set_bits_mstatus(MSTATUS_MIE_BIT_MASK);
__asm__ volatile("wfi");
csr_clr_bits_mstatus(MSTATUS_MIE_BIT_MASK);
_tx_thread_smp_initialize_wait();
}
void _secondary_ipi_trap(void)
{
#if __riscv_xlen == 64
__asm__ volatile("addi sp, sp, -16;"
"sd ra, 8(sp);"
"call bootup_ipi_clear_handler;"
"ld ra, 8(sp);"
"addi sp, sp, 16;"
"mret");
#else
__asm__ volatile("addi sp, sp, -8;"
"sw ra, 4(sp);"
"call bootup_ipi_clear_handler;"
"lw ra, 4(sp);"
"addi sp, sp, 8;"
"mret");
#endif
}
void bootup_wake_secondary_cores(void)
{
for (UINT core = 1; core < TX_THREAD_SMP_MAX_CORES; ++core) {
send_ipi(core);
}
}
VOID _tx_initialize_low_level(VOID)
{
_tx_thread_system_stack_ptr = (VOID*)(ULONG)riscv_get_sp();
_tx_initialize_unused_memory = (VOID*)&__heap_start;
// disable interrupts
asm volatile("csrrc zero, mstatus, %0" : : "r"(MSTATUS_MIE));
// set previous interrupt enable and previous priv mode to be set when executing "mret"
asm volatile("csrrs zero, mstatus, %0" : : "r"(MSTATUS_MPP_M | MSTATUS_MPIE));
// enable timer, software and external interrupts
asm volatile("csrrs zero, mie, %0" : : "r"(MIE_MTIE | MIE_MSIE | MIE_MEIE));
#ifdef __riscv_flen
// enable f extension and reset state
asm volatile("csrrs zero, mstatus, %0" : : "r"(MSTATUS_FS));
asm volatile("fscsr x0");
#endif
board_init();
register_irq_handler(RISCV_INT_MTI, handle_RISCV_INT_MTI);
register_irq_handler(RISCV_INT_MEI, handle_RISCV_INT_MEI);
#ifdef TX_THREAD_SMP_INTER_CORE_INTERRUPT
register_irq_handler(RISCV_INT_MSI, handle_RISCV_INT_MSI);
#endif
asm volatile("csrw mtvec, %0" : : "r"((uintptr_t)trap_entry));
}
@@ -80,13 +80,13 @@ _tx_thread_context_restore:
{ */ { */
csrr t3, mhartid // Pickup current hart ID csrr t3, mhartid // Pickup current hart ID
slli t4, t3, 2 // Build per-hart ULONG offset slli t4, t3, LOG_REGBYTES // Build per-hart ULONG offset
slli t5, t3, LOG_REGBYTES // Build per-hart pointer offset slli t5, t3, LOG_REGBYTES // Build per-hart pointer offset
la t0, _tx_thread_system_state // Pickup base of system-state array la t0, _tx_thread_system_state // Pickup base of system-state array
add t0, t0, t4 // Select this hart's system-state slot add t0, t0, t4 // Select this hart's system-state slot
lw t1, 0(t0) // Pickup nested interrupt count LOAD t1, 0(t0) // Pickup nested interrupt count
addi t1, t1, -1 // Decrement the nested interrupt counter addi t1, t1, -1 // Decrement the nested interrupt counter
sw t1, 0(t0) // Store new nested count STORE t1, 0(t0) // Store new nested count
beqz t1, _tx_thread_not_nested_restore // If 0, not nested restore beqz t1, _tx_thread_not_nested_restore // If 0, not nested restore
/* Interrupts are nested. */ /* Interrupts are nested. */
@@ -202,10 +202,10 @@ _tx_thread_not_nested_restore:
beq t1, t2, _tx_thread_no_preempt_restore // Same thread selected, no preemption beq t1, t2, _tx_thread_no_preempt_restore // Same thread selected, no preemption
la t0, _tx_thread_smp_protection // Pickup protection structure la t0, _tx_thread_smp_protection // Pickup protection structure
lw t2, 4(t0) // Pickup owning hart LOAD t2, 1*REGBYTES(t0) // Pickup owning hart
bne t2, t3, _tx_thread_preempt_restore // If owned by another hart, preempt bne t2, t3, _tx_thread_preempt_restore // If owned by another hart, preempt
LOAD t2, _tx_thread_preempt_disable // Pickup preempt disable flag LWU t2, _tx_thread_preempt_disable // Pickup preempt disable flag
bgtz t2, _tx_thread_no_preempt_restore // If set, restore interrupted thread bgtz t2, _tx_thread_no_preempt_restore // If set, restore interrupted thread
@@ -367,14 +367,14 @@ _tx_thread_preempt_restore:
la t0, _tx_timer_time_slice // Pickup base of time-slice array la t0, _tx_timer_time_slice // Pickup base of time-slice array
add t0, t0, t4 // Select this hart's time-slice slot add t0, t0, t4 // Select this hart's time-slice slot
lw t2, 0(t0) // Pickup time slice LOAD t2, 0(t0) // Pickup time slice
beqz t2, _tx_thread_dont_save_ts // If 0, skip time slice processing 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_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice
_tx_timer_time_slice = 0; */ _tx_timer_time_slice = 0; */
sw t2, TX_THREAD_TIME_SLICE_OFFSET(t1) // Save current time slice STORE t2, 6*REGBYTES(t1) // Save current time slice
sw x0, 0(t0) // Clear global time slice STORE x0, 0(t0) // Clear global time slice
/* } */ /* } */
@@ -392,7 +392,7 @@ _tx_thread_dont_save_ts:
fence rw, rw // Publish current-thread clear before ready token fence rw, rw // Publish current-thread clear before ready token
addi t0, t1, TX_THREAD_SMP_LOCK_READY_BIT_OFFSET // Pickup lock/ready-bit address addi t0, t1, TX_THREAD_SMP_LOCK_READY_BIT_OFFSET // Pickup lock/ready-bit address
li t2, 1 // Rebuild ready token li t2, 1 // Rebuild ready token
amoswap.w.rl x0, t2, (t0) // Set thread ready token for reschedule AMOSWAP_RL x0, t2, (t0) // Set thread ready token for reschedule
/* } */ /* } */
_tx_thread_idle_system_restore: _tx_thread_idle_system_restore:
@@ -77,18 +77,18 @@ _tx_thread_context_save:
STORE x29, 15*REGBYTES(sp) // Save t4 before reusing it STORE x29, 15*REGBYTES(sp) // Save t4 before reusing it
csrr t2, mhartid // Pickup current hart ID csrr t2, mhartid // Pickup current hart ID
slli t3, t2, 2 // Build per-hart ULONG offset slli t3, t2, LOG_REGBYTES // Build per-hart ULONG offset
slli t4, t2, LOG_REGBYTES // Build per-hart pointer offset slli t4, t2, LOG_REGBYTES // Build per-hart pointer offset
la t1, _tx_thread_system_state // Pickup base of system state array la t1, _tx_thread_system_state // Pickup base of system state array
add t0, t1, t3 // Select this hart's system-state slot add t0, t1, t3 // Select this hart's system-state slot
lw t1, 0(t0) // Pickup system state LOAD t1, 0(t0) // Pickup system state
/* Check for a nested interrupt condition. */ /* Check for a nested interrupt condition. */
/* if (_tx_thread_system_state++) /* if (_tx_thread_system_state++)
{ */ { */
beqz t1, _tx_thread_not_nested_save // If 0, first interrupt condition beqz t1, _tx_thread_not_nested_save // If 0, first interrupt condition
addi t1, t1, 1 // Increment the interrupt counter addi t1, t1, 1 // Increment the interrupt counter
sw t1, 0(t0) // Store the interrupt counter STORE t1, 0(t0) // Store the interrupt counter
/* Nested interrupt condition. /* Nested interrupt condition.
Save the reset of the scratch registers on the stack and return to the Save the reset of the scratch registers on the stack and return to the
@@ -170,7 +170,7 @@ _tx_thread_not_nested_save:
/* else if (_tx_thread_current_ptr) /* else if (_tx_thread_current_ptr)
{ */ { */
addi t1, t1, 1 // Increment the interrupt counter addi t1, t1, 1 // Increment the interrupt counter
sw t1, 0(t0) // Store the interrupt counter STORE t1, 0(t0) // Store the interrupt counter
/* Not nested: Find the user thread that was running and load our SP */ /* Not nested: Find the user thread that was running and load our SP */
@@ -0,0 +1,81 @@
/***************************************************************************
* 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 */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
RETURN_MASK = 0x000000000000000F
SET_SR_MASK = 0xFFFFFFFFFFFFFFF0
.section .text
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_interrupt_control RISC-V64/GNU */
/* 6.2.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for changing the interrupt lockout */
/* posture of the system. */
/* */
/* INPUT */
/* */
/* new_posture New interrupt lockout posture */
/* */
/* OUTPUT */
/* */
/* old_posture Old interrupt lockout posture */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* Application Code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 03-08-2023 Scott Larson Initial Version 6.2.1 */
/* */
/**************************************************************************/
/* UINT _tx_thread_interrupt_control(UINT new_posture)
{ */
.global _tx_thread_interrupt_control
_tx_thread_interrupt_control:
/* Pickup current interrupt lockout posture. */
csrr t0, mstatus
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
csrw mstatus, t0
andi a0, t1, RETURN_MASK // Return original mstatus.
ret
/* } */
+8 -13
View File
@@ -80,26 +80,21 @@ _tx_thread_schedule:
la t0, _tx_thread_execute_ptr // Pickup address of execute ptr la t0, _tx_thread_execute_ptr // Pickup address of execute ptr
add t0, t0, t4 // Select this hart's execute slot add t0, t0, t4 // Select this hart's execute slot
_tx_thread_schedule_loop: _tx_thread_schedule_loop:
csrci mstatus, 0x08 // Lockout interrupts
LOAD t1, 0(t0) // Pickup next thread to execute
bnez t1, _tx_thread_schedule_thread // If non-NULL, continue
csrsi mstatus, 0x08 // Enable interrupts
#ifdef TX_ENABLE_WFI #ifdef TX_ENABLE_WFI
csrci mstatus, 0x08 // Lockout interrupts
LOAD t1, 0(t0) // Pickup next thread to execute
bnez t1, _tx_thread_schedule_thread // If non-NULL, continue
csrsi mstatus, 0x08 // Enable interrupts
wfi // Wait for interrupt wfi // Wait for interrupt
j _tx_thread_schedule_loop // Keep looking for a thread
#else
csrci mstatus, 0x08 // Lockout interrupts
LOAD t1, 0(t0) // Pickup next thread to execute
bnez t1, _tx_thread_schedule_thread // If non-NULL, continue
csrsi mstatus, 0x08 // Enable interrupts
j _tx_thread_schedule_loop // Keep looking for a thread
#endif #endif
j _tx_thread_schedule_loop // Keep looking for a thread
_tx_thread_schedule_thread: _tx_thread_schedule_thread:
/* Atomically claim the thread's ready token so only one hart can /* Atomically claim the thread's ready token so only one hart can
dispatch this TCB at a time. */ dispatch this TCB at a time. */
addi t2, t1, TX_THREAD_SMP_LOCK_READY_BIT_OFFSET // Pickup lock/ready-bit address addi t2, t1, TX_THREAD_SMP_LOCK_READY_BIT_OFFSET // Pickup lock/ready-bit address
amoswap.w.aq t3, x0, (t2) // Clear it and fetch prior state AMOSWAP_AQ t3, x0, (t2) // Clear it and fetch prior state
beqz t3, _tx_thread_schedule // If not ready, retry scheduling beqz t3, _tx_thread_schedule // If not ready, retry scheduling
/* } /* }
@@ -120,7 +115,7 @@ _tx_thread_schedule_thread:
and restart so the new selection is not missed. */ and restart so the new selection is not missed. */
STORE x0, 0(t5) // Clear current thread pointer STORE x0, 0(t5) // Clear current thread pointer
li t3, 1 // Rebuild ready token li t3, 1 // Rebuild ready token
amoswap.w.rl x0, t3, (t2) // Restore ready token with release ordering AMOSWAP_RL x0, t3, (t2) // Restore ready token with release ordering
j _tx_thread_schedule_loop // Restart scheduling j _tx_thread_schedule_loop // Restart scheduling
_execute_pointer_did_not_change: _execute_pointer_did_not_change:
@@ -8,7 +8,7 @@
_tx_thread_smp_current_state_get: _tx_thread_smp_current_state_get:
csrr t0, mhartid // Pickup current hart ID csrr t0, mhartid // Pickup current hart ID
la t1, _tx_thread_system_state // Base of per-hart system-state array la t1, _tx_thread_system_state // Base of per-hart system-state array
slli t0, t0, 2 // Build offset into array slli t0, t0, LOG_REGBYTES // Build offset into array
add t1, t1, t0 // Select this hart's slot add t1, t1, t0 // Select this hart's slot
LWU a0, 0(t1) // Return current system state LOAD a0, 0(t1) // Return current system state
ret ret
@@ -16,17 +16,21 @@ _tx_thread_smp_initialize_wait:
beqz t0, _tx_thread_smp_initialize_done // Core 0 does not wait beqz t0, _tx_thread_smp_initialize_done // Core 0 does not wait
/* Build per-hart offsets for ULONG and pointer arrays. */ /* Build per-hart offsets for ULONG and pointer arrays. */
slli t1, t0, 2 // ULONG array offset slli t1, t0, LOG_REGBYTES // ULONG array offset
slli t2, t0, LOG_REGBYTES // Pointer array offset slli t2, t0, LOG_REGBYTES // Pointer array offset
/* Wait until ThreadX has acknowledged this hart by setting its /* Wait until ThreadX has acknowledged this hart by setting its
system state to TX_INITIALIZE_IN_PROGRESS. */ system state to TX_INITIALIZE_IN_PROGRESS. */
li t3, 0xF0F0F0F0 // TX_INITIALIZE_IN_PROGRESS li t3, 0xF0F0F0F0 // TX_INITIALIZE_IN_PROGRESS
#if __riscv_xlen == 64
slli t3, t3, 32
srli t3, t3, 32
#endif
la t4, _tx_thread_system_state // Base of system state array la t4, _tx_thread_system_state // Base of system state array
add t5, t4, t1 // This hart's system state slot add t5, t4, t1 // This hart's system state slot
_tx_thread_smp_wait_for_initialize: _tx_thread_smp_wait_for_initialize:
LWU t6, 0(t5) // Pickup current hart's system state LOAD t6, 0(t5) // Pickup current hart's system state
bne t6, t3, _tx_thread_smp_wait_for_initialize bne t6, t3, _tx_thread_smp_wait_for_initialize
/* Save the system stack pointer for this hart. */ /* Save the system stack pointer for this hart. */
@@ -38,15 +42,15 @@ _tx_thread_smp_wait_for_initialize:
la t3, _tx_thread_smp_release_cores_flag // Release flag address la t3, _tx_thread_smp_release_cores_flag // Release flag address
_tx_thread_smp_wait_for_release: _tx_thread_smp_wait_for_release:
LWU t6, 0(t3) // Pickup release flag LOAD t6, 0(t3) // Pickup release flag
beqz t6, _tx_thread_smp_wait_for_release beqz t6, _tx_thread_smp_wait_for_release
/* Acknowledge the release by clearing this hart's system state. */ /* Acknowledge the release by clearing this hart's system state. */
sw x0, 0(t5) // Set this hart's system state to zero STORE x0, 0(t5) // Set this hart's system state to zero
/* Wait for core 0 to finish initialization. */ /* Wait for core 0 to finish initialization. */
_tx_thread_smp_wait_for_core0: _tx_thread_smp_wait_for_core0:
LWU t6, 0(t4) // Pickup core 0 system state LOAD t6, 0(t4) // Pickup core 0 system state
bnez t6, _tx_thread_smp_wait_for_core0 bnez t6, _tx_thread_smp_wait_for_core0
/* Prepare interrupt state */ /* Prepare interrupt state */
+7 -14
View File
@@ -18,30 +18,23 @@ _tx_thread_smp_protect:
la t1, _tx_thread_smp_protection la t1, _tx_thread_smp_protection
/* If this hart already owns protection, just nest the count. */ /* If this hart already owns protection, just nest the count. */
LWU t3, 4(t1) // Pickup owning hart LOAD t3, 1*REGBYTES(t1) // Pickup owning hart
beq t3, t2, _owned // Already owned by this hart beq t3, t2, _owned // Already owned by this hart
/* Try to get the protection. */ /* Try to get the protection. */
LWU t4, 0(t1) // Pickup protection flag LOAD t4, 0(t1) // Pickup protection flag
beqz t4, _get_protection // If clear, try to claim it bnez t4, _protection_busy // If set, protection is busy
/* Protection is busy. Restore interrupts and retry. */
csrw mstatus, a0 // Restore interrupts
j _tx_thread_smp_protect // Restart the protection attempt
_get_protection:
li t4, 1 // Build lock value li t4, 1 // Build lock value
amoswap.w.aq t5, t4, (t1) // Attempt to get protection AMOSWAP_AQ t5, t4, (t1) // Attempt to get protection
bnez t5, _protection_busy // If old value != 0, retry bnez t5, _protection_busy // If old value != 0, retry
_got_protection:
fence rw, rw // Ensure lock acquisition is visible fence rw, rw // Ensure lock acquisition is visible
sw t2, 4(t1) // Save owning hart STORE t2, 1*REGBYTES(t1) // Save owning hart
_owned: _owned:
LWU t5, 8(t1) // Pickup ownership count LOAD t5, 2*REGBYTES(t1) // Pickup ownership count
addi t5, t5, 1 // Increment ownership count addi t5, t5, 1 // Increment ownership count
sw t5, 8(t1) // Store ownership count STORE t5, 2*REGBYTES(t1) // Store ownership count
fence rw, rw // Publish owner/count before return fence rw, rw // Publish owner/count before return
ret ret
@@ -17,14 +17,14 @@ _tx_thread_smp_unprotect:
la t2, _tx_thread_smp_protection la t2, _tx_thread_smp_protection
/* Only the owning hart may release the protection. */ /* Only the owning hart may release the protection. */
LWU t3, 4(t2) // Pickup owning hart LOAD t3, 1*REGBYTES(t2) // Pickup owning hart
bne t1, t3, _still_protected // Not owner, skip release bne t1, t3, _still_protected // Not owner, skip release
/* Pickup and decrement the protection count. */ /* Pickup and decrement the protection count. */
LWU t3, 8(t2) // Pickup protection count LOAD t3, 2*REGBYTES(t2) // Pickup protection count
beqz t3, _still_protected // Already cleared beqz t3, _still_protected // Already cleared
addi t3, t3, -1 // Decrement protection count addi t3, t3, -1 // Decrement protection count
sw t3, 8(t2) // Store new count STORE t3, 2*REGBYTES(t2) // Store new count
bnez t3, _still_protected // Still nested, stay protected bnez t3, _still_protected // Still nested, stay protected
/* If preemption is disabled, keep protection in force. */ /* If preemption is disabled, keep protection in force. */
@@ -34,9 +34,8 @@ _tx_thread_smp_unprotect:
/* Release the protection. */ /* Release the protection. */
li t3, -1 // Invalid owner value li t3, -1 // Invalid owner value
sw t3, 4(t2) // Mark owning hart invalid STORE t3, 1*REGBYTES(t2) // Mark owning hart invalid
fence rw, rw // Ensure shared accesses complete AMOSWAP_RL x0, x0, (t2) // Release protection flag
amoswap.w.rl x0, x0, (t2) // Release protection flag
_still_protected: _still_protected:
csrw mstatus, a0 // Restore interrupt posture csrw mstatus, a0 // Restore interrupt posture
+3 -3
View File
@@ -138,8 +138,8 @@ If floating point support:
Stack Bottom: (higher memory address) */ Stack Bottom: (higher memory address) */
LOAD t0, TX_THREAD_STACK_END_OFFSET(a0) // Pickup end of stack area LOAD t0, 4*REGBYTES(a0) // Pickup end of stack area
andi t0, t0, -4*REGBYTES // Ensure alignment (16-byte for RV32 & 32-byte for RV64) andi t0, t0, -16 // Ensure 16-byte alignment
/* Actually build the stack frame. */ /* Actually build the stack frame. */
@@ -224,6 +224,6 @@ If floating point support:
STORE t0, 2*REGBYTES(a0) // Save stack pointer in thread's STORE t0, 2*REGBYTES(a0) // Save stack pointer in thread's
addi t1, x0, 1 // Build ready flag addi t1, x0, 1 // Build ready flag
sw t1, TX_THREAD_SMP_LOCK_READY_BIT_OFFSET(a0) // Set ready flag STORE t1, TX_THREAD_SMP_LOCK_READY_BIT_OFFSET(a0) // Set ready flag
ret // control block and return ret // control block and return
/* } */ /* } */
@@ -136,7 +136,7 @@ _tx_thread_system_return:
#endif #endif
csrr t5, mhartid // Pickup current hart ID csrr t5, mhartid // Pickup current hart ID
slli t6, t5, 2 // Build per-hart ULONG offset slli t6, t5, LOG_REGBYTES // Build per-hart ULONG offset
slli t5, t5, LOG_REGBYTES // Build per-hart pointer offset slli t5, t5, LOG_REGBYTES // Build per-hart pointer offset
la t0, _tx_thread_current_ptr // Pickup base of current-thread array la t0, _tx_thread_current_ptr // Pickup base of current-thread array
@@ -158,7 +158,7 @@ _tx_thread_system_return:
la t4, _tx_timer_time_slice // Pickup base of time-slice array la t4, _tx_timer_time_slice // Pickup base of time-slice array
add t4, t4, t6 // Select this hart's time-slice slot add t4, t4, t6 // Select this hart's time-slice slot
lw t3, 0(t4) // Pickup time slice value LOAD t3, 0(t4) // Pickup time slice value
la t2, _tx_thread_schedule // Pickup address of scheduling loop 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 beqz t3, _tx_thread_dont_save_ts // If no time-slice, don't save it
@@ -166,8 +166,8 @@ _tx_thread_system_return:
/* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice; /* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
_tx_timer_time_slice = 0; */ _tx_timer_time_slice = 0; */
sw t3, TX_THREAD_TIME_SLICE_OFFSET(t1) // Save current time-slice for thread STORE t3, 6*REGBYTES(t1) // Save current time-slice for thread
sw x0, 0(t4) // Clear time-slice variable STORE x0, 0(t4) // Clear time-slice variable
/* } */ /* } */
_tx_thread_dont_save_ts: _tx_thread_dont_save_ts:
@@ -181,18 +181,18 @@ _tx_thread_dont_save_ts:
fence rw, rw // Publish current-thread clear before ready token fence rw, rw // Publish current-thread clear before ready token
addi t3, t1, TX_THREAD_SMP_LOCK_READY_BIT_OFFSET // Pickup lock/ready-bit address addi t3, t1, TX_THREAD_SMP_LOCK_READY_BIT_OFFSET // Pickup lock/ready-bit address
li t4, 1 // Build ready token li t4, 1 // Build ready token
amoswap.w.rl x0, t4, (t3) // Restore ready token AMOSWAP_RL x0, t4, (t3) // Restore ready token
/* Clear protection state. */ /* Clear protection state. */
la t3, _tx_thread_preempt_disable // Pickup preempt-disable address la t3, _tx_thread_preempt_disable // Pickup preempt-disable address
sw x0, 0(t3) // Clear preempt disable flag sw x0, 0(t3) // Clear preempt disable flag
la t3, _tx_thread_smp_protection // Pickup protection structure la t3, _tx_thread_smp_protection // Pickup protection structure
sw x0, 8(t3) // Clear protection count STORE x0, 2*REGBYTES(t3) // Clear protection count
li t4, -1 // Build invalid owner value li t4, -1 // Build invalid owner value
sw t4, 4(t3) // Invalidate owning hart STORE t4, 1*REGBYTES(t3) // Invalidate owning hart
fence rw, rw // Ensure shared accesses complete before unlock fence rw, rw // Ensure shared accesses complete before unlock
sw x0, 0(t3) // Clear protection in-force flag STORE x0, 0(t3) // Clear protection in-force flag
jr t2 // Return to thread scheduler jr t2 // Return to thread scheduler
/* } */ /* } */
+4 -4
View File
@@ -137,11 +137,11 @@ void thread_0_entry(ULONG thread_input)
UINT status; UINT status;
NX_PACKET* my_packet; NX_PACKET* my_packet;
ULONG length; UINT32 length;
NXD_ADDRESS server_ipv4_address; NXD_ADDRESS server_ipv4_address;
NXD_ADDRESS peer_address; NXD_ADDRESS peer_address;
ULONG peer_port; UINT32 peer_port;
NX_PARAMETER_NOT_USED(thread_input); NX_PARAMETER_NOT_USED(thread_input);
@@ -259,7 +259,7 @@ void thread_1_entry(ULONG thread_input)
UINT status; UINT status;
NX_PACKET* packet_ptr; NX_PACKET* packet_ptr;
ULONG actual_status; UINT32 actual_status;
NX_PARAMETER_NOT_USED(thread_input); NX_PARAMETER_NOT_USED(thread_input);
@@ -331,7 +331,7 @@ void thread_1_entry(ULONG thread_input)
else else
{ {
char buffer[64]; char buffer[64];
ULONG size; UINT32 size;
nx_packet_data_extract_offset(packet_ptr, 0, buffer, 64, &size); nx_packet_data_extract_offset(packet_ptr, 0, buffer, 64, &size);
buffer[size] = 0; buffer[size] = 0;
printf("Received packet %lu with %s\n", thread_1_counter, buffer); printf("Received packet %lu with %s\n", thread_1_counter, buffer);
+3
View File
@@ -184,6 +184,9 @@ void tx_application_define(void* first_unused_memory)
/* Release the block back to the pool. */ /* Release the block back to the pool. */
tx_block_release(pointer); tx_block_release(pointer);
/* Enable tracing */
tx_trace_enable((void*)0x31000000, 0x100000, 256);
} }
/* Define the test threads. */ /* Define the test threads. */
-102
View File
@@ -1,102 +0,0 @@
cmake_minimum_required(VERSION 3.21)
set(BUILD_SHARED_LIBS OFF)
get_filename_component(THREADX4TGFS_ROOT "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE)
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
set(CMAKE_TOOLCHAIN_FILE
${THREADX4TGFS_ROOT}/cmake/rv32imac_gnu.cmake
CACHE FILEPATH "Toolchain file")
endif()
include(${CMAKE_TOOLCHAIN_FILE})
set(__THREAD_LOCAL_STORAGE OFF)
add_subdirectory(${THREADX4TGFS_ROOT}/third-party/picolibc ${CMAKE_BINARY_DIR}/picolibc)
target_link_libraries(c PUBLIC gcc)
set(THREADX_CUSTOM_PORT ${THREADX4TGFS_ROOT}/port/threadx)
add_subdirectory(${THREADX4TGFS_ROOT}/third-party/threadx ${CMAKE_BINARY_DIR}/threadx)
target_link_libraries(threadx PUBLIC c)
target_compile_definitions(threadx PUBLIC TX_REGRESSION_TEST)
project(threadx_regression C ASM)
enable_testing()
set(TARGET_MEM "ram_dram" CACHE STRING "memory map to use")
set(CMAKE_EXECUTABLE_SUFFIX_C ".elf")
set(THREADX_TEST_SIMULATOR
""
CACHE FILEPATH "Path to the RISC-V VP executable used by CTest")
if(NOT THREADX_TEST_SIMULATOR)
message(FATAL_ERROR
"THREADX_TEST_SIMULATOR is not set. Configure with -DTHREADX_TEST_SIMULATOR=/path/to/riscv-vp")
endif()
# Evaluate the variable from the toolchain file to decide which XLEN we are targetting (IMAC only!)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "risc-v32")
set(THREADX_TEST_ISA "rv32imac_m")
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "risc-v64")
set(THREADX_TEST_ISA "rv64imac_m")
else()
message(FATAL_ERROR
"Unsupported CMAKE_SYSTEM_PROCESSOR for VP ISA selection: ${CMAKE_SYSTEM_PROCESSOR}")
endif()
# The regression tests require the Timer ISR to call the function test_interrupt_dispatch(void)
# We patch the current trap handler and include it using MOONLIGHT_TRAP_SOURCE.
set(MOONLIGHT_TRAP_SOURCE_INPUT ${THREADX4TGFS_ROOT}/port/moonlight/src/trap_non_vectored.c)
set(MOONLIGHT_TRAP_SOURCE ${CMAKE_BINARY_DIR}/generated/trap_non_vectored.c)
add_custom_command(
OUTPUT ${MOONLIGHT_TRAP_SOURCE}
COMMAND bash ${CMAKE_CURRENT_LIST_DIR}/threadx/generate_trap_file.sh
${MOONLIGHT_TRAP_SOURCE_INPUT}
${MOONLIGHT_TRAP_SOURCE}
DEPENDS ${MOONLIGHT_TRAP_SOURCE_INPUT}
${CMAKE_CURRENT_LIST_DIR}/threadx/generate_trap_file.sh
VERBATIM
)
add_custom_target(threadx_regression_generated_trap DEPENDS ${MOONLIGHT_TRAP_SOURCE})
set_source_files_properties(${MOONLIGHT_TRAP_SOURCE} PROPERTIES GENERATED TRUE)
add_subdirectory(${THREADX4TGFS_ROOT}/port/moonlight ${CMAKE_BINARY_DIR}/port/moonlight)
add_dependencies(moonlight_platform_common threadx_regression_generated_trap)
function(setup_target TARGET)
set(options)
set(multiValueArgs LIBRARIES SOURCES)
cmake_parse_arguments(ST "${options}" "" "${multiValueArgs}" ${ARGN})
if(ST_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "setup_target(${TARGET} ...): unknown args: ${ST_UNPARSED_ARGUMENTS}")
endif()
add_executable(${TARGET})
set_target_properties(${TARGET} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
)
target_add_moonlight_platform(${TARGET})
if(ST_SOURCES)
target_sources(${TARGET} PRIVATE ${ST_SOURCES})
endif()
if(ST_LIBRARIES)
target_link_libraries(${TARGET} PRIVATE ${ST_LIBRARIES})
endif()
target_link_options(${TARGET} PRIVATE
-nostartfiles
-nostdlib
-T ${THREADX4TGFS_ROOT}/src/${TARGET_MEM}.lds
-Wl,--gc-sections
-Wl,-Map=${CMAKE_BINARY_DIR}/${TARGET}.map)
add_custom_command(TARGET ${TARGET} POST_BUILD
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}> > ${CMAKE_BINARY_DIR}/${TARGET}.dis
#COMMENT "Creating collateral for ${TARGET}"
)
endfunction()
add_subdirectory(threadx regression_targets)
-90
View File
@@ -1,90 +0,0 @@
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 24,
"patch": 0
},
"configurePresets": [
{
"name": "Debug",
"binaryDir": "${sourceDir}/../build/${presetName}/test",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../cmake/rv64imac_gnu.cmake",
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "Debug32",
"binaryDir": "${sourceDir}/../build/${presetName}/test",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../cmake/rv32imac_gnu.cmake",
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "Release",
"binaryDir": "${sourceDir}/../build/${presetName}/test",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../cmake/rv64imac_gnu.cmake",
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "Release32",
"binaryDir": "${sourceDir}/../build/${presetName}/test",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../cmake/rv32imac_gnu.cmake",
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "MinSizeRel",
"binaryDir": "${sourceDir}/../build/${presetName}/test",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../cmake/rv64imac_gnu.cmake",
"CMAKE_BUILD_TYPE": "MinSizeRel",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "MinSizeRel32",
"binaryDir": "${sourceDir}/../build/${presetName}/test",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../cmake/rv32imac_gnu.cmake",
"CMAKE_BUILD_TYPE": "MinSizeRel",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
}
],
"buildPresets": [
{
"name": "Debug",
"configurePreset": "Debug"
},
{
"name": "Debug32",
"configurePreset": "Debug32"
},
{
"name": "Release",
"configurePreset": "Release"
},
{
"name": "Release32",
"configurePreset": "Release32"
},
{
"name": "MinSizeRel",
"configurePreset": "MinSizeRel"
},
{
"name": "MinSizeRel32",
"configurePreset": "MinSizeRel32"
}
]
}
+265
View File
@@ -0,0 +1,265 @@
cmake_minimum_required(VERSION 3.21)
set(BUILD_SHARED_LIBS OFF)
get_filename_component(THREADX4TGFS_ROOT "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE)
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
set(CMAKE_TOOLCHAIN_FILE
${THREADX4TGFS_ROOT}/cmake/rv32imac_gnu.cmake
CACHE FILEPATH "Toolchain file")
endif()
include(${CMAKE_TOOLCHAIN_FILE})
project(threadx_smp_regression LANGUAGES C ASM)
enable_testing()
set(TARGET_MEM "ram_dram" CACHE STRING "memory map to use")
set(CMAKE_EXECUTABLE_SUFFIX_C ".elf")
set(THREADX_TEST_SIMULATOR
""
CACHE FILEPATH "Path to the RISC-V VP executable used by CTest")
if(NOT THREADX_TEST_SIMULATOR)
message(FATAL_ERROR
"THREADX_TEST_SIMULATOR is not set. Configure with -DTHREADX_TEST_SIMULATOR=/path/to/riscv-vp")
endif()
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "risc-v32")
set(THREADX_TEST_ISA "rv32imac_m")
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "risc-v64")
set(THREADX_TEST_ISA "rv64imac_m")
else()
message(FATAL_ERROR
"Unsupported CMAKE_SYSTEM_PROCESSOR for VP ISA selection: ${CMAKE_SYSTEM_PROCESSOR}")
endif()
set(__THREAD_LOCAL_STORAGE OFF)
add_subdirectory(${THREADX4TGFS_ROOT}/third-party/picolibc ${CMAKE_BINARY_DIR}/picolibc)
target_link_libraries(c PUBLIC gcc)
set(THREADX_LOW_LEVEL_INIT_SOURCE_INPUT
${THREADX4TGFS_ROOT}/port/threadx_smp/src/tx_initialize_low_level.c)
set(THREADX_LOW_LEVEL_INIT_SOURCE
${CMAKE_BINARY_DIR}/generated/tx_initialize_low_level.c)
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
${THREADX_LOW_LEVEL_INIT_SOURCE_INPUT}
${THREADX4TGFS_ROOT}/test/threadx/generate_trap_file.sh)
execute_process(
COMMAND bash ${THREADX4TGFS_ROOT}/test/threadx/generate_trap_file.sh
${THREADX_LOW_LEVEL_INIT_SOURCE_INPUT}
${THREADX_LOW_LEVEL_INIT_SOURCE}
RESULT_VARIABLE THREADX_LOW_LEVEL_INIT_GENERATE_RESULT
COMMAND_ERROR_IS_FATAL ANY
)
add_subdirectory(${THREADX4TGFS_ROOT}/port/moonlight ${CMAKE_BINARY_DIR}/port/moonlight)
target_sources(c PRIVATE ${THREADX4TGFS_ROOT}/port/picolibc/port.c)
target_link_libraries(c PUBLIC moonlight gcc)
add_subdirectory(${THREADX4TGFS_ROOT}/port/threadx_smp ${CMAKE_BINARY_DIR}/port/threadx_smp)
target_link_libraries(threadx_smp PUBLIC moonlight c)
target_compile_definitions(threadx_smp PUBLIC TX_REGRESSION_TEST TX_THREAD_SMP_ONLY_CORE_0_DEFAULT TX_SMP_NOT_POSSIBLE)
function(setup_target TARGET)
set(options)
set(multiValueArgs LIBRARIES SOURCES)
cmake_parse_arguments(ST "${options}" "" "${multiValueArgs}" ${ARGN})
if(ST_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "setup_target(${TARGET} ...): unknown args: ${ST_UNPARSED_ARGUMENTS}")
endif()
add_executable(${TARGET})
set_target_properties(${TARGET} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
)
if(ST_SOURCES)
target_sources(${TARGET} PRIVATE ${ST_SOURCES})
endif()
if(ST_LIBRARIES)
target_link_libraries(${TARGET} PRIVATE ${ST_LIBRARIES})
endif()
target_link_options(${TARGET} PRIVATE
-Wl,-Map=${CMAKE_BINARY_DIR}/${TARGET}.map)
add_custom_command(TARGET ${TARGET} POST_BUILD
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 ${OBJDUMP} -S $<TARGET_FILE:${TARGET}> > ${CMAKE_BINARY_DIR}/${TARGET}.dis
)
endfunction()
set(TX_REGRESSION_DIR
${THREADX4TGFS_ROOT}/third-party/threadx/test/smp/regression
)
set(TX_CMAKE_DIR
${THREADX4TGFS_ROOT}/third-party/threadx/test/tx/cmake
)
set(TX_REGRESSION_CASES
${TX_REGRESSION_DIR}/threadx_block_memory_basic_test.c
${TX_REGRESSION_DIR}/threadx_block_memory_error_detection_test.c
${TX_REGRESSION_DIR}/threadx_block_memory_information_test.c
${TX_REGRESSION_DIR}/threadx_block_memory_prioritize_test.c
${TX_REGRESSION_DIR}/threadx_block_memory_suspension_test.c
${TX_REGRESSION_DIR}/threadx_block_memory_suspension_timeout_test.c
${TX_REGRESSION_DIR}/threadx_block_memory_thread_terminate_test.c
${TX_REGRESSION_DIR}/threadx_byte_memory_basic_test.c
${TX_REGRESSION_DIR}/threadx_byte_memory_information_test.c
${TX_REGRESSION_DIR}/threadx_byte_memory_prioritize_test.c
${TX_REGRESSION_DIR}/threadx_byte_memory_suspension_test.c
${TX_REGRESSION_DIR}/threadx_byte_memory_suspension_timeout_test.c
${TX_REGRESSION_DIR}/threadx_byte_memory_thread_contention_test.c
${TX_REGRESSION_DIR}/threadx_byte_memory_thread_terminate_test.c
${TX_REGRESSION_DIR}/threadx_event_flag_basic_test.c
${TX_REGRESSION_DIR}/threadx_event_flag_information_test.c
${TX_REGRESSION_DIR}/threadx_event_flag_isr_set_clear_test.c
${TX_REGRESSION_DIR}/threadx_event_flag_isr_wait_abort_test.c
${TX_REGRESSION_DIR}/threadx_event_flag_single_thread_terminate_test.c
${TX_REGRESSION_DIR}/threadx_event_flag_suspension_consume_test.c
${TX_REGRESSION_DIR}/threadx_event_flag_suspension_different_bits_consume_test.c
${TX_REGRESSION_DIR}/threadx_event_flag_suspension_different_bits_test.c
${TX_REGRESSION_DIR}/threadx_event_flag_suspension_test.c
${TX_REGRESSION_DIR}/threadx_event_flag_suspension_timeout_test.c
${TX_REGRESSION_DIR}/threadx_event_flag_thread_terminate_test.c
${TX_REGRESSION_DIR}/threadx_initialize_kernel_setup_test.c
${TX_REGRESSION_DIR}/threadx_interrupt_control_test.c
${TX_REGRESSION_DIR}/threadx_mutex_basic_test.c
${TX_REGRESSION_DIR}/threadx_mutex_delete_test.c
${TX_REGRESSION_DIR}/threadx_mutex_information_test.c
${TX_REGRESSION_DIR}/threadx_mutex_nested_priority_inheritance_test.c
${TX_REGRESSION_DIR}/threadx_mutex_no_preemption_test.c
${TX_REGRESSION_DIR}/threadx_mutex_preemption_test.c
${TX_REGRESSION_DIR}/threadx_mutex_priority_inheritance_test.c
${TX_REGRESSION_DIR}/threadx_mutex_proritize_test.c
${TX_REGRESSION_DIR}/threadx_mutex_suspension_timeout_test.c
${TX_REGRESSION_DIR}/threadx_mutex_thread_terminate_test.c
${TX_REGRESSION_DIR}/threadx_queue_basic_eight_word_test.c
${TX_REGRESSION_DIR}/threadx_queue_basic_four_word_test.c
${TX_REGRESSION_DIR}/threadx_queue_basic_max_message_size_test.c
${TX_REGRESSION_DIR}/threadx_queue_basic_one_word_test.c
${TX_REGRESSION_DIR}/threadx_queue_basic_sixteen_word_test.c
${TX_REGRESSION_DIR}/threadx_queue_basic_two_word_test.c
${TX_REGRESSION_DIR}/threadx_queue_empty_suspension_test.c
${TX_REGRESSION_DIR}/threadx_queue_flush_no_suspension_test.c
${TX_REGRESSION_DIR}/threadx_queue_flush_test.c
${TX_REGRESSION_DIR}/threadx_queue_front_send_test.c
${TX_REGRESSION_DIR}/threadx_queue_full_suspension_test.c
${TX_REGRESSION_DIR}/threadx_queue_information_test.c
${TX_REGRESSION_DIR}/threadx_queue_prioritize.c
${TX_REGRESSION_DIR}/threadx_queue_suspension_timeout_test.c
${TX_REGRESSION_DIR}/threadx_queue_thread_terminate_test.c
${TX_REGRESSION_DIR}/threadx_semaphore_basic_test.c
${TX_REGRESSION_DIR}/threadx_semaphore_ceiling_put_test.c
${TX_REGRESSION_DIR}/threadx_semaphore_delete_test.c
${TX_REGRESSION_DIR}/threadx_semaphore_information_test.c
${TX_REGRESSION_DIR}/threadx_semaphore_non_preemption_test.c
${TX_REGRESSION_DIR}/threadx_semaphore_preemption_test.c
${TX_REGRESSION_DIR}/threadx_semaphore_prioritize.c
${TX_REGRESSION_DIR}/threadx_semaphore_thread_terminate_test.c
${TX_REGRESSION_DIR}/threadx_semaphore_timeout_test.c
${TX_REGRESSION_DIR}/threadx_smp_multiple_threads_one_core_test.c
${TX_REGRESSION_DIR}/threadx_smp_non_trivial_scheduling_test.c
${TX_REGRESSION_DIR}/threadx_smp_one_thread_dynamic_exclusion_test.c
${TX_REGRESSION_DIR}/threadx_smp_preemption_threshold_test.c
${TX_REGRESSION_DIR}/threadx_smp_random_resume_suspend_exclusion_pt_test.c
${TX_REGRESSION_DIR}/threadx_smp_random_resume_suspend_exclusion_test.c
${TX_REGRESSION_DIR}/threadx_smp_random_resume_suspend_test.c
${TX_REGRESSION_DIR}/threadx_smp_rebalance_exclusion_test.c
${TX_REGRESSION_DIR}/threadx_smp_relinquish_test.c
${TX_REGRESSION_DIR}/threadx_smp_resume_suspend_accending_order_test.c
${TX_REGRESSION_DIR}/threadx_smp_resume_suspend_decending_order_test.c
${TX_REGRESSION_DIR}/threadx_smp_time_slice_test.c
${TX_REGRESSION_DIR}/threadx_smp_two_threads_one_core_test.c
${TX_REGRESSION_DIR}/threadx_thread_basic_execution_test.c
${TX_REGRESSION_DIR}/threadx_thread_basic_time_slice_test.c
${TX_REGRESSION_DIR}/threadx_thread_completed_test.c
${TX_REGRESSION_DIR}/threadx_thread_create_preemption_threshold_test.c
${TX_REGRESSION_DIR}/threadx_thread_delayed_suspension_test.c
${TX_REGRESSION_DIR}/threadx_thread_information_test.c
${TX_REGRESSION_DIR}/threadx_thread_multi_level_preemption_threshold_test.c
${TX_REGRESSION_DIR}/threadx_thread_multiple_non_current_test.c
${TX_REGRESSION_DIR}/threadx_thread_multiple_sleep_test.c
${TX_REGRESSION_DIR}/threadx_thread_multiple_suspension_test.c
${TX_REGRESSION_DIR}/threadx_thread_multiple_time_slice_test.c
${TX_REGRESSION_DIR}/threadx_thread_preemptable_suspension_test.c
${TX_REGRESSION_DIR}/threadx_thread_preemption_change_test.c
${TX_REGRESSION_DIR}/threadx_thread_priority_change.c
${TX_REGRESSION_DIR}/threadx_thread_relinquish_test.c
${TX_REGRESSION_DIR}/threadx_thread_reset_test.c
${TX_REGRESSION_DIR}/threadx_thread_simple_sleep_non_clear_test.c
${TX_REGRESSION_DIR}/threadx_thread_simple_sleep_test.c
${TX_REGRESSION_DIR}/threadx_thread_simple_suspend_test.c
${TX_REGRESSION_DIR}/threadx_thread_sleep_for_100ticks_test.c
${TX_REGRESSION_DIR}/threadx_thread_sleep_terminate_test.c
${TX_REGRESSION_DIR}/threadx_thread_stack_checking_test.c
${TX_REGRESSION_DIR}/threadx_thread_terminate_delete_test.c
${TX_REGRESSION_DIR}/threadx_thread_time_slice_change_test.c
${TX_REGRESSION_DIR}/threadx_thread_wait_abort_and_isr_test.c
${TX_REGRESSION_DIR}/threadx_thread_wait_abort_test.c
${TX_REGRESSION_DIR}/threadx_time_get_set_test.c
${TX_REGRESSION_DIR}/threadx_timer_activate_deactivate_test.c
${TX_REGRESSION_DIR}/threadx_timer_deactivate_accuracy_test.c
${TX_REGRESSION_DIR}/threadx_timer_information_test.c
${TX_REGRESSION_DIR}/threadx_timer_large_timer_accuracy_test.c
${TX_REGRESSION_DIR}/threadx_timer_multiple_accuracy_test.c
${TX_REGRESSION_DIR}/threadx_timer_multiple_test.c
${TX_REGRESSION_DIR}/threadx_timer_simple_test.c
#${TX_REGRESSION_DIR}/threadx_trace_basic_test.c #windows specifics in the test
)
add_library(
threadx_smp_regression_support STATIC
${TX_REGRESSION_DIR}/testcontrol.c
${TX_CMAKE_DIR}/samples/fake.c
)
target_link_libraries(threadx_smp_regression_support PUBLIC threadx_smp c)
target_compile_definitions(
threadx_smp_regression_support
PUBLIC
TX_REGRESSION_TEST
TX_THREAD_SMP_ONLY_CORE_0_DEFAULT
TX_SMP_NOT_POSSIBLE
CTEST
BATCH_TEST
TEST_STACK_SIZE_PRINTF=4096
)
function(add_threadx_regression_test TEST_SOURCE)
get_filename_component(TEST_NAME ${TEST_SOURCE} NAME_WE)
if(TEST_NAME STREQUAL "threadx_initialize_kernel_setup_test")
set(test_libraries threadx_smp)
else()
set(test_libraries threadx_smp_regression_support)
endif()
setup_target(
${TEST_NAME}
LIBRARIES ${test_libraries}
SOURCES ${TEST_SOURCE}
)
list(APPEND TX_REGRESSION_TARGETS ${TEST_NAME})
set(TX_REGRESSION_TARGETS ${TX_REGRESSION_TARGETS} PARENT_SCOPE)
add_test(
NAME ${TEST_NAME}
COMMAND ${THREADX_TEST_SIMULATOR}
--isa=${THREADX_TEST_ISA}
-f $<TARGET_FILE:${TEST_NAME}>
-m 60s
-p tb.top.num_cores=4
)
set_tests_properties(${TEST_NAME} PROPERTIES TIMEOUT 60)
endfunction()
foreach(test_case ${TX_REGRESSION_CASES})
add_threadx_regression_test(${test_case})
endforeach()
add_custom_target(
threadx_smp_regression_build
DEPENDS ${TX_REGRESSION_TARGETS}
)
+72
View File
@@ -0,0 +1,72 @@
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 24,
"patch": 0
},
"configurePresets": [
{
"name": "Debug",
"binaryDir": "${sourceDir}/../../build/${presetName}/test/smp",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../../cmake/rv64imac_gnu.cmake",
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "Debug32",
"binaryDir": "${sourceDir}/../../build/${presetName}/test/smp",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../../cmake/rv32imac_gnu.cmake",
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "Release",
"binaryDir": "${sourceDir}/../../build/${presetName}/test/smp",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../../cmake/rv64imac_gnu.cmake",
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "Release32",
"binaryDir": "${sourceDir}/../../build/${presetName}/test/smp",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../../cmake/rv32imac_gnu.cmake",
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "MinSizeRel",
"binaryDir": "${sourceDir}/../../build/${presetName}/test/smp",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../../cmake/rv64imac_gnu.cmake",
"CMAKE_BUILD_TYPE": "MinSizeRel",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "MinSizeRel32",
"binaryDir": "${sourceDir}/../../build/${presetName}/test/smp",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../../cmake/rv32imac_gnu.cmake",
"CMAKE_BUILD_TYPE": "MinSizeRel",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
}
],
"buildPresets": [
{ "name": "Debug", "configurePreset": "Debug" },
{ "name": "Debug32", "configurePreset": "Debug32" },
{ "name": "Release", "configurePreset": "Release" },
{ "name": "Release32", "configurePreset": "Release32" },
{ "name": "MinSizeRel", "configurePreset": "MinSizeRel" },
{ "name": "MinSizeRel32", "configurePreset": "MinSizeRel32" }
]
}
+100 -39
View File
@@ -1,3 +1,97 @@
cmake_minimum_required(VERSION 3.21)
set(BUILD_SHARED_LIBS OFF)
get_filename_component(THREADX4TGFS_ROOT "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE)
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
set(CMAKE_TOOLCHAIN_FILE
${THREADX4TGFS_ROOT}/cmake/rv32imac_gnu.cmake
CACHE FILEPATH "Toolchain file")
endif()
include(${CMAKE_TOOLCHAIN_FILE})
project(threadx_regression LANGUAGES C ASM)
enable_testing()
set(TARGET_MEM "ram_dram" CACHE STRING "memory map to use")
set(CMAKE_EXECUTABLE_SUFFIX_C ".elf")
set(THREADX_TEST_SIMULATOR
""
CACHE FILEPATH "Path to the RISC-V VP executable used by CTest")
if(NOT THREADX_TEST_SIMULATOR)
message(FATAL_ERROR
"THREADX_TEST_SIMULATOR is not set. Configure with -DTHREADX_TEST_SIMULATOR=/path/to/riscv-vp")
endif()
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "risc-v32")
set(THREADX_TEST_ISA "rv32imac_m")
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "risc-v64")
set(THREADX_TEST_ISA "rv64imac_m")
else()
message(FATAL_ERROR
"Unsupported CMAKE_SYSTEM_PROCESSOR for VP ISA selection: ${CMAKE_SYSTEM_PROCESSOR}")
endif()
set(__THREAD_LOCAL_STORAGE OFF)
add_subdirectory(${THREADX4TGFS_ROOT}/third-party/picolibc ${CMAKE_BINARY_DIR}/picolibc)
target_link_libraries(c PUBLIC gcc)
set(THREADX_LOW_LEVEL_INIT_SOURCE_INPUT
${THREADX4TGFS_ROOT}/port/threadx/src/tx_initialize_low_level.c)
set(THREADX_LOW_LEVEL_INIT_SOURCE
${CMAKE_BINARY_DIR}/generated/tx_initialize_low_level.c)
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
${THREADX_LOW_LEVEL_INIT_SOURCE_INPUT}
${CMAKE_CURRENT_LIST_DIR}/generate_trap_file.sh)
execute_process(
COMMAND bash ${CMAKE_CURRENT_LIST_DIR}/generate_trap_file.sh
${THREADX_LOW_LEVEL_INIT_SOURCE_INPUT}
${THREADX_LOW_LEVEL_INIT_SOURCE}
RESULT_VARIABLE THREADX_LOW_LEVEL_INIT_GENERATE_RESULT
COMMAND_ERROR_IS_FATAL ANY
)
add_subdirectory(${THREADX4TGFS_ROOT}/port/moonlight ${CMAKE_BINARY_DIR}/port/moonlight)
target_sources(c PRIVATE ${THREADX4TGFS_ROOT}/port/picolibc/port.c)
target_link_libraries(c PUBLIC moonlight gcc)
set(THREADX_CUSTOM_PORT ${THREADX4TGFS_ROOT}/port/threadx)
add_subdirectory(${THREADX4TGFS_ROOT}/third-party/threadx ${CMAKE_BINARY_DIR}/threadx)
target_link_libraries(threadx PUBLIC moonlight c)
target_compile_definitions(threadx PUBLIC TX_REGRESSION_TEST)
function(setup_target TARGET)
set(options)
set(multiValueArgs LIBRARIES SOURCES)
cmake_parse_arguments(ST "${options}" "" "${multiValueArgs}" ${ARGN})
if(ST_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "setup_target(${TARGET} ...): unknown args: ${ST_UNPARSED_ARGUMENTS}")
endif()
add_executable(${TARGET})
set_target_properties(${TARGET} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
)
if(ST_SOURCES)
target_sources(${TARGET} PRIVATE ${ST_SOURCES})
endif()
if(ST_LIBRARIES)
target_link_libraries(${TARGET} PRIVATE ${ST_LIBRARIES})
endif()
target_link_options(${TARGET} PRIVATE
-Wl,-Map=${CMAKE_BINARY_DIR}/${TARGET}.map)
add_custom_command(TARGET ${TARGET} POST_BUILD
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 ${OBJDUMP} -S $<TARGET_FILE:${TARGET}> > ${CMAKE_BINARY_DIR}/${TARGET}.dis
)
endfunction()
set(TX_REGRESSION_DIR set(TX_REGRESSION_DIR
${THREADX4TGFS_ROOT}/third-party/threadx/test/tx/regression ${THREADX4TGFS_ROOT}/third-party/threadx/test/tx/regression
) )
@@ -5,23 +99,6 @@ set(TX_CMAKE_DIR
${THREADX4TGFS_ROOT}/third-party/threadx/test/tx/cmake ${THREADX4TGFS_ROOT}/third-party/threadx/test/tx/cmake
) )
# This test needs a local test_interrupt_dispatch() because it does not link testcontrol.c.
set(TX_KERNEL_SETUP_TEST_SOURCE_INPUT ${THREADX4TGFS_ROOT}/third-party/threadx/test/tx/regression/threadx_initialize_kernel_setup_test.c)
set(TX_KERNEL_SETUP_TEST_SOURCE ${CMAKE_BINARY_DIR}/generated/threadx_initialize_kernel_setup_test.c)
add_custom_command(
OUTPUT ${TX_KERNEL_SETUP_TEST_SOURCE}
COMMAND bash ${CMAKE_CURRENT_LIST_DIR}/generate_kernel_setup_test_file.sh
${TX_KERNEL_SETUP_TEST_SOURCE_INPUT}
${TX_KERNEL_SETUP_TEST_SOURCE}
DEPENDS ${TX_KERNEL_SETUP_TEST_SOURCE_INPUT}
${CMAKE_CURRENT_LIST_DIR}/generate_kernel_setup_test_file.sh
VERBATIM
)
add_custom_target(threadx_regression_generated_kernel_setup_test
DEPENDS ${TX_KERNEL_SETUP_TEST_SOURCE}
)
set_source_files_properties(${TX_KERNEL_SETUP_TEST_SOURCE} PROPERTIES GENERATED TRUE)
set(TX_REGRESSION_CASES set(TX_REGRESSION_CASES
${TX_REGRESSION_DIR}/threadx_block_memory_basic_test.c ${TX_REGRESSION_DIR}/threadx_block_memory_basic_test.c
${TX_REGRESSION_DIR}/threadx_block_memory_error_detection_test.c ${TX_REGRESSION_DIR}/threadx_block_memory_error_detection_test.c
@@ -118,7 +195,7 @@ set(TX_REGRESSION_CASES
${TX_REGRESSION_DIR}/threadx_timer_multiple_test.c ${TX_REGRESSION_DIR}/threadx_timer_multiple_test.c
${TX_REGRESSION_DIR}/threadx_timer_simple_test.c ${TX_REGRESSION_DIR}/threadx_timer_simple_test.c
${TX_REGRESSION_DIR}/threadx_trace_basic_test.c ${TX_REGRESSION_DIR}/threadx_trace_basic_test.c
${TX_KERNEL_SETUP_TEST_SOURCE} ${TX_REGRESSION_DIR}/threadx_initialize_kernel_setup_test.c
) )
set(TX_REGRESSION_TARGETS) set(TX_REGRESSION_TARGETS)
@@ -153,33 +230,17 @@ function(add_threadx_regression_test TEST_SOURCE)
SOURCES ${TEST_SOURCE} SOURCES ${TEST_SOURCE}
) )
if(TEST_NAME STREQUAL "threadx_initialize_kernel_setup_test")
add_dependencies(${TEST_NAME} threadx_regression_generated_kernel_setup_test)
endif()
list(APPEND TX_REGRESSION_TARGETS ${TEST_NAME}) list(APPEND TX_REGRESSION_TARGETS ${TEST_NAME})
set(TX_REGRESSION_TARGETS ${TX_REGRESSION_TARGETS} PARENT_SCOPE) set(TX_REGRESSION_TARGETS ${TX_REGRESSION_TARGETS} PARENT_SCOPE)
if(TEST_NAME STREQUAL "threadx_initialize_kernel_setup_test")
add_test( add_test(
NAME ${TEST_NAME} NAME ${TEST_NAME}
COMMAND ${CMAKE_CURRENT_LIST_DIR}/run_threadx_simple_test.sh COMMAND ${THREADX_TEST_SIMULATOR}
${THREADX_TEST_SIMULATOR} --isa=${THREADX_TEST_ISA}
${THREADX_TEST_ISA} -f $<TARGET_FILE:${TEST_NAME}>
$<TARGET_FILE:${TEST_NAME}> -m 60s
"Running Initialize Kernel Setup Test................................ SUCCESS!"
"Running Initialize Kernel Setup Test................................ ERROR!"
) )
else() set_tests_properties(${TEST_NAME} PROPERTIES TIMEOUT 60)
add_test(
NAME ${TEST_NAME}
COMMAND ${CMAKE_CURRENT_LIST_DIR}/run_threadx_test.sh
${THREADX_TEST_SIMULATOR}
${THREADX_TEST_ISA}
$<TARGET_FILE:${TEST_NAME}>
)
endif()
set_tests_properties(${TEST_NAME} PROPERTIES TIMEOUT 10)
endfunction() endfunction()
foreach(test_case ${TX_REGRESSION_CASES}) foreach(test_case ${TX_REGRESSION_CASES})
+72
View File
@@ -0,0 +1,72 @@
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 24,
"patch": 0
},
"configurePresets": [
{
"name": "Debug",
"binaryDir": "${sourceDir}/../../build/${presetName}/test/threadx",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../../cmake/rv64imac_gnu.cmake",
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "Debug32",
"binaryDir": "${sourceDir}/../../build/${presetName}/test/threadx",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../../cmake/rv32imac_gnu.cmake",
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "Release",
"binaryDir": "${sourceDir}/../../build/${presetName}/test/threadx",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../../cmake/rv64imac_gnu.cmake",
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "Release32",
"binaryDir": "${sourceDir}/../../build/${presetName}/test/threadx",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../../cmake/rv32imac_gnu.cmake",
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "MinSizeRel",
"binaryDir": "${sourceDir}/../../build/${presetName}/test/threadx",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../../cmake/rv64imac_gnu.cmake",
"CMAKE_BUILD_TYPE": "MinSizeRel",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "MinSizeRel32",
"binaryDir": "${sourceDir}/../../build/${presetName}/test/threadx",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../../cmake/rv32imac_gnu.cmake",
"CMAKE_BUILD_TYPE": "MinSizeRel",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
}
],
"buildPresets": [
{ "name": "Debug", "configurePreset": "Debug" },
{ "name": "Debug32", "configurePreset": "Debug32" },
{ "name": "Release", "configurePreset": "Release" },
{ "name": "Release32", "configurePreset": "Release32" },
{ "name": "MinSizeRel", "configurePreset": "MinSizeRel" },
{ "name": "MinSizeRel32", "configurePreset": "MinSizeRel32" }
]
}
@@ -1,16 +0,0 @@
#!/bin/bash
set -eu
src="$1"
dst="$2"
anchor='void tx_application_define(void *first_unused_memory){}'
line=$(grep -n -F "$anchor" "$src" | head -n 1 | cut -d: -f1)
if [ -z "$line" ]; then
echo "failed to find tx_application_define anchor in kernel setup test source" >&2
exit 1
fi
mkdir -p "$(dirname "$dst")"
sed "${line}a\\
void test_interrupt_dispatch(void){}" "$src" > "$dst"
+3 -3
View File
@@ -12,15 +12,15 @@ tmp1="${dst}.tmp1"
line=$(grep -n -F "$extern_anchor" "$src" | head -n 1 | cut -d: -f1) line=$(grep -n -F "$extern_anchor" "$src" | head -n 1 | cut -d: -f1)
if [ -z "$line" ]; then if [ -z "$line" ]; then
echo "failed to find _tx_timer_interrupt declaration anchor in trap source" >&2 echo "failed to find _tx_timer_interrupt declaration anchor in input source" >&2
exit 1 exit 1
fi fi
sed "${line}a\\ sed "${line}a\\
extern void test_interrupt_dispatch(void);" "$src" > "$tmp1" void test_interrupt_dispatch(void) __attribute__((weak));\nvoid test_interrupt_dispatch(void) {}" "$src" > "$tmp1"
line=$(grep -n -F "$call_anchor" "$tmp1" | head -n 1 | cut -d: -f1) line=$(grep -n -F "$call_anchor" "$tmp1" | head -n 1 | cut -d: -f1)
if [ -z "$line" ]; then if [ -z "$line" ]; then
echo "failed to find _tx_timer_interrupt call anchor in trap source" >&2 echo "failed to find _tx_timer_interrupt call anchor in input source" >&2
rm -f "$tmp1" rm -f "$tmp1"
exit 1 exit 1
fi fi
-40
View File
@@ -1,40 +0,0 @@
#!/bin/bash
set -euo pipefail
simulator="$1"
isa="$2"
elf="$3"
pass_pattern="$4"
fail_pattern="$5"
if [ ! -x "$simulator" ]; then
echo "Simulator not found or not executable: $simulator" >&2
exit 2
fi
if [ ! -f "$elf" ]; then
echo "ELF not found: $elf" >&2
exit 2
fi
log_file=$(mktemp)
trap 'rm -f "$log_file"' EXIT
"$simulator" \
--isa="$isa" \
-f "$elf" \
-p tb.top.core.finish_condition=1 \
-m 10s \
| tee "$log_file"
if grep -Fq "$fail_pattern" "$log_file"; then
echo "ThreadX regression reported failure pattern: $fail_pattern" >&2
exit 1
fi
if ! grep -Fq "$pass_pattern" "$log_file"; then
echo "Missing expected success pattern in simulator output: $pass_pattern" >&2
exit 1
fi
exit 0
-47
View File
@@ -1,47 +0,0 @@
#!/bin/bash
set -euo pipefail
simulator="$1"
isa="$2"
elf="$3"
if [ ! -x "$simulator" ]; then
echo "Simulator not found or not executable: $simulator" >&2
exit 2
fi
if [ ! -f "$elf" ]; then
echo "ELF not found: $elf" >&2
exit 2
fi
log_file=$(mktemp)
trap 'rm -f "$log_file"' EXIT
"$simulator" \
--isa="$isa" \
-f "$elf" \
-m 10s \
| tee "$log_file"
summary_line=$(grep -F "**** Test Summary:" "$log_file" | tail -n 1 || true)
if [ -z "$summary_line" ]; then
echo "Missing ThreadX test summary in simulator output" >&2
exit 1
fi
read -r passed failed errors <<EOF_SUMMARY
$(echo "$summary_line" | sed -n 's/.*Tests Passed:[[:space:]]*\([0-9][0-9]*\)[[:space:]]*Tests Failed:[[:space:]]*\([0-9][0-9]*\)[[:space:]]*System Errors:[[:space:]]*\([0-9][0-9]*\).*/\1 \2 \3/p')
EOF_SUMMARY
if [ -z "${passed:-}" ] || [ -z "${failed:-}" ] || [ -z "${errors:-}" ]; then
echo "Could not parse ThreadX test summary: $summary_line" >&2
exit 1
fi
if [ "$failed" -ne 0 ] || [ "$errors" -ne 0 ]; then
echo "ThreadX regression reported failure: passed=$passed failed=$failed errors=$errors" >&2
exit 1
fi
exit 0