Compare commits

...

45 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
52 changed files with 1125 additions and 702 deletions
+13 -26
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 PLATFORM_TARGET)
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,16 +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}
) )
if(ST_PLATFORM_TARGET)
target_add_moonlight_platform(${TARGET} PLATFORM_TARGET ${ST_PLATFORM_TARGET})
else()
target_add_moonlight_platform(${TARGET})
endif()
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()
@@ -70,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
@@ -86,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 PLATFORM_TARGET moonlight_platform_common_smp 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
+30 -80
View File
@@ -1,91 +1,41 @@
set(MOONLIGHT_ROOT ${CMAKE_CURRENT_LIST_DIR}) cmake_minimum_required(VERSION 3.21)
set(THREADX4TGFS_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..) project(moonlight LANGUAGES C)
set(MOONLIGHT_SRC_DIR ${MOONLIGHT_ROOT}/src)
set(MOONLIGHT_INC_DIR ${MOONLIGHT_ROOT}/inc)
if(NOT DEFINED MOONLIGHT_TRAP_SOURCE) # Hook to use vectored traps, also used in regression testing
set(MOONLIGHT_ROOT ${CMAKE_CURRENT_LIST_DIR})
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)
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}
)
# define a basic library containing all generic board components target_include_directories(moonlight PUBLIC ${MOONLIGHT_INC_DIR})
add_library(moonlight_platform_defaults INTERFACE) target_link_directories(moonlight INTERFACE ${MOONLIGHT_LDS_DIR})
target_include_directories(moonlight_platform_defaults INTERFACE
${MOONLIGHT_INC_DIR} target_compile_options(moonlight
${THREADX4TGFS_ROOT}/src) PUBLIC
target_compile_options(moonlight_platform_defaults INTERFACE
-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()
# helper to tie in different threadx runtimes target_link_options(moonlight
function(moonlight_define_platform TARGET THREADX_TARGET) INTERFACE
add_library(${TARGET} OBJECT -nostartfiles
${MOONLIGHT_PLATFORM_SOURCES}) -T ${MOONLIGHT_LDS_DIR}/${TARGET_MEM}.lds
target_link_libraries(${TARGET} PUBLIC -Wl,--gc-sections
moonlight_platform_defaults )
c
${THREADX_TARGET})
endfunction()
if(TARGET threadx)
moonlight_define_platform(moonlight_platform_common threadx)
endif()
if(TARGET threadx_smp)
moonlight_define_platform(moonlight_platform_common_smp threadx_smp)
endif()
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()
# helper for consumers to inject moonlight as a dependency into a target
function(target_add_moonlight_platform TARGET)
set(options)
set(oneValueArgs PLATFORM_TARGET)
cmake_parse_arguments(TAMP "${options}" "${oneValueArgs}" "" ${ARGN})
if(TAMP_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "target_add_moonlight_platform(${TARGET} ...): unknown args: ${TAMP_UNPARSED_ARGUMENTS}")
endif()
if(NOT TAMP_PLATFORM_TARGET)
if(NOT TARGET moonlight_platform_common)
message(FATAL_ERROR "moonlight_platform_common is not available in this build; pass PLATFORM_TARGET explicitly")
endif()
set(TAMP_PLATFORM_TARGET moonlight_platform_common)
endif()
target_link_libraries(${TARGET} PRIVATE ${TAMP_PLATFORM_TARGET})
endfunction()
# helper to inject the network driver into a target
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();
+27 -8
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"
@@ -45,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
@@ -61,7 +66,7 @@ void _start(void) {
// The 'norelax' option is critical here. // The 'norelax' option is critical here.
// Without 'norelax' the global pointer will // Without 'norelax' the global pointer will
// be loaded relative to the global pointer! // be loaded relative to the global pointer!
".option norelax;" ".option norelax;"
"la gp, __global_pointer$;" "la gp, __global_pointer$;"
".option pop;" ".option pop;"
"la sp, _sp;" "la sp, _sp;"
@@ -74,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 */
@@ -107,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
@@ -120,6 +127,18 @@ void _initialize(void) {
_exit(rc); _exit(rc);
} }
void _secondary_initialize(void) {
// sleep forever
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. // This should never be called. Report the exit code through HTIF and idle the CPU.
void _exit(int exit_code) { void _exit(int exit_code) {
uintptr_t htif_exit_code = (((uintptr_t)(unsigned int)exit_code) << 1) | 1u; uintptr_t htif_exit_code = (((uintptr_t)(unsigned int)exit_code) << 1) | 1u;
-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
@@ -138,8 +138,7 @@
/* Disable IPv6 processing in NetX Duo. */ /* Disable IPv6 processing in NetX Duo. */
/* /*
#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
+3 -9
View File
@@ -66,9 +66,7 @@
#define LWU lw #define LWU lw
#define LOG_REGBYTES 2 #define LOG_REGBYTES 2
#endif #endif
#define REGBYTES (1 << LOG_REGBYTES) #define REGBYTES (1 << LOG_REGBYTES)
#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,15 +92,12 @@ 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; // ThreadX expects ULONG to be 32 bit 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;
#define ULONG64_DEFINED #define ULONG64_DEFINED
#define ALIGN_TYPE_DEFINED
// Since ULONG is not actually unsigned long, it is to small to hold pointers for 64-bit systems
#define ALIGN_TYPE unsigned long
/* Define the priority levels for ThreadX. Legal values range /* Define the priority levels for ThreadX. Legal values range
from 32 to 1024 and MUST be evenly divisible by 32. */ from 32 to 1024 and MUST be evenly divisible by 32. */
@@ -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:
+9 -20
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,8 +10,16 @@ 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_interrupt_control.S
@@ -31,19 +37,6 @@ set(THREADX_SMP_CUSTOM_SRC
src/tx_timer_interrupt.c src/tx_timer_interrupt.c
) )
threadx_smp_add_offsets(
TARGET threadx_smp_offsets
OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated
SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/tx_asm_offsets.c
INCLUDE_DIRS
${THREADX_COMMON_SMP_DIR}/inc
${THREADX_SMP_CUSTOM_INC}
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/inc/tx_port.h
${THREADX_COMMON_SMP_DIR}/inc/tx_api.h
OUT_INCLUDE_DIR THREADX_SMP_GENERATED_INC_DIR
)
set(THREADX_SMP_SOURCES set(THREADX_SMP_SOURCES
${THREADX_COMMON_SMP_DIR}/src/tx_block_allocate.c ${THREADX_COMMON_SMP_DIR}/src/tx_block_allocate.c
${THREADX_COMMON_SMP_DIR}/src/tx_block_pool_cleanup.c ${THREADX_COMMON_SMP_DIR}/src/tx_block_pool_cleanup.c
@@ -250,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()
+17 -13
View File
@@ -57,22 +57,26 @@
#ifdef __ASSEMBLER__ #ifdef __ASSEMBLER__
#if __riscv_xlen == 64 #if __riscv_xlen == 64
#define SLL32 sllw #define SLL32 sllw
#define STORE sd #define STORE sd
#define LOAD ld #define LOAD ld
#define LWU lwu #define LWU lwu
#define LOG_REGBYTES 3 #define AMOSWAP_AQ amoswap.d.aq
#define AMOSWAP_RL amoswap.d.rl
#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 LOG_REGBYTES 2 #define AMOSWAP_AQ amoswap.w.aq
#define AMOSWAP_RL amoswap.w.rl
#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. *************/
@@ -166,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;
@@ -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 */
+2 -2
View File
@@ -94,7 +94,7 @@ _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
/* } /* }
@@ -115,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 */
+6 -6
View File
@@ -18,23 +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
bnez t4, _protection_busy // If set, protection is busy bnez t4, _protection_busy // If set, protection is busy
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
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,8 +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
amoswap.w.rl x0, x0, (t2) // Release protection flag AMOSWAP_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. */
+18 -28
View File
@@ -37,32 +37,32 @@ set(__THREAD_LOCAL_STORAGE OFF)
add_subdirectory(${THREADX4TGFS_ROOT}/third-party/picolibc ${CMAKE_BINARY_DIR}/picolibc) add_subdirectory(${THREADX4TGFS_ROOT}/third-party/picolibc ${CMAKE_BINARY_DIR}/picolibc)
target_link_libraries(c PUBLIC gcc) target_link_libraries(c PUBLIC gcc)
add_subdirectory(${THREADX4TGFS_ROOT}/port/threadx_smp ${CMAKE_BINARY_DIR}/port/threadx_smp) set(THREADX_LOW_LEVEL_INIT_SOURCE_INPUT
target_link_libraries(threadx_smp PUBLIC c) ${THREADX4TGFS_ROOT}/port/threadx_smp/src/tx_initialize_low_level.c)
target_compile_definitions(threadx_smp PUBLIC TX_REGRESSION_TEST TX_THREAD_SMP_ONLY_CORE_0_DEFAULT TX_SMP_NOT_POSSIBLE) set(THREADX_LOW_LEVEL_INIT_SOURCE
${CMAKE_BINARY_DIR}/generated/tx_initialize_low_level.c)
set(MOONLIGHT_TRAP_SOURCE_INPUT ${THREADX4TGFS_ROOT}/port/moonlight/src/trap_non_vectored.c) set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
set(MOONLIGHT_TRAP_SOURCE ${CMAKE_BINARY_DIR}/generated/trap_non_vectored.c) ${THREADX_LOW_LEVEL_INIT_SOURCE_INPUT}
add_custom_command( ${THREADX4TGFS_ROOT}/test/threadx/generate_trap_file.sh)
OUTPUT ${MOONLIGHT_TRAP_SOURCE} execute_process(
COMMAND bash ${THREADX4TGFS_ROOT}/test/threadx/generate_trap_file.sh COMMAND bash ${THREADX4TGFS_ROOT}/test/threadx/generate_trap_file.sh
${MOONLIGHT_TRAP_SOURCE_INPUT} ${THREADX_LOW_LEVEL_INIT_SOURCE_INPUT}
${MOONLIGHT_TRAP_SOURCE} ${THREADX_LOW_LEVEL_INIT_SOURCE}
DEPENDS ${MOONLIGHT_TRAP_SOURCE_INPUT} RESULT_VARIABLE THREADX_LOW_LEVEL_INIT_GENERATE_RESULT
${THREADX4TGFS_ROOT}/test/threadx/generate_trap_file.sh COMMAND_ERROR_IS_FATAL ANY
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_subdirectory(${THREADX4TGFS_ROOT}/port/moonlight ${CMAKE_BINARY_DIR}/port/moonlight)
add_dependencies(moonlight_platform_common_smp threadx_regression_generated_trap) 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) function(setup_target TARGET)
set(options) set(options)
set(oneValueArgs PLATFORM_TARGET)
set(multiValueArgs LIBRARIES SOURCES) set(multiValueArgs LIBRARIES SOURCES)
cmake_parse_arguments(ST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) cmake_parse_arguments(ST "${options}" "" "${multiValueArgs}" ${ARGN})
if(ST_UNPARSED_ARGUMENTS) if(ST_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "setup_target(${TARGET} ...): unknown args: ${ST_UNPARSED_ARGUMENTS}") message(FATAL_ERROR "setup_target(${TARGET} ...): unknown args: ${ST_UNPARSED_ARGUMENTS}")
endif() endif()
@@ -71,11 +71,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}
) )
if(ST_PLATFORM_TARGET)
target_add_moonlight_platform(${TARGET} PLATFORM_TARGET ${ST_PLATFORM_TARGET})
else()
target_add_moonlight_platform(${TARGET})
endif()
if(ST_SOURCES) if(ST_SOURCES)
target_sources(${TARGET} PRIVATE ${ST_SOURCES}) target_sources(${TARGET} PRIVATE ${ST_SOURCES})
@@ -86,10 +81,6 @@ function(setup_target TARGET)
endif() endif()
target_link_options(${TARGET} PRIVATE target_link_options(${TARGET} PRIVATE
-nostartfiles
-nostdlib
-T ${THREADX4TGFS_ROOT}/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
@@ -246,7 +237,6 @@ function(add_threadx_regression_test TEST_SOURCE)
setup_target( setup_target(
${TEST_NAME} ${TEST_NAME}
PLATFORM_TARGET moonlight_platform_common_smp
LIBRARIES ${test_libraries} LIBRARIES ${test_libraries}
SOURCES ${TEST_SOURCE} SOURCES ${TEST_SOURCE}
) )
+151 -159
View File
@@ -37,33 +37,34 @@ set(__THREAD_LOCAL_STORAGE OFF)
add_subdirectory(${THREADX4TGFS_ROOT}/third-party/picolibc ${CMAKE_BINARY_DIR}/picolibc) add_subdirectory(${THREADX4TGFS_ROOT}/third-party/picolibc ${CMAKE_BINARY_DIR}/picolibc)
target_link_libraries(c PUBLIC gcc) target_link_libraries(c PUBLIC gcc)
set(THREADX_CUSTOM_PORT ${THREADX4TGFS_ROOT}/port/threadx) set(THREADX_LOW_LEVEL_INIT_SOURCE_INPUT
add_subdirectory(${THREADX4TGFS_ROOT}/third-party/threadx ${CMAKE_BINARY_DIR}/threadx) ${THREADX4TGFS_ROOT}/port/threadx/src/tx_initialize_low_level.c)
target_link_libraries(threadx PUBLIC c) set(THREADX_LOW_LEVEL_INIT_SOURCE
target_compile_definitions(threadx PUBLIC TX_REGRESSION_TEST) ${CMAKE_BINARY_DIR}/generated/tx_initialize_low_level.c)
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
set(MOONLIGHT_TRAP_SOURCE_INPUT ${THREADX4TGFS_ROOT}/port/moonlight/src/trap_non_vectored.c) ${THREADX_LOW_LEVEL_INIT_SOURCE_INPUT}
set(MOONLIGHT_TRAP_SOURCE ${CMAKE_BINARY_DIR}/generated/trap_non_vectored.c) ${CMAKE_CURRENT_LIST_DIR}/generate_trap_file.sh)
add_custom_command( execute_process(
OUTPUT ${MOONLIGHT_TRAP_SOURCE}
COMMAND bash ${CMAKE_CURRENT_LIST_DIR}/generate_trap_file.sh COMMAND bash ${CMAKE_CURRENT_LIST_DIR}/generate_trap_file.sh
${MOONLIGHT_TRAP_SOURCE_INPUT} ${THREADX_LOW_LEVEL_INIT_SOURCE_INPUT}
${MOONLIGHT_TRAP_SOURCE} ${THREADX_LOW_LEVEL_INIT_SOURCE}
DEPENDS ${MOONLIGHT_TRAP_SOURCE_INPUT} RESULT_VARIABLE THREADX_LOW_LEVEL_INIT_GENERATE_RESULT
${CMAKE_CURRENT_LIST_DIR}/generate_trap_file.sh COMMAND_ERROR_IS_FATAL ANY
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_subdirectory(${THREADX4TGFS_ROOT}/port/moonlight ${CMAKE_BINARY_DIR}/port/moonlight)
add_dependencies(moonlight_platform_common threadx_regression_generated_trap) 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) function(setup_target TARGET)
set(options) set(options)
set(oneValueArgs PLATFORM_TARGET)
set(multiValueArgs LIBRARIES SOURCES) set(multiValueArgs LIBRARIES SOURCES)
cmake_parse_arguments(ST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) cmake_parse_arguments(ST "${options}" "" "${multiValueArgs}" ${ARGN})
if(ST_UNPARSED_ARGUMENTS) if(ST_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "setup_target(${TARGET} ...): unknown args: ${ST_UNPARSED_ARGUMENTS}") message(FATAL_ERROR "setup_target(${TARGET} ...): unknown args: ${ST_UNPARSED_ARGUMENTS}")
endif() endif()
@@ -72,11 +73,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}
) )
if(ST_PLATFORM_TARGET)
target_add_moonlight_platform(${TARGET} PLATFORM_TARGET ${ST_PLATFORM_TARGET})
else()
target_add_moonlight_platform(${TARGET})
endif()
if(ST_SOURCES) if(ST_SOURCES)
target_sources(${TARGET} PRIVATE ${ST_SOURCES}) target_sources(${TARGET} PRIVATE ${ST_SOURCES})
@@ -87,10 +83,6 @@ function(setup_target TARGET)
endif() endif()
target_link_options(${TARGET} PRIVATE target_link_options(${TARGET} PRIVATE
-nostartfiles
-nostdlib
-T ${THREADX4TGFS_ROOT}/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
@@ -101,161 +93,161 @@ function(setup_target TARGET)
endfunction() 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
) )
set(TX_CMAKE_DIR set(TX_CMAKE_DIR
${THREADX4TGFS_ROOT}/third-party/threadx/test/tx/cmake ${THREADX4TGFS_ROOT}/third-party/threadx/test/tx/cmake
) )
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
${TX_REGRESSION_DIR}/threadx_block_memory_information_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_prioritize_test.c
${TX_REGRESSION_DIR}/threadx_block_memory_suspension_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_suspension_timeout_test.c
${TX_REGRESSION_DIR}/threadx_block_memory_thread_terminate_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_basic_test.c
${TX_REGRESSION_DIR}/threadx_byte_memory_information_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_prioritize_test.c
${TX_REGRESSION_DIR}/threadx_byte_memory_suspension_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_suspension_timeout_test.c
${TX_REGRESSION_DIR}/threadx_byte_memory_thread_contention_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_byte_memory_thread_terminate_test.c
${TX_REGRESSION_DIR}/threadx_event_flag_basic_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_information_test.c
${TX_REGRESSION_DIR}/threadx_event_flag_isr_set_clear_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_isr_wait_abort_test.c
${TX_REGRESSION_DIR}/threadx_event_flag_single_thread_terminate_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_consume_test.c
${TX_REGRESSION_DIR}/threadx_event_flag_suspension_different_bits_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_different_bits_test.c
${TX_REGRESSION_DIR}/threadx_event_flag_suspension_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_suspension_timeout_test.c
${TX_REGRESSION_DIR}/threadx_event_flag_thread_terminate_test.c ${TX_REGRESSION_DIR}/threadx_event_flag_thread_terminate_test.c
${TX_REGRESSION_DIR}/threadx_interrupt_control_test.c ${TX_REGRESSION_DIR}/threadx_interrupt_control_test.c
${TX_REGRESSION_DIR}/threadx_mutex_basic_test.c ${TX_REGRESSION_DIR}/threadx_mutex_basic_test.c
${TX_REGRESSION_DIR}/threadx_mutex_delete_test.c ${TX_REGRESSION_DIR}/threadx_mutex_delete_test.c
${TX_REGRESSION_DIR}/threadx_mutex_information_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_nested_priority_inheritance_test.c
${TX_REGRESSION_DIR}/threadx_mutex_no_preemption_test.c ${TX_REGRESSION_DIR}/threadx_mutex_no_preemption_test.c
${TX_REGRESSION_DIR}/threadx_mutex_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_priority_inheritance_test.c
${TX_REGRESSION_DIR}/threadx_mutex_proritize_test.c ${TX_REGRESSION_DIR}/threadx_mutex_proritize_test.c
${TX_REGRESSION_DIR}/threadx_mutex_suspension_timeout_test.c ${TX_REGRESSION_DIR}/threadx_mutex_suspension_timeout_test.c
${TX_REGRESSION_DIR}/threadx_mutex_thread_terminate_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_eight_word_test.c
${TX_REGRESSION_DIR}/threadx_queue_basic_four_word_test.c ${TX_REGRESSION_DIR}/threadx_queue_basic_four_word_test.c
${TX_REGRESSION_DIR}/threadx_queue_basic_one_word_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_sixteen_word_test.c
${TX_REGRESSION_DIR}/threadx_queue_basic_two_word_test.c ${TX_REGRESSION_DIR}/threadx_queue_basic_two_word_test.c
${TX_REGRESSION_DIR}/threadx_queue_basic_max_message_size_test.c ${TX_REGRESSION_DIR}/threadx_queue_basic_max_message_size_test.c
${TX_REGRESSION_DIR}/threadx_queue_empty_suspension_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_no_suspension_test.c
${TX_REGRESSION_DIR}/threadx_queue_flush_test.c ${TX_REGRESSION_DIR}/threadx_queue_flush_test.c
${TX_REGRESSION_DIR}/threadx_queue_front_send_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_full_suspension_test.c
${TX_REGRESSION_DIR}/threadx_queue_information_test.c ${TX_REGRESSION_DIR}/threadx_queue_information_test.c
${TX_REGRESSION_DIR}/threadx_queue_prioritize.c ${TX_REGRESSION_DIR}/threadx_queue_prioritize.c
${TX_REGRESSION_DIR}/threadx_queue_suspension_timeout_test.c ${TX_REGRESSION_DIR}/threadx_queue_suspension_timeout_test.c
${TX_REGRESSION_DIR}/threadx_queue_thread_terminate_test.c ${TX_REGRESSION_DIR}/threadx_queue_thread_terminate_test.c
${TX_REGRESSION_DIR}/threadx_semaphore_basic_test.c ${TX_REGRESSION_DIR}/threadx_semaphore_basic_test.c
${TX_REGRESSION_DIR}/threadx_semaphore_ceiling_put_test.c ${TX_REGRESSION_DIR}/threadx_semaphore_ceiling_put_test.c
${TX_REGRESSION_DIR}/threadx_semaphore_delete_test.c ${TX_REGRESSION_DIR}/threadx_semaphore_delete_test.c
${TX_REGRESSION_DIR}/threadx_semaphore_information_test.c ${TX_REGRESSION_DIR}/threadx_semaphore_information_test.c
${TX_REGRESSION_DIR}/threadx_semaphore_non_preemption_test.c ${TX_REGRESSION_DIR}/threadx_semaphore_non_preemption_test.c
${TX_REGRESSION_DIR}/threadx_semaphore_preemption_test.c ${TX_REGRESSION_DIR}/threadx_semaphore_preemption_test.c
${TX_REGRESSION_DIR}/threadx_semaphore_prioritize.c ${TX_REGRESSION_DIR}/threadx_semaphore_prioritize.c
${TX_REGRESSION_DIR}/threadx_semaphore_thread_terminate_test.c ${TX_REGRESSION_DIR}/threadx_semaphore_thread_terminate_test.c
${TX_REGRESSION_DIR}/threadx_semaphore_timeout_test.c ${TX_REGRESSION_DIR}/threadx_semaphore_timeout_test.c
${TX_REGRESSION_DIR}/threadx_thread_basic_execution_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_basic_time_slice_test.c
${TX_REGRESSION_DIR}/threadx_thread_completed_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_create_preemption_threshold_test.c
${TX_REGRESSION_DIR}/threadx_thread_delayed_suspension_test.c ${TX_REGRESSION_DIR}/threadx_thread_delayed_suspension_test.c
${TX_REGRESSION_DIR}/threadx_thread_information_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_multi_level_preemption_threshold_test.c
${TX_REGRESSION_DIR}/threadx_thread_multiple_non_current_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_sleep_test.c
${TX_REGRESSION_DIR}/threadx_thread_multiple_suspension_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_multiple_time_slice_test.c
${TX_REGRESSION_DIR}/threadx_thread_preemptable_suspension_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_preemption_change_test.c
${TX_REGRESSION_DIR}/threadx_thread_priority_change.c ${TX_REGRESSION_DIR}/threadx_thread_priority_change.c
${TX_REGRESSION_DIR}/threadx_thread_relinquish_test.c ${TX_REGRESSION_DIR}/threadx_thread_relinquish_test.c
${TX_REGRESSION_DIR}/threadx_thread_reset_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_non_clear_test.c
${TX_REGRESSION_DIR}/threadx_thread_simple_sleep_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_simple_suspend_test.c
${TX_REGRESSION_DIR}/threadx_thread_sleep_for_100ticks_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_sleep_terminate_test.c
${TX_REGRESSION_DIR}/threadx_thread_stack_checking_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_terminate_delete_test.c
${TX_REGRESSION_DIR}/threadx_thread_time_slice_change_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_and_isr_test.c
${TX_REGRESSION_DIR}/threadx_thread_wait_abort_test.c ${TX_REGRESSION_DIR}/threadx_thread_wait_abort_test.c
${TX_REGRESSION_DIR}/threadx_time_get_set_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_activate_deactivate_test.c
${TX_REGRESSION_DIR}/threadx_timer_deactivate_accuracy_test.c ${TX_REGRESSION_DIR}/threadx_timer_deactivate_accuracy_test.c
${TX_REGRESSION_DIR}/threadx_timer_information_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_large_timer_accuracy_test.c
${TX_REGRESSION_DIR}/threadx_timer_multiple_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_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_REGRESSION_DIR}/threadx_initialize_kernel_setup_test.c ${TX_REGRESSION_DIR}/threadx_initialize_kernel_setup_test.c
) )
set(TX_REGRESSION_TARGETS) set(TX_REGRESSION_TARGETS)
add_library( add_library(
threadx_regression_support STATIC threadx_regression_support STATIC
${TX_REGRESSION_DIR}/testcontrol.c ${TX_REGRESSION_DIR}/testcontrol.c
${TX_CMAKE_DIR}/samples/fake.c ${TX_CMAKE_DIR}/samples/fake.c
) )
target_link_libraries(threadx_regression_support PUBLIC threadx c) target_link_libraries(threadx_regression_support PUBLIC threadx c)
target_compile_definitions( target_compile_definitions(
threadx_regression_support threadx_regression_support
PUBLIC PUBLIC
TX_REGRESSION_TEST TX_REGRESSION_TEST
CTEST CTEST
BATCH_TEST BATCH_TEST
TEST_STACK_SIZE_PRINTF=4096 TEST_STACK_SIZE_PRINTF=4096
) )
function(add_threadx_regression_test TEST_SOURCE) function(add_threadx_regression_test TEST_SOURCE)
get_filename_component(TEST_NAME ${TEST_SOURCE} NAME_WE) get_filename_component(TEST_NAME ${TEST_SOURCE} NAME_WE)
if(TEST_NAME STREQUAL "threadx_initialize_kernel_setup_test") if(TEST_NAME STREQUAL "threadx_initialize_kernel_setup_test")
set(test_libraries threadx) set(test_libraries threadx)
else() else()
set(test_libraries threadx_regression_support) set(test_libraries threadx_regression_support)
endif() endif()
setup_target( setup_target(
${TEST_NAME} ${TEST_NAME}
LIBRARIES ${test_libraries} LIBRARIES ${test_libraries}
SOURCES ${TEST_SOURCE} SOURCES ${TEST_SOURCE}
) )
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)
add_test( add_test(
NAME ${TEST_NAME} NAME ${TEST_NAME}
COMMAND ${THREADX_TEST_SIMULATOR} COMMAND ${THREADX_TEST_SIMULATOR}
--isa=${THREADX_TEST_ISA} --isa=${THREADX_TEST_ISA}
-f $<TARGET_FILE:${TEST_NAME}> -f $<TARGET_FILE:${TEST_NAME}>
-m 60s -m 60s
) )
set_tests_properties(${TEST_NAME} PROPERTIES TIMEOUT 60) set_tests_properties(${TEST_NAME} PROPERTIES TIMEOUT 60)
endfunction() endfunction()
foreach(test_case ${TX_REGRESSION_CASES}) foreach(test_case ${TX_REGRESSION_CASES})
add_threadx_regression_test(${test_case}) add_threadx_regression_test(${test_case})
endforeach() endforeach()
add_custom_target( add_custom_target(
threadx_regression_build threadx_regression_build
DEPENDS ${TX_REGRESSION_TARGETS} DEPENDS ${TX_REGRESSION_TARGETS}
) )
+2 -2
View File
@@ -12,7 +12,7 @@ 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\\
@@ -20,7 +20,7 @@ void test_interrupt_dispatch(void) __attribute__((weak));\nvoid test_interrupt_d
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