diff --git a/.github/workflows/ci_cortex_m.yml b/.github/workflows/ci_cortex_m.yml index 933c950fb..7e30d39e4 100644 --- a/.github/workflows/ci_cortex_m.yml +++ b/.github/workflows/ci_cortex_m.yml @@ -34,6 +34,12 @@ on: - 'ports/cortex_m3/gnu/**' - 'ports/cortex_m4/gnu/**' - 'ports/cortex_m7/gnu/**' + - 'ports_module/cortex_m0+/gnu/**' + - 'ports_module/cortex_m3/gnu/**' + - 'ports_module/cortex_m4/gnu/**' + - 'ports_module/cortex_m7/gnu/**' + - 'common_modules/**' + - 'CMakeLists.txt' jobs: build: @@ -111,3 +117,12 @@ jobs: - name: Compile and link run: cmake --build ./build + + - name: Prepare build system (module manager) + run: cmake -Bbuild-mm -DCMAKE_TOOLCHAIN_FILE=./cmake/cortex_m${{ matrix.port }}.cmake -DTHREADX_MODULE_MANAGER=ON -GNinja . + + - name: Compile and link (module manager) + run: | + cmake --build ./build-mm + cmake --build ./build-mm --target threadx-module-manager-consumer-check + diff --git a/CMakeLists.txt b/CMakeLists.txt index 940717df9..05784383a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ if(NOT ((THREADX_ARCH STREQUAL "win32") OR (THREADX_ARCH STREQUAL "win64"))) endif() option(THREADX_SMP "Build ThreadX SMP version" OFF) +option(THREADX_MODULE_MANAGER "Build ThreadX kernel with module manager support" OFF) # Enable testing at the top level so that tests registered by ports and # example builds further down the tree are discoverable with ctest from the @@ -31,7 +32,33 @@ option(THREADX_SMP "Build ThreadX SMP version" OFF) # "ctest --test-dir " reports no tests at all. enable_testing() -if(THREADX_SMP) +if(THREADX_MODULE_MANAGER) + set(TX_PORT_DIR "ports_module") + if(THREADX_SMP) + set(TX_COMMON_DIR "common_smp") + if(THREADX_ARCH MATCHES "_smp$") + set(TX_ARCH_DIR "${THREADX_ARCH}") + else() + set(TX_ARCH_DIR "${THREADX_ARCH}_smp") + endif() + message(STATUS "Building ThreadX module manager SMP version") + else() + set(TX_COMMON_DIR "common") + set(TX_ARCH_DIR "${THREADX_ARCH}") + if(THREADX_ARCH STREQUAL "cortex_m0" AND NOT IS_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/${TX_PORT_DIR}/${TX_ARCH_DIR}") + set(TX_ARCH_DIR "cortex_m0+") + endif() + if(THREADX_ARCH MATCHES "_smp$") + message(FATAL_ERROR "ThreadX module manager SMP port '${THREADX_ARCH}' requires THREADX_SMP=ON") + endif() + message(STATUS "Building ThreadX module manager version") + endif() + + set(TX_PORT_PATH "${CMAKE_CURRENT_LIST_DIR}/${TX_PORT_DIR}/${TX_ARCH_DIR}/${THREADX_TOOLCHAIN}") + if(NOT IS_DIRECTORY "${TX_PORT_PATH}/module_manager/src") + message(FATAL_ERROR "ThreadX module manager is not supported for architecture '${THREADX_ARCH}' with toolchain '${THREADX_TOOLCHAIN}' (SMP=${THREADX_SMP})") + endif() +elseif(THREADX_SMP) set(TX_PORT_DIR "ports_smp") set(TX_COMMON_DIR "common_smp") set(TX_ARCH_DIR "${THREADX_ARCH}_smp") @@ -43,11 +70,13 @@ if(THREADX_SMP) set(TX_ARCH_DIR "${THREADX_ARCH}") endif() message(STATUS "Building ThreadX SMP version") + set(TX_PORT_PATH "${CMAKE_CURRENT_LIST_DIR}/${TX_PORT_DIR}/${TX_ARCH_DIR}/${THREADX_TOOLCHAIN}") else() set(TX_PORT_DIR "ports") set(TX_COMMON_DIR "common") set(TX_ARCH_DIR "${THREADX_ARCH}") message(STATUS "Building standard ThreadX version") + set(TX_PORT_PATH "${CMAKE_CURRENT_LIST_DIR}/${TX_PORT_DIR}/${TX_ARCH_DIR}/${THREADX_TOOLCHAIN}") endif() message(STATUS "THREADX_ARCH: ${THREADX_ARCH}") @@ -63,12 +92,39 @@ set(CUSTOM_INC_DIR ${CMAKE_CURRENT_BINARY_DIR}/custom_inc) # Pick up the port specific variables and apply them if(DEFINED THREADX_CUSTOM_PORT) add_subdirectory(${THREADX_CUSTOM_PORT} threadx_port) +elseif(EXISTS "${TX_PORT_PATH}/CMakeLists.txt") + add_subdirectory(${TX_PORT_PATH}) +elseif(THREADX_MODULE_MANAGER) + file(GLOB TX_PORT_SOURCES + "${TX_PORT_PATH}/module_manager/src/*.c" + "${TX_PORT_PATH}/module_manager/src/*.S" + "${TX_PORT_PATH}/module_manager/src/*.s" + ) + if(THREADX_ARCH STREQUAL "cortex_r52") + file(GLOB TX_R52_BASE_SOURCES + "${CMAKE_CURRENT_LIST_DIR}/ports/cortex_r52/gnu/src/tx_thread_fiq_*.S" + "${CMAKE_CURRENT_LIST_DIR}/ports/cortex_r52/gnu/src/tx_thread_irq_*.S" + "${CMAKE_CURRENT_LIST_DIR}/ports/cortex_r52/gnu/src/tx_thread_interrupt_*.S" + "${CMAKE_CURRENT_LIST_DIR}/ports/cortex_r52/gnu/src/tx_thread_vectored_context_save.S" + "${CMAKE_CURRENT_LIST_DIR}/ports/cortex_r52/gnu/src/tx_timer_interrupt.S" + ) + list(APPEND TX_PORT_SOURCES ${TX_R52_BASE_SOURCES}) + endif() + target_sources(${PROJECT_NAME} PRIVATE ${TX_PORT_SOURCES}) + target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${TX_PORT_PATH}/inc + ) else() - add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/${TX_PORT_DIR}/${TX_ARCH_DIR}/${THREADX_TOOLCHAIN}) + add_subdirectory(${TX_PORT_PATH}) endif() # Pick up the common stuff add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/${TX_COMMON_DIR}) +if(THREADX_MODULE_MANAGER) + add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/common_modules/module_manager) +endif() # Define the FreeRTOS adaptation layer add_library(freertos-threadx EXCLUDE_FROM_ALL) @@ -118,6 +174,9 @@ target_compile_definitions(${PROJECT_NAME} PUBLIC "TX_INCLUDE_USER_DEFINE_FILE" if(THREADX_SMP) target_compile_definitions(${PROJECT_NAME} PUBLIC "TX_MPCORE" ) endif() +if(THREADX_MODULE_MANAGER) + target_compile_definitions(${PROJECT_NAME} PUBLIC "TXM_MODULE_MANAGER" ) +endif() # Optional: build for S-mode (Supervisor mode) instead of M-mode (Machine mode). # Required when running after OpenSBI, e.g. booted from U-Boot. diff --git a/README.md b/README.md index 256162ae4..a12d61c6c 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,17 @@ Instruction for building the ThreadX as static library using Arm GNU Toolchain a $ cmake --build ./build ``` + To build ThreadX with module manager support, enable `THREADX_MODULE_MANAGER`: + + ```bash + $ cmake -Bbuild-mm -GNinja -DCMAKE_TOOLCHAIN_FILE=cmake/cortex_m4.cmake -DTHREADX_MODULE_MANAGER=ON . + + $ cmake --build ./build-mm + ``` + + When enabled, the `azrtos::threadx` target includes the module manager kernel sources and public include headers (`txm_module.h`) for downstream targets. + + ## Licensing License terms for using Eclipse ThreadX are defined in the LICENSE.txt file of this repo. Please refer to this file for all definitive licensing information for all content, incl. the history of this repo. diff --git a/common_modules/module_manager/CMakeLists.txt b/common_modules/module_manager/CMakeLists.txt new file mode 100644 index 000000000..f6dce7a4d --- /dev/null +++ b/common_modules/module_manager/CMakeLists.txt @@ -0,0 +1,47 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT + +target_sources(${PROJECT_NAME} + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_absolute_load.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_absolute_load_extended.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_application_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_callback_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_event_flags_notify_trampoline.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_file_load.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_in_place_load.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_internal_load.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_kernel_dispatch.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_maximum_module_priority_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_memory_load.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_object_allocate.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_object_deallocate.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_object_pointer_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_object_pointer_get_extended.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_object_pool_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_properties_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_queue_notify_trampoline.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_semaphore_notify_trampoline.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_stop.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_thread_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_thread_notify_trampoline.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_thread_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_timer_notify_trampoline.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_unload.c + ${CMAKE_CURRENT_LIST_DIR}/src/txm_module_manager_util.c +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc + ${CMAKE_CURRENT_LIST_DIR}/../inc +) + +# Define consumer check demonstrating compilation against the module-manager API +add_library(threadx-module-manager-consumer-check OBJECT EXCLUDE_FROM_ALL + ${CMAKE_CURRENT_LIST_DIR}/consumer_check.c +) +target_link_libraries(threadx-module-manager-consumer-check PRIVATE azrtos::threadx) diff --git a/common_modules/module_manager/consumer_check.c b/common_modules/module_manager/consumer_check.c new file mode 100644 index 000000000..14be219b0 --- /dev/null +++ b/common_modules/module_manager/consumer_check.c @@ -0,0 +1,51 @@ +/*************************************************************************** + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * 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 + **************************************************************************/ + +#include "tx_api.h" +#include "txm_module.h" + +static TX_THREAD module_manager_thread; +static ULONG module_manager_stack[1024 / sizeof(ULONG)]; +static UCHAR object_memory_pool[16384]; +static UCHAR module_data_area[32768]; +static TXM_MODULE_INSTANCE test_module; + +static VOID test_fault_handler(TX_THREAD *thread, TXM_MODULE_INSTANCE *module) +{ + (VOID) thread; + (VOID) module; +} + +static VOID module_manager_entry(ULONG input) +{ + (VOID) input; + txm_module_manager_initialize((VOID *) module_data_area, sizeof(module_data_area)); + txm_module_manager_object_pool_create(object_memory_pool, sizeof(object_memory_pool)); + txm_module_manager_memory_fault_notify(test_fault_handler); + txm_module_manager_maximum_module_priority_set(&test_module, 5); + txm_module_manager_start(&test_module); + txm_module_manager_stop(&test_module); + txm_module_manager_unload(&test_module); +} + +VOID tx_application_define(VOID *first_unused_memory) +{ + (VOID) first_unused_memory; + tx_thread_create(&module_manager_thread, "Module Manager", + module_manager_entry, 0, + module_manager_stack, sizeof(module_manager_stack), + 1, 1, TX_NO_TIME_SLICE, TX_AUTO_START); +} + +int main(void) +{ + tx_kernel_enter(); + return 0; +}